diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 000000000..d439198c7
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,38 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven and Deploy
+
+on:
+ push:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11 for Maven Central
+ uses: actions/setup-java@v1
+ with:
+ java-version: '11'
+ architecture: x64
+ server-id: ossrh
+ gpg-private-key: ${{ secrets.GPG_SECRET_KEY }}
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_CENTRAL_TOKEN
+ - name: Setup git profile
+ run: |
+ git config --global user.name github-actions
+ git config --global user.email github-actions@github.com
+ - name: Publish Snapshot to Maven Central
+ run: mvn deploy -B -Possrh
+ env:
+ MAVEN_USERNAME: hap-java-dev
+ MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ - name: Publish site
+ run: mvn -B site-deploy -Dusername=github-actions -Dpassword=${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 000000000..a07bff253
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,23 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: '11'
+ architecture: x64
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 000000000..0aa72794f
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,39 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Stage Release on Master Branch
+
+on:
+ workflow_dispatch:
+ inputs:
+ releaseVersion:
+ description: Version to release
+ required: true
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: '11'
+ architecture: x64
+ server-id: ossrh
+ gpg-private-key: ${{ secrets.GPG_SECRET_KEY }}
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_CENTRAL_TOKEN
+ - name: Setup git profile
+ run: |
+ git config user.name github-actions
+ git config user.email github-actions@github.com
+ - name: Maven release
+ run: mvn release:prepare release:perform -B -DreleaseVersion=${{ github.event.inputs.releaseVersion }} -Possrh
+ env:
+ MAVEN_USERNAME: hap-java-dev
+ MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
diff --git a/CHANGES.md b/CHANGES.md
index 758ddf6f7..73ecb18af 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -14,6 +14,11 @@
* Valid values are supported for enum characteristics instead of min and max values
* Supported valid states for Thermostat, SecuritySystem, HeaterCooler and HumidifierDehumidifier [#108] [#120](https://github.com/hap-java/HAP-Java/pull/120)
* Support for FilterMaintenance. Can be used as a linked service for an Air Purifier [#124](https://github.com/hap-java/HAP-Java/pull/124)
+* Update crypto libs [#130](https://github.com/hap-java/HAP-Java/pull/130)
+
+## Fixes
+
+* Fix for re-advertising service when using alternative jMDNS implementations.
# HAP-Java 1.1.5
diff --git a/README.md b/README.md
index 463f5d49b..03fb0aaba 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
HAP-Java
=========
+[](https://search.maven.org/search?q=g:io.github.hap-java%20a:hap)
+[](https://github.com/hap-java/HAP-Java/blob/master/LICENSE)
+
+
HAP-Java is a Java implementation of the HomeKit Accessory Protocol.
Using this library, you can create your own HomeKit Accessory or HomeKit Accessory Bridge.
@@ -18,7 +22,8 @@ Include HAP-Java in your project using maven:
```
-After that, check out the [Sample](https://github.com/hap-java/HAP-Java/tree/sample).
+After that, check out the [Sample](https://github.com/hap-java/HAP-Java/tree/sample) and
+read the [Javadoc](https://hap-java.github.io/HAP-Java/apidocs/index.html)
Supported HomeKit Accessories
=========
diff --git a/RELEASING.md b/RELEASING.md
new file mode 100644
index 000000000..a3001c9f3
--- /dev/null
+++ b/RELEASING.md
@@ -0,0 +1,7 @@
+# How to release HAP-Java
+
+These actions can only be performed by someone with maintainer level access to the repository.
+
+1. Run the [Stage Release on Master Branch](https://github.com/hap-java/HAP-Java/actions/workflows/release.yml) Action
+2. After this completes, find the release on the [Releases page](https://github.com/hap-java/HAP-Java/releases)
+3. Edit the release to include the changelog details
diff --git a/deploy/distribution.xml b/deploy/distribution.xml
deleted file mode 100644
index a2cf6d668..000000000
--- a/deploy/distribution.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
- dir-with-dependencies
-
- dir
-
- false
-
-
- /
- true
- false
- ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.jar
- runtime
-
-
-
\ No newline at end of file
diff --git a/deploy/publish.sh b/deploy/publish.sh
deleted file mode 100755
index 1fb261646..000000000
--- a/deploy/publish.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-if [[ ( $TRAVIS_PULL_REQUEST == "false" && $TRAVIS_BRANCH == "master" ) ]]; then
- mvn deploy --settings deploy/settings.xml -DperformRelease=true -DskipTests=true
- exit $?
-fi
diff --git a/deploy/pubring.gpg.enc b/deploy/pubring.gpg.enc
deleted file mode 100644
index 1361f5a9f..000000000
Binary files a/deploy/pubring.gpg.enc and /dev/null differ
diff --git a/deploy/secring.gpg.enc b/deploy/secring.gpg.enc
deleted file mode 100644
index 1f1c31049..000000000
Binary files a/deploy/secring.gpg.enc and /dev/null differ
diff --git a/deploy/settings.xml b/deploy/settings.xml
deleted file mode 100644
index f08c008c0..000000000
--- a/deploy/settings.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- ossrh
- ${env.SONATYPE_USERNAME}
- ${env.SONATYPE_PASSWORD}
-
-
-
diff --git a/pom.xml b/pom.xml
index 5faf6eafc..8e38a1880 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
scm:git:https://github.com/hap-java/HAP-Java.git
- scm:git:git@github.com:hap-java/HAP-Java.git
+ scm:git:https://github.com/hap-java/HAP-Java.git
https://github.com/hap-java/HAP-Java.git
HEAD
@@ -100,37 +100,31 @@
com.nimbusds
srp6a
- 1.5.2
+ 2.1.0
org.bouncycastle
bcprov-jdk15on
- 1.51
+ 1.69
net.vrallev.ecc
ecc-25519-java
- 1.0.1
-
-
-
- org.zeromq
- curve25519-java
- 0.1.0
+ 1.0.3
javax.json
javax.json-api
- 1.0
+ 1.1.4
org.glassfish
javax.json
- 1.0.4
+ 1.1.4
@@ -148,8 +142,15 @@
org.mockito
- mockito-all
- 1.10.19
+ mockito-core
+ 3.8.0
+ test
+
+
+
+ org.assertj
+ assertj-core
+ 3.19.0
test
@@ -208,28 +209,10 @@
-
- maven-assembly-plugin
- 3.1.1
-
-
- deploy/distribution.xml
-
-
-
-
- make-assembly
- package
-
- single
-
-
-
-
org.apache.maven.plugins
maven-scm-publish-plugin
- 3.0.0
+ 3.1.0
scm-publish
@@ -238,7 +221,7 @@
publish-scm
- scm:git:git@github.com:hap-java/HAP-Java.git
+ scm:git:https://github.com/hap-java/HAP-Java.git
gh-pages
@@ -284,11 +267,11 @@
ossrh
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
+ https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
ossrh
- https://oss.sonatype.org/content/repositories/snapshots
+ https://s01.oss.sonatype.org/content/repositories/snapshots
@@ -305,6 +288,8 @@
3.0.1
io.github.hapjava.server.impl
+ 8
+ false
@@ -325,20 +310,6 @@
ossrh
-
- gpg
- ${env.GPG_KEYNAME}
- ${env.GPG_PASSPHRASE}
- false
- deploy/pubring.gpg
- deploy/secring.gpg
-
-
-
- performRelease
- true
-
-
@@ -354,6 +325,13 @@
+
+ HAP-Java
+
+ --pinentry-mode
+ loopback
+
+
org.sonatype.plugins
@@ -362,17 +340,12 @@
true
ossrh
- https://oss.sonatype.org/
+ https://s01.oss.sonatype.org/
true
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.5.3
-
-
+
diff --git a/src/main/java/io/github/hapjava/accessories/LightSensorAccessory.java b/src/main/java/io/github/hapjava/accessories/LightSensorAccessory.java
index bcdab09c4..2087b1e99 100644
--- a/src/main/java/io/github/hapjava/accessories/LightSensorAccessory.java
+++ b/src/main/java/io/github/hapjava/accessories/LightSensorAccessory.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.lightsensor.CurrentAmbientLightLevelCharacteristic;
import io.github.hapjava.services.Service;
import io.github.hapjava.services.impl.LightSensorService;
import java.util.Collection;
@@ -31,6 +32,36 @@ public interface LightSensorAccessory extends HomekitAccessory {
/** Unsubscribes from changes in the current ambient light level. */
void unsubscribeCurrentAmbientLightLevel();
+ /**
+ * return the min value for current ambient light level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min current ambient light level
+ */
+ default double getMinCurrentAmbientLightLevel() {
+ return CurrentAmbientLightLevelCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for current ambient light level. overwrite if you want to change the
+ * default value.
+ *
+ * @return max current ambient light level
+ */
+ default double getMaxCurrentAmbientLightLevel() {
+ return CurrentAmbientLightLevelCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for current ambient light level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step current ambient light level
+ */
+ default double getMinStepCurrentAmbientLightLevel() {
+ return CurrentAmbientLightLevelCharacteristic.DEFAULT_STEP;
+ }
+
@Override
default Collection getServices() {
return Collections.singleton(new LightSensorService(this));
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonDioxideLevel.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonDioxideLevel.java
index bd4bb3afc..bd143b22f 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonDioxideLevel.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonDioxideLevel.java
@@ -1,6 +1,8 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxideLevelCharacteristic;
+import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxidePeakLevelCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with carbon dioxide level and peak level characteristic. */
@@ -20,6 +22,66 @@ public interface AccessoryWithCarbonDioxideLevel {
*/
CompletableFuture getCarbonDioxideLevel();
+ /**
+ * return the min value for carbon dioxide level. overwrite if you want to change the default
+ * value.
+ *
+ * @return min carbon dioxide level
+ */
+ default double getMinCarbonDioxideLevel() {
+ return CarbonDioxideLevelCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for carbon dioxide level. overwrite if you want to change the default
+ * value.
+ *
+ * @return max carbon dioxide level
+ */
+ default double getMaxCarbonDioxideLevel() {
+ return CarbonDioxideLevelCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for carbon dioxide level. overwrite if you want to change the default
+ * value.
+ *
+ * @return min step carbon dioxide level
+ */
+ default double getMinStepCarbonDioxideLevel() {
+ return CarbonDioxideLevelCharacteristic.DEFAULT_STEP;
+ }
+
+ /**
+ * return the min value for carbon dioxide peak level. overwrite if you want to change the default
+ * value.
+ *
+ * @return min carbon dioxide peak level
+ */
+ default double getMinCarbonDioxidePeakLevel() {
+ return CarbonDioxidePeakLevelCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for carbon dioxide peak level. overwrite if you want to change the default
+ * value.
+ *
+ * @return max carbon dioxide peak level
+ */
+ default double getMaxCarbonDioxidePeakLevel() {
+ return CarbonDioxidePeakLevelCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for carbon dioxide peak level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step carbon dioxide peak level
+ */
+ default double getMinStepCarbonDioxidePeakLevel() {
+ return CarbonDioxidePeakLevelCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in the carbon dioxide level.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonMonoxideLevel.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonMonoxideLevel.java
index a3946c40b..cbccd9647 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonMonoxideLevel.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithCarbonMonoxideLevel.java
@@ -1,9 +1,11 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxideLevelCharacteristic;
+import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxidePeakLevelCharacteristic;
import java.util.concurrent.CompletableFuture;
-/** Accessory with carbon dioxide level and peak level characteristic. */
+/** Accessory with carbon monoxide level and peak level characteristic. */
public interface AccessoryWithCarbonMonoxideLevel {
/**
@@ -20,6 +22,66 @@ public interface AccessoryWithCarbonMonoxideLevel {
*/
CompletableFuture getCarbonMonoxideLevel();
+ /**
+ * return the min value for carbon monoxide level. overwrite if you want to change the default
+ * value.
+ *
+ * @return min carbon monoxide level
+ */
+ default double getMinCarbonMonoxideLevel() {
+ return CarbonMonoxideLevelCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for carbon monoxide level. overwrite if you want to change the default
+ * value.
+ *
+ * @return max carbon monoxide level
+ */
+ default double getMaxCarbonMonoxideLevel() {
+ return CarbonMonoxideLevelCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for carbon monoxide level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step carbon monoxide level
+ */
+ default double getMinStepCarbonMonoxideLevel() {
+ return CarbonMonoxideLevelCharacteristic.DEFAULT_STEP;
+ }
+
+ /**
+ * return the min value for carbon monoxide peak level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min carbon monoxide peak level
+ */
+ default double getMinCarbonMonoxidePeakLevel() {
+ return CarbonMonoxidePeakLevelCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for carbon monoxide peak level. overwrite if you want to change the
+ * default value.
+ *
+ * @return max carbon monoxide peak level
+ */
+ default double getMaxCarbonMonoxidePeakLevel() {
+ return CarbonMonoxidePeakLevelCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for carbon monoxide peak level. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step carbon monoxide peak level
+ */
+ default double getMinStepCarbonMonoxidePeakLevel() {
+ return CarbonMonoxidePeakLevelCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in the carbon monoxide level.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithColorTemperature.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithColorTemperature.java
index fee36884d..ecf74ba63 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithColorTemperature.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithColorTemperature.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.lightbulb.ColorTemperatureCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with color temperature. */
@@ -22,6 +23,24 @@ public interface AccessoryWithColorTemperature {
*/
CompletableFuture setColorTemperature(Integer value) throws Exception;
+ /**
+ * return the min value for color temperature. overwrite if you want to change the default value.
+ *
+ * @return min color temperature
+ */
+ default int getMinColorTemperature() {
+ return ColorTemperatureCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for color temperature. overwrite if you want to change the default value.
+ *
+ * @return max color temperature
+ */
+ default int getMaxColorTemperature() {
+ return ColorTemperatureCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
/**
* Subscribes to changes in color temperature.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithDuration.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithDuration.java
index e3d310dfd..a5cebf97c 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithDuration.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithDuration.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.valve.SetDurationCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with duration characteristic. */
@@ -13,6 +14,24 @@ public interface AccessoryWithDuration {
*/
CompletableFuture getSetDuration();
+ /**
+ * return the min value for duration. overwrite if you want to change the default value.
+ *
+ * @return min remaining duration
+ */
+ default int getMinDuration() {
+ return SetDurationCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for duration. overwrite if you want to change the default value.
+ *
+ * @return max duration
+ */
+ default int getMaxDuration() {
+ return SetDurationCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
/**
* Sets the duration for which the service should run.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithNitrogenDioxideDensity.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithNitrogenDioxideDensity.java
index 685edfb5c..6aead4f98 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithNitrogenDioxideDensity.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithNitrogenDioxideDensity.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.NitrogenDioxideDensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with nitrogen dioxide density characteristic. */
@@ -13,6 +14,36 @@ public interface AccessoryWithNitrogenDioxideDensity {
*/
CompletableFuture getNitrogenDioxideDensity();
+ /**
+ * return the min value for nitrogen dioxide density. overwrite if you want to change the default
+ * value.
+ *
+ * @return min nitrogen dioxide density
+ */
+ default double getMinNitrogenDioxideDensity() {
+ return NitrogenDioxideDensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for nitrogen dioxide density. overwrite if you want to change the default
+ * value.
+ *
+ * @return max nitrogen dioxide density
+ */
+ default double getMaxNitrogenDioxideDensity() {
+ return NitrogenDioxideDensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for nitrogen dioxide density. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step nitrogen dioxide density
+ */
+ default double getMinStepNitrogenDioxideDensity() {
+ return NitrogenDioxideDensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in nitrogen dioxide density.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithOzoneDensity.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithOzoneDensity.java
index 87bb8fa74..efba2a49f 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithOzoneDensity.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithOzoneDensity.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.OzoneDensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with Ozone Density characteristic. */
@@ -13,6 +14,33 @@ public interface AccessoryWithOzoneDensity {
*/
CompletableFuture getOzoneDensity();
+ /**
+ * return the min value for ozone density. overwrite if you want to change the default value.
+ *
+ * @return min ozone density
+ */
+ default double getMinOzoneDensity() {
+ return OzoneDensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for ozone density. overwrite if you want to change the default value.
+ *
+ * @return max ozone density
+ */
+ default double getMaxOzoneDensity() {
+ return OzoneDensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for ozone density. overwrite if you want to change the default value.
+ *
+ * @return min step ozone density
+ */
+ default double getMinStepOzoneDensity() {
+ return OzoneDensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in ozone density.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM10Density.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM10Density.java
index 2bfad14ac..2ae3cded0 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM10Density.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM10Density.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.PM10DensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with PM10 Density characteristic. */
@@ -13,6 +14,33 @@ public interface AccessoryWithPM10Density {
*/
CompletableFuture getPM10Density();
+ /**
+ * return the min value for PM10 density. overwrite if you want to change the default value.
+ *
+ * @return min PM10 density
+ */
+ default double getMinPM10Density() {
+ return PM10DensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for PM10 density. overwrite if you want to change the default value.
+ *
+ * @return max PM10 density
+ */
+ default double getMaxPM10Density() {
+ return PM10DensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for PM10 density. overwrite if you want to change the default value.
+ *
+ * @return min step PM10 density
+ */
+ default double getMinStepPM10Density() {
+ return PM10DensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in PM10 density.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM25Density.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM25Density.java
index 11ad2a12e..02488f52d 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM25Density.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithPM25Density.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.PM25DensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with PM25 Density characteristic. */
@@ -13,6 +14,33 @@ public interface AccessoryWithPM25Density {
*/
CompletableFuture getPM25Density();
+ /**
+ * return the min value for PM25 density. overwrite if you want to change the default value.
+ *
+ * @return min PM25 density
+ */
+ default double getMinPM25Density() {
+ return PM25DensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for PM25 density. overwrite if you want to change the default value.
+ *
+ * @return max PM25 density
+ */
+ default double getMaxPM25Density() {
+ return PM25DensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for PM25 density. overwrite if you want to change the default value.
+ *
+ * @return min step PM25 density
+ */
+ default double getMinStepPM25Density() {
+ return PM25DensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in PM25 density.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithRemainingDuration.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithRemainingDuration.java
index b949b413e..7859fb396 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithRemainingDuration.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithRemainingDuration.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.valve.RemainingDurationCharacteristic;
import java.util.concurrent.CompletableFuture;
/**
@@ -17,6 +18,24 @@ public interface AccessoryWithRemainingDuration {
*/
CompletableFuture getRemainingDuration();
+ /**
+ * return the min value for remaining duration. overwrite if you want to change the default value.
+ *
+ * @return min remaining duration
+ */
+ default int getMinRemainingDuration() {
+ return RemainingDurationCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for remaining duration. overwrite if you want to change the default value.
+ *
+ * @return max remaining duration
+ */
+ default int getMaxRemainingDuration() {
+ return RemainingDurationCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
/**
* Subscribes to changes in the duration; note it is not necessary to emit a change every second,
* homekit infers the countdown progress client side.
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithSulphurDioxideDensity.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithSulphurDioxideDensity.java
index 94fad0be4..dbe0cc947 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithSulphurDioxideDensity.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithSulphurDioxideDensity.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.SulphurDioxideDensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with sulphur dioxide density characteristic. */
@@ -13,6 +14,36 @@ public interface AccessoryWithSulphurDioxideDensity {
*/
CompletableFuture getSulphurDioxideDensity();
+ /**
+ * return the min value for sulphur dioxide density. overwrite if you want to change the default
+ * value.
+ *
+ * @return min sulphur dioxide density
+ */
+ default double getMinSulphurDioxideDensity() {
+ return SulphurDioxideDensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for sulphur dioxide density. overwrite if you want to change the default
+ * value.
+ *
+ * @return max sulphur dioxide density
+ */
+ default double getMaxSulphurDioxideDensity() {
+ return SulphurDioxideDensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for sulphur dioxide density. overwrite if you want to change the
+ * default value.
+ *
+ * @return min step sulphur dioxide density
+ */
+ default double getMinStepSulphurDioxideDensity() {
+ return SulphurDioxideDensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in sulphur dioxide density.
*
diff --git a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithVOCDensity.java b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithVOCDensity.java
index b41cc43b7..f8a7bc46b 100644
--- a/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithVOCDensity.java
+++ b/src/main/java/io/github/hapjava/accessories/optionalcharacteristic/AccessoryWithVOCDensity.java
@@ -1,6 +1,7 @@
package io.github.hapjava.accessories.optionalcharacteristic;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
+import io.github.hapjava.characteristics.impl.airquality.VOCDensityCharacteristic;
import java.util.concurrent.CompletableFuture;
/** Accessory with VOC Density characteristic. */
@@ -13,6 +14,33 @@ public interface AccessoryWithVOCDensity {
*/
CompletableFuture getVOCDensity();
+ /**
+ * return the min value for VOC density. overwrite if you want to change the default value.
+ *
+ * @return min VOC density
+ */
+ default double getMinVOCDensity() {
+ return VOCDensityCharacteristic.DEFAULT_MIN_VALUE;
+ }
+
+ /**
+ * return the max value for VOC density. overwrite if you want to change the default value.
+ *
+ * @return max VOC density
+ */
+ default double getMaxVOCDensity() {
+ return VOCDensityCharacteristic.DEFAULT_MAX_VALUE;
+ }
+
+ /**
+ * return the min step value for VOC density. overwrite if you want to change the default value.
+ *
+ * @return min step VOC density
+ */
+ default double getMinStepVOCDensity() {
+ return VOCDensityCharacteristic.DEFAULT_STEP;
+ }
+
/**
* Subscribes to changes in VOC density.
*
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/NitrogenDioxideDensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/NitrogenDioxideDensityCharacteristic.java
index 432a85029..1e37e28b6 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/NitrogenDioxideDensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/NitrogenDioxideDensityCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic contains the current NO2 density in micrograms/m3. */
public class NitrogenDioxideDensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public NitrogenDioxideDensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C4-0000-1000-8000-0026BB765291",
"nitrogen dioxide density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public NitrogenDioxideDensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/OzoneDensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/OzoneDensityCharacteristic.java
index 542dbce0b..577339288 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/OzoneDensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/OzoneDensityCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic contains the current ozone density in micrograms/m3. */
public class OzoneDensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public OzoneDensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C3-0000-1000-8000-0026BB765291",
"ozone density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public OzoneDensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM10DensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM10DensityCharacteristic.java
index fdb0b9b49..a7b9c1245 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM10DensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM10DensityCharacteristic.java
@@ -11,21 +11,34 @@
* This characteristic contains the current PM10 micrometer particulate density in micrograms/m3.
*/
public class PM10DensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public PM10DensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C7-0000-1000-8000-0026BB765291",
"PM10 density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public PM10DensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM25DensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM25DensityCharacteristic.java
index c54831553..1667934ef 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM25DensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/PM25DensityCharacteristic.java
@@ -11,21 +11,34 @@
* This characteristic contains the current PM2.5 micrometer particulate density in micrograms/m3.
*/
public class PM25DensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public PM25DensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C6-0000-1000-8000-0026BB765291",
"PM2.5 density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public PM25DensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/SulphurDioxideDensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/SulphurDioxideDensityCharacteristic.java
index 03f668757..81df2c64b 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/SulphurDioxideDensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/SulphurDioxideDensityCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic contains the current SO2 density in micrograms/m3. */
public class SulphurDioxideDensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public SulphurDioxideDensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C5-0000-1000-8000-0026BB765291",
"sulphur dioxide density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public SulphurDioxideDensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/airquality/VOCDensityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/airquality/VOCDensityCharacteristic.java
index 76e062f45..a752161c9 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/airquality/VOCDensityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/airquality/VOCDensityCharacteristic.java
@@ -12,21 +12,34 @@
* micrograms/m3.
*/
public class VOCDensityCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 1000;
+ public static final double DEFAULT_STEP = 1;
public VOCDensityCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000C8-0000-1000-8000-0026BB765291",
"VOC density",
- 0,
- 1000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"micrograms",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public VOCDensityCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/base/BaseCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/base/BaseCharacteristic.java
index 73ce32df4..a90f1fadc 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/base/BaseCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/base/BaseCharacteristic.java
@@ -113,7 +113,6 @@ protected CompletableFuture makeBuilder(int instanceId) {
.add("type", shortType)
.add("perms", perms.build())
.add("format", format)
- .add("ev", false)
.add("description", description);
if (isReadable) setJsonValue(builder, value);
return builder;
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxideLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxideLevelCharacteristic.java
index 7d1d8d440..b9b320564 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxideLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxideLevelCharacteristic.java
@@ -11,21 +11,34 @@
* This characteristic indicates the detected level of Carbon Dioxide in parts per million (ppm).
*/
public class CarbonDioxideLevelCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 100000;
+ public static final double DEFAULT_STEP = 1;
public CarbonDioxideLevelCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"00000093-0000-1000-8000-0026BB765291",
"Carbon Dioxide Level",
- 0,
- 100000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"ppm",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public CarbonDioxideLevelCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxidePeakLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxidePeakLevelCharacteristic.java
index a2ad994fc..1a1793773 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxidePeakLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/carbondioxidesensor/CarbonDioxidePeakLevelCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic indicates the highest detected level (ppm) of carbon dioxide. */
public class CarbonDioxidePeakLevelCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 100000;
+ public static final double DEFAULT_STEP = 1;
public CarbonDioxidePeakLevelCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"00000094-0000-1000-8000-0026BB765291",
"Carbon Dioxide Level",
- 0,
- 100000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"ppm",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public CarbonDioxidePeakLevelCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxideLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxideLevelCharacteristic.java
index 554638a22..e35171b38 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxideLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxideLevelCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic contains the Carbon Monoxide levels in parts per million (ppm). */
public class CarbonMonoxideLevelCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 100;
+ public static final double DEFAULT_STEP = 1;
public CarbonMonoxideLevelCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"00000090-0000-1000-8000-0026BB765291",
"Carbon Monoxide Level",
- 0,
- 100,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"ppm",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public CarbonMonoxideLevelCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxidePeakLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxidePeakLevelCharacteristic.java
index 3a714674a..892901866 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxidePeakLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/carbonmonoxidesensor/CarbonMonoxidePeakLevelCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic indicates the highest detected level (ppm) of Carbon Monoxide. */
public class CarbonMonoxidePeakLevelCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0;
+ public static final double DEFAULT_MAX_VALUE = 100;
+ public static final double DEFAULT_STEP = 1;
public CarbonMonoxidePeakLevelCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"00000091-0000-1000-8000-0026BB765291",
"Carbon Monoxide Peak Level",
- 0,
- 100000,
- 1,
+ minValue,
+ maxValue,
+ minStep,
"ppm",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public CarbonMonoxidePeakLevelCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateEnum.java b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateEnum.java
index 9d2b145ab..88474e6cc 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateEnum.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/garagedoor/CurrentDoorStateEnum.java
@@ -15,7 +15,7 @@ public enum CurrentDoorStateEnum implements CharacteristicEnum {
CLOSED(1),
OPENING(2),
CLOSING(3),
- SOPPED(4);
+ STOPPED(4);
private static final Map reverse;
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/ColorTemperatureCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/ColorTemperatureCharacteristic.java
index c7779233a..12886c7a1 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/ColorTemperatureCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/ColorTemperatureCharacteristic.java
@@ -12,8 +12,12 @@
/** This characteristic describes color temperature in Kelvin */
public class ColorTemperatureCharacteristic extends IntegerCharacteristic
implements EventableCharacteristic {
+ public static final int DEFAULT_MIN_VALUE = 50;
+ public static final int DEFAULT_MAX_VALUE = 400;
public ColorTemperatureCharacteristic(
+ int minValue,
+ int maxValue,
Supplier> getter,
ExceptionalConsumer setter,
Consumer subscriber,
@@ -21,12 +25,20 @@ public ColorTemperatureCharacteristic(
super(
"000000CE-0000-1000-8000-0026BB765291",
"color temperature",
- 50,
- 400,
+ minValue,
+ maxValue,
"K",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public ColorTemperatureCharacteristic(
+ Supplier> getter,
+ ExceptionalConsumer setter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, getter, setter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lightsensor/CurrentAmbientLightLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lightsensor/CurrentAmbientLightLevelCharacteristic.java
index aee5e24d5..afec35ce6 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/lightsensor/CurrentAmbientLightLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/lightsensor/CurrentAmbientLightLevelCharacteristic.java
@@ -9,21 +9,34 @@
/** This characteristic indicates the current light level in Lux */
public class CurrentAmbientLightLevelCharacteristic extends FloatCharacteristic {
+ public static final double DEFAULT_MIN_VALUE = 0.0001;
+ public static final double DEFAULT_MAX_VALUE = 100000;
+ public static final double DEFAULT_STEP = 0.0001;
public CurrentAmbientLightLevelCharacteristic(
+ double minValue,
+ double maxValue,
+ double minStep,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"0000006B-0000-1000-8000-0026BB765291",
"ambient light level",
- 0.0001,
- 100000,
- 0.0001,
+ minValue,
+ maxValue,
+ minStep,
"lux",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public CurrentAmbientLightLevelCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEP, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/valve/RemainingDurationCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/valve/RemainingDurationCharacteristic.java
index 4866be230..828fafab1 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/valve/RemainingDurationCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/valve/RemainingDurationCharacteristic.java
@@ -15,20 +15,31 @@
*/
public class RemainingDurationCharacteristic extends IntegerCharacteristic
implements EventableCharacteristic {
+ public static final int DEFAULT_MIN_VALUE = 0;
+ public static final int DEFAULT_MAX_VALUE = 3600;
public RemainingDurationCharacteristic(
+ int minValue,
+ int maxValue,
Supplier> getter,
Consumer subscriber,
Runnable unsubscriber) {
super(
"000000D4-0000-1000-8000-0026BB765291",
"remaining duration",
- 0,
- 3600,
+ minValue,
+ maxValue,
"s",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public RemainingDurationCharacteristic(
+ Supplier> getter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, getter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/valve/SetDurationCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/valve/SetDurationCharacteristic.java
index a372d0515..59cef5646 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/valve/SetDurationCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/valve/SetDurationCharacteristic.java
@@ -12,8 +12,12 @@
/** This characteristic describes the duration, how long an accessory should be set to "InUse". */
public class SetDurationCharacteristic extends IntegerCharacteristic
implements EventableCharacteristic {
+ public static final int DEFAULT_MIN_VALUE = 0;
+ public static final int DEFAULT_MAX_VALUE = 3600;
public SetDurationCharacteristic(
+ int minValue,
+ int maxValue,
Supplier> getter,
ExceptionalConsumer setter,
Consumer subscriber,
@@ -21,12 +25,20 @@ public SetDurationCharacteristic(
super(
"000000D3-0000-1000-8000-0026BB765291",
"set duration",
- 0,
- 3600,
+ minValue,
+ maxValue,
"s",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
Optional.of(unsubscriber));
}
+
+ public SetDurationCharacteristic(
+ Supplier> getter,
+ ExceptionalConsumer setter,
+ Consumer subscriber,
+ Runnable unsubscriber) {
+ this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, getter, setter, subscriber, unsubscriber);
+ }
}
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java b/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
index 9b5b2b8ee..20a697ff9 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitUtils.java
@@ -2,7 +2,6 @@
import com.nimbusds.srp6.SRP6Routines;
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -14,11 +13,12 @@ public class HomekitUtils {
private static volatile SecureRandom secureRandom;
public static BigInteger generateSalt() {
- return new BigInteger(SRP6Routines.generateRandomSalt(16));
+ return new BigInteger(new SRP6Routines().generateRandomSalt(16));
}
- public static byte[] generateKey() throws InvalidAlgorithmParameterException {
- EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512");
+ public static byte[] generateKey() {
+ EdDSAParameterSpec spec =
+ EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
byte[] seed = new byte[spec.getCurve().getField().getb() / 8];
getSecureRandom().nextBytes(seed);
return seed;
diff --git a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
index 4c74a469d..9b9c2cc5d 100644
--- a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
+++ b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaDecoder.java
@@ -5,8 +5,6 @@
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.tls.AlertDescription;
-import org.bouncycastle.crypto.tls.TlsFatalAlert;
import org.bouncycastle.util.Arrays;
public class ChachaDecoder {
@@ -28,7 +26,7 @@ public byte[] decodeCiphertext(byte[] receivedMAC, byte[] additionalData, byte[]
byte[] calculatedMAC = PolyKeyCreator.create(macKey, additionalData, ciphertext);
if (!Arrays.constantTimeAreEqual(calculatedMAC, receivedMAC)) {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ throw new IOException("received an incorrect MAC");
}
byte[] output = new byte[ciphertext.length];
@@ -45,9 +43,7 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) {
byte[] firstBlock = new byte[64];
cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0);
- // NOTE: The BC implementation puts 'r' after 'k'
- System.arraycopy(firstBlock, 0, firstBlock, 32, 16);
- KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
+ KeyParameter macKey = new KeyParameter(firstBlock, 0, 32);
Poly1305KeyGenerator.clamp(macKey.getKey());
return macKey;
}
diff --git a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java
index 3304e7d9a..3649844eb 100644
--- a/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java
+++ b/src/main/java/io/github/hapjava/server/impl/crypto/ChachaEncoder.java
@@ -39,9 +39,7 @@ private KeyParameter initRecordMAC(ChaChaEngine cipher) {
byte[] firstBlock = new byte[64];
cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0);
- // NOTE: The BC implementation puts 'r' after 'k'
- System.arraycopy(firstBlock, 0, firstBlock, 32, 16);
- KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
+ KeyParameter macKey = new KeyParameter(firstBlock, 0, 32);
Poly1305KeyGenerator.clamp(macKey.getKey());
return macKey;
}
diff --git a/src/main/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiser.java b/src/main/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiser.java
index a178d2cfc..04016561e 100644
--- a/src/main/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiser.java
+++ b/src/main/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiser.java
@@ -26,6 +26,7 @@ public class JmdnsHomekitAdvertiser {
private String setupId;
private int port;
private int configurationIndex;
+ private ServiceInfo serviceInfo;
public JmdnsHomekitAdvertiser(JmDNS jmdns) {
this.jmdns = jmdns;
@@ -87,12 +88,20 @@ public synchronized void setConfigurationIndex(int revision) throws IOException
}
private void unregisterService() {
- jmdns.unregisterService(buildServiceInfo());
+ if (serviceInfo != null) {
+ jmdns.unregisterService(serviceInfo);
+ serviceInfo = null;
+ }
}
private void registerService() throws IOException {
logger.info("Registering " + SERVICE_TYPE + " on port " + port);
- jmdns.registerService(buildServiceInfo());
+ if (this.serviceInfo != null) {
+ throw new AssertionError(
+ "Registering an already registered service without unregistering first is not allowed");
+ }
+ serviceInfo = buildServiceInfo();
+ jmdns.registerService(serviceInfo);
}
private ServiceInfo buildServiceInfo() {
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java b/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
index 6516e2e29..e65beec3c 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ByteUtils.java
@@ -22,7 +22,7 @@ public static byte[] joinBytes(byte[]... piece) {
return ret;
}
- public static byte[] toByteArray(BigInteger i) {
+ public static byte[] toUnsignedByteArray(BigInteger i) {
byte[] array = i.toByteArray();
if (array[0] == 0) {
array = Arrays.copyOfRange(array, 1, array.length);
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
index 16c514707..7e139296c 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ClientEvidenceRoutineImpl.java
@@ -1,5 +1,7 @@
package io.github.hapjava.server.impl.pairing;
+import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray;
+
import com.nimbusds.srp6.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
@@ -8,9 +10,7 @@
class ClientEvidenceRoutineImpl implements ClientEvidenceRoutine {
- public ClientEvidenceRoutineImpl() {
- // TODO Auto-generated constructor stub
- }
+ public ClientEvidenceRoutineImpl() {}
/**
* Calculates M1 according to the following formula:
@@ -27,10 +27,10 @@ public BigInteger computeClientEvidence(
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Could not locate requested algorithm", e);
}
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.N));
+ digest.update(toUnsignedByteArray(cryptoParams.N));
byte[] hN = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.g));
+ digest.update(toUnsignedByteArray(cryptoParams.g));
byte[] hg = digest.digest();
byte[] hNhg = xor(hN, hg);
@@ -38,14 +38,14 @@ public BigInteger computeClientEvidence(
digest.update(ctx.userID.getBytes(StandardCharsets.UTF_8));
byte[] hu = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S));
+ digest.update(toUnsignedByteArray(ctx.S));
byte[] hS = digest.digest();
digest.update(hNhg);
digest.update(hu);
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.s));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.B));
+ digest.update(toUnsignedByteArray(ctx.s));
+ digest.update(toUnsignedByteArray(ctx.A));
+ digest.update(toUnsignedByteArray(ctx.B));
digest.update(hS);
BigInteger ret = new BigInteger(1, digest.digest());
return ret;
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java b/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
index 3841d9fb7..116fced13 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/HomekitSRP6ServerSession.java
@@ -8,6 +8,7 @@
import com.nimbusds.srp6.SRP6Session;
import com.nimbusds.srp6.URoutineContext;
import java.math.BigInteger;
+import java.security.MessageDigest;
/**
* This is a slightly modified version of the SRP6ServerSession class included with nimbus. The only
@@ -74,6 +75,8 @@ public static enum State {
/** The current SRP-6a auth state. */
private State state;
+ private MessageDigest digest;
+
/**
* Creates a new server-side SRP-6a authentication session and sets its state to {@link
* State#INIT}.
@@ -92,7 +95,7 @@ public HomekitSRP6ServerSession(final SRP6CryptoParams config, final int timeout
this.config = config;
- digest = config.getMessageDigestInstance();
+ this.digest = config.getMessageDigestInstance();
if (digest == null)
throw new IllegalArgumentException("Unsupported hash algorithm 'H': " + config.H);
@@ -151,13 +154,13 @@ public BigInteger step1(final String userID, final BigInteger s, final BigIntege
throw new IllegalStateException("State violation: Session must be in INIT state");
// Generate server private and public values
- k = SRP6Routines.computeK(digest, config.N, config.g);
+ k = new SRP6Routines().computeK(digest, config.N, config.g);
digest.reset();
b = HomekitSRP6Routines.generatePrivateValue(config.N, random);
digest.reset();
- B = SRP6Routines.computePublicServerValue(config.N, config.g, k, v, b);
+ B = new SRP6Routines().computePublicServerValue(config.N, config.g, k, v, b);
state = State.STEP_1;
@@ -234,7 +237,7 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
if (hasTimedOut()) throw new SRP6Exception("Session timeout", SRP6Exception.CauseType.TIMEOUT);
// Check A validity
- if (!SRP6Routines.isValidPublicValue(config.N, A))
+ if (!new SRP6Routines().isValidPublicValue(config.N, A))
throw new SRP6Exception(
"Bad client public value 'A'", SRP6Exception.CauseType.BAD_PUBLIC_VALUE);
@@ -246,11 +249,11 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
URoutineContext hashedKeysContext = new URoutineContext(A, B);
u = hashedKeysRoutine.computeU(config, hashedKeysContext);
} else {
- u = SRP6Routines.computeU(digest, config.N, A, B);
+ u = new SRP6Routines().computeU(digest, config.N, A, B);
digest.reset();
}
- S = SRP6Routines.computeSessionKey(config.N, v, u, A, b);
+ S = new SRP6Routines().computeSessionKey(config.N, v, u, A, b);
// Compute the own client evidence message 'M1'
BigInteger computedM1;
@@ -262,7 +265,7 @@ public BigInteger step2(final BigInteger A, final BigInteger M1) throws SRP6Exce
computedM1 = clientEvidenceRoutine.computeClientEvidence(config, ctx);
} else {
// With default routine
- computedM1 = SRP6Routines.computeClientEvidence(digest, A, B, S);
+ computedM1 = new SRP6Routines().computeClientEvidence(digest, A, B, S);
digest.reset();
}
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java b/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
index af6a6e01f..ee4b772f9 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/PairingManager.java
@@ -29,7 +29,7 @@ public HttpResponse handle(HttpRequest httpRequest) throws Exception {
if (req.getStage() == Stage.ONE) {
logger.trace("Starting pair for " + registry.getLabel());
srpHandler = new SrpHandler(authInfo.getPin(), authInfo.getSalt());
- return srpHandler.handle(req);
+ return srpHandler.step1();
} else if (req.getStage() == Stage.TWO) {
logger.trace("Entering second stage of pair for " + registry.getLabel());
if (srpHandler == null) {
@@ -37,7 +37,7 @@ public HttpResponse handle(HttpRequest httpRequest) throws Exception {
return new UnauthorizedResponse();
} else {
try {
- return srpHandler.handle(req);
+ return srpHandler.step2((PairSetupRequest.Stage2Request) req);
} catch (Exception e) {
srpHandler = null; // You don't get to try again - need a new key
logger.warn("Exception encountered while processing pairing request", e);
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java b/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
index 7cf7b3164..77739e9b2 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/ServerEvidenceRoutineImpl.java
@@ -1,5 +1,7 @@
package io.github.hapjava.server.impl.pairing;
+import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray;
+
import com.nimbusds.srp6.SRP6CryptoParams;
import com.nimbusds.srp6.SRP6ServerEvidenceContext;
import com.nimbusds.srp6.ServerEvidenceRoutine;
@@ -20,10 +22,10 @@ public BigInteger computeServerEvidence(
throw new RuntimeException("Could not locate requested algorithm", e);
}
- byte[] hS = digest.digest(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S));
+ byte[] hS = digest.digest(toUnsignedByteArray(ctx.S));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.M1));
+ digest.update(toUnsignedByteArray(ctx.A));
+ digest.update(toUnsignedByteArray(ctx.M1));
digest.update(hS);
return new BigInteger(1, digest.digest());
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java b/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
index e02ccdb90..ec4b34c97 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/SrpHandler.java
@@ -1,25 +1,22 @@
package io.github.hapjava.server.impl.pairing;
+import static io.github.hapjava.server.impl.pairing.ByteUtils.toUnsignedByteArray;
+
import com.nimbusds.srp6.*;
import io.github.hapjava.server.impl.http.HttpResponse;
import io.github.hapjava.server.impl.pairing.HomekitSRP6ServerSession.State;
import io.github.hapjava.server.impl.pairing.PairSetupRequest.Stage2Request;
import io.github.hapjava.server.impl.pairing.TypeLengthValueUtils.Encoder;
import io.github.hapjava.server.impl.responses.ConflictResponse;
-import io.github.hapjava.server.impl.responses.NotFoundResponse;
import java.math.BigInteger;
import java.security.MessageDigest;
-import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class SrpHandler {
- // Precomputed safe 3072 bit prime 'N'. Origin RFC 5054, appendix A.
- private static final BigInteger N_3072 =
- new BigInteger(
- "5809605995369958062791915965639201402176612226902900533702900882779736177890990861472094774477339581147373410185646378328043729800750470098210924487866935059164371588168047540943981644516632755067501626434556398193186628990071248660819361205119793693985433297036118232914410171876807536457391277857011849897410207519105333355801121109356897459426271845471397952675959440793493071628394122780510124618488232602464649876850458861245784240929258426287699705312584509625419513463605155428017165714465363094021609290561084025893662561222573202082865797821865270991145082200656978177192827024538990239969175546190770645685893438011714430426409338676314743571154537142031573004276428701433036381801705308659830751190352946025482059931306571004727362479688415574702596946457770284148435989129632853918392117997472632693078113129886487399347796982772784615865232621289656944284216824611318709764535152507354116344703769998514148343807");
- private static final BigInteger G = BigInteger.valueOf(5);
+ private static final int BIT_SIZE = 3072;
+ private static final String HASH_ALG_H = "SHA-512";
private static final String IDENTIFIER = "Pair-Setup";
private static final Logger logger = LoggerFactory.getLogger(SrpHandler.class);
@@ -30,7 +27,7 @@ class SrpHandler {
private final String pin;
public SrpHandler(String pin, BigInteger salt) {
- config = new SRP6CryptoParams(N_3072, G, "SHA-512");
+ config = SRP6CryptoParams.getInstance(BIT_SIZE, HASH_ALG_H);
session = new HomekitSRP6ServerSession(config);
session.setClientEvidenceRoutine(new ClientEvidenceRoutineImpl());
session.setServerEvidenceRoutine(new ServerEvidenceRoutineImpl());
@@ -38,20 +35,7 @@ public SrpHandler(String pin, BigInteger salt) {
this.salt = salt;
}
- public HttpResponse handle(PairSetupRequest request) throws Exception {
- switch (request.getStage()) {
- case ONE:
- return step1();
-
- case TWO:
- return step2((Stage2Request) request);
-
- default:
- return new NotFoundResponse();
- }
- }
-
- private HttpResponse step1() throws Exception {
+ HttpResponse step1() throws Exception {
if (session.getState() != State.INIT) {
logger.warn("Session is not in state INIT when receiving step1");
return new ConflictResponse();
@@ -68,7 +52,7 @@ private HttpResponse step1() throws Exception {
return new PairingResponse(encoder.toByteArray());
}
- private HttpResponse step2(Stage2Request request) throws Exception {
+ HttpResponse step2(Stage2Request request) throws Exception {
if (session.getState() != State.STEP_1) {
logger.warn("Session is not in state Stage 1 when receiving step2");
return new ConflictResponse();
@@ -80,18 +64,10 @@ private HttpResponse step2(Stage2Request request) throws Exception {
return new PairingResponse(encoder.toByteArray());
}
- public byte[] getK() {
+ byte[] getK() {
MessageDigest digest = session.getCryptoParams().getMessageDigestInstance();
- BigInteger S = session.getSessionKey(false);
- byte[] sBytes = bigIntegerToUnsignedByteArray(S);
+ BigInteger S = session.getSessionKey();
+ byte[] sBytes = toUnsignedByteArray(S);
return digest.digest(sBytes);
}
-
- public static byte[] bigIntegerToUnsignedByteArray(BigInteger i) {
- byte[] array = i.toByteArray();
- if (array[0] == 0) {
- array = Arrays.copyOfRange(array, 1, array.length);
- }
- return array;
- }
}
diff --git a/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java b/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
index 396829d34..03665d94d 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/TypeLengthValueUtils.java
@@ -38,7 +38,7 @@ private Encoder() {
}
public void add(MessageType type, BigInteger i) throws IOException {
- add(type, ByteUtils.toByteArray(i));
+ add(type, ByteUtils.toUnsignedByteArray(i));
}
public void add(MessageType type, short b) {
diff --git a/src/main/java/io/github/hapjava/services/impl/AirQualityService.java b/src/main/java/io/github/hapjava/services/impl/AirQualityService.java
index c9ccd6d62..4aa74c88f 100644
--- a/src/main/java/io/github/hapjava/services/impl/AirQualityService.java
+++ b/src/main/java/io/github/hapjava/services/impl/AirQualityService.java
@@ -53,6 +53,9 @@ public AirQualityService(AirQualityAccessory accessory) {
if (accessory instanceof AccessoryWithNitrogenDioxideDensity) {
addOptionalCharacteristic(
new NitrogenDioxideDensityCharacteristic(
+ ((AccessoryWithNitrogenDioxideDensity) accessory).getMinNitrogenDioxideDensity(),
+ ((AccessoryWithNitrogenDioxideDensity) accessory).getMaxNitrogenDioxideDensity(),
+ ((AccessoryWithNitrogenDioxideDensity) accessory).getMinStepNitrogenDioxideDensity(),
((AccessoryWithNitrogenDioxideDensity) accessory)::getNitrogenDioxideDensity,
((AccessoryWithNitrogenDioxideDensity) accessory)::subscribeNitrogenDioxideDensity,
((AccessoryWithNitrogenDioxideDensity) accessory)
@@ -62,6 +65,9 @@ public AirQualityService(AirQualityAccessory accessory) {
if (accessory instanceof AccessoryWithSulphurDioxideDensity) {
addOptionalCharacteristic(
new SulphurDioxideDensityCharacteristic(
+ ((AccessoryWithSulphurDioxideDensity) accessory).getMinSulphurDioxideDensity(),
+ ((AccessoryWithSulphurDioxideDensity) accessory).getMaxSulphurDioxideDensity(),
+ ((AccessoryWithSulphurDioxideDensity) accessory).getMinStepSulphurDioxideDensity(),
((AccessoryWithSulphurDioxideDensity) accessory)::getSulphurDioxideDensity,
((AccessoryWithSulphurDioxideDensity) accessory)::subscribeSulphurDioxideDensity,
((AccessoryWithSulphurDioxideDensity) accessory)::unsubscribeSulphurDioxideDensity));
@@ -69,6 +75,9 @@ public AirQualityService(AirQualityAccessory accessory) {
if (accessory instanceof AccessoryWithPM25Density) {
addOptionalCharacteristic(
new PM25DensityCharacteristic(
+ ((AccessoryWithPM25Density) accessory).getMinPM25Density(),
+ ((AccessoryWithPM25Density) accessory).getMaxPM25Density(),
+ ((AccessoryWithPM25Density) accessory).getMinStepPM25Density(),
((AccessoryWithPM25Density) accessory)::getPM25Density,
((AccessoryWithPM25Density) accessory)::subscribePM25Density,
((AccessoryWithPM25Density) accessory)::unsubscribePM25Density));
@@ -76,6 +85,9 @@ public AirQualityService(AirQualityAccessory accessory) {
if (accessory instanceof AccessoryWithPM10Density) {
addOptionalCharacteristic(
new PM10DensityCharacteristic(
+ ((AccessoryWithPM10Density) accessory).getMinPM10Density(),
+ ((AccessoryWithPM10Density) accessory).getMaxPM10Density(),
+ ((AccessoryWithPM10Density) accessory).getMinStepPM10Density(),
((AccessoryWithPM10Density) accessory)::getPM10Density,
((AccessoryWithPM10Density) accessory)::subscribePM10Density,
((AccessoryWithPM10Density) accessory)::unsubscribePM10Density));
@@ -83,6 +95,9 @@ public AirQualityService(AirQualityAccessory accessory) {
if (accessory instanceof AccessoryWithVOCDensity) {
addOptionalCharacteristic(
new VOCDensityCharacteristic(
+ ((AccessoryWithVOCDensity) accessory).getMinVOCDensity(),
+ ((AccessoryWithVOCDensity) accessory).getMaxVOCDensity(),
+ ((AccessoryWithVOCDensity) accessory).getMinStepVOCDensity(),
((AccessoryWithVOCDensity) accessory)::getVOCDensity,
((AccessoryWithVOCDensity) accessory)::subscribeVOCDensity,
((AccessoryWithVOCDensity) accessory)::unsubscribeVOCDensity));
diff --git a/src/main/java/io/github/hapjava/services/impl/CarbonDioxideSensorService.java b/src/main/java/io/github/hapjava/services/impl/CarbonDioxideSensorService.java
index b329e5f8f..b61e91b91 100644
--- a/src/main/java/io/github/hapjava/services/impl/CarbonDioxideSensorService.java
+++ b/src/main/java/io/github/hapjava/services/impl/CarbonDioxideSensorService.java
@@ -34,11 +34,17 @@ public CarbonDioxideSensorService(CarbonDioxideSensorAccessory accessory) {
if (accessory instanceof AccessoryWithCarbonDioxideLevel) {
addOptionalCharacteristic(
new CarbonDioxideLevelCharacteristic(
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMinCarbonDioxideLevel(),
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMaxCarbonDioxideLevel(),
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMinStepCarbonDioxideLevel(),
((AccessoryWithCarbonDioxideLevel) accessory)::getCarbonDioxideLevel,
((AccessoryWithCarbonDioxideLevel) accessory)::subscribeCarbonDioxideLevel,
((AccessoryWithCarbonDioxideLevel) accessory)::unsubscribeCarbonDioxideLevel));
addOptionalCharacteristic(
new CarbonDioxidePeakLevelCharacteristic(
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMinCarbonDioxidePeakLevel(),
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMaxCarbonDioxidePeakLevel(),
+ ((AccessoryWithCarbonDioxideLevel) accessory).getMinStepCarbonDioxidePeakLevel(),
((AccessoryWithCarbonDioxideLevel) accessory)::getCarbonDioxidePeakLevel,
((AccessoryWithCarbonDioxideLevel) accessory)::subscribeCarbonDioxidePeakLevel,
((AccessoryWithCarbonDioxideLevel) accessory)::unsubscribeCarbonDioxidePeakLevel));
diff --git a/src/main/java/io/github/hapjava/services/impl/LightSensorService.java b/src/main/java/io/github/hapjava/services/impl/LightSensorService.java
index b40b4a43e..6aef8cd34 100644
--- a/src/main/java/io/github/hapjava/services/impl/LightSensorService.java
+++ b/src/main/java/io/github/hapjava/services/impl/LightSensorService.java
@@ -24,6 +24,9 @@ public LightSensorService(CurrentAmbientLightLevelCharacteristic lightLevel) {
public LightSensorService(LightSensorAccessory accessory) {
this(
new CurrentAmbientLightLevelCharacteristic(
+ accessory.getMinCurrentAmbientLightLevel(),
+ accessory.getMaxCurrentAmbientLightLevel(),
+ accessory.getMinStepCurrentAmbientLightLevel(),
accessory::getCurrentAmbientLightLevel,
accessory::subscribeCurrentAmbientLightLevel,
accessory::unsubscribeCurrentAmbientLightLevel));
diff --git a/src/main/java/io/github/hapjava/services/impl/LightbulbService.java b/src/main/java/io/github/hapjava/services/impl/LightbulbService.java
index 387a2b092..b37ca4d2c 100644
--- a/src/main/java/io/github/hapjava/services/impl/LightbulbService.java
+++ b/src/main/java/io/github/hapjava/services/impl/LightbulbService.java
@@ -55,6 +55,8 @@ public LightbulbService(LightbulbAccessory accessory) {
if (accessory instanceof AccessoryWithColorTemperature) {
addOptionalCharacteristic(
new ColorTemperatureCharacteristic(
+ ((AccessoryWithColorTemperature) accessory).getMinColorTemperature(),
+ ((AccessoryWithColorTemperature) accessory).getMaxColorTemperature(),
((AccessoryWithColorTemperature) accessory)::getColorTemperature,
((AccessoryWithColorTemperature) accessory)::setColorTemperature,
((AccessoryWithColorTemperature) accessory)::subscribeColorTemperature,
diff --git a/src/main/java/io/github/hapjava/services/impl/ThermostatService.java b/src/main/java/io/github/hapjava/services/impl/ThermostatService.java
index 232d9c487..c775a41d5 100644
--- a/src/main/java/io/github/hapjava/services/impl/ThermostatService.java
+++ b/src/main/java/io/github/hapjava/services/impl/ThermostatService.java
@@ -73,6 +73,12 @@ public ThermostatService(ThermostatAccessory accessory) {
if (accessory instanceof AccessoryWithCoolingThresholdTemperature) {
addOptionalCharacteristic(
new CoolingThresholdTemperatureCharacteristic(
+ ((AccessoryWithCoolingThresholdTemperature) accessory)
+ .getMinCoolingThresholdTemperature(),
+ ((AccessoryWithCoolingThresholdTemperature) accessory)
+ .getMaxCoolingThresholdTemperature(),
+ ((AccessoryWithCoolingThresholdTemperature) accessory)
+ .getStepCoolingThresholdTemperature(),
((AccessoryWithCoolingThresholdTemperature) accessory)
::getCoolingThresholdTemperature,
((AccessoryWithCoolingThresholdTemperature) accessory)
@@ -85,6 +91,12 @@ public ThermostatService(ThermostatAccessory accessory) {
if (accessory instanceof AccessoryWithHeatingThresholdTemperature) {
addOptionalCharacteristic(
new HeatingThresholdTemperatureCharacteristic(
+ ((AccessoryWithHeatingThresholdTemperature) accessory)
+ .getMinHeatingThresholdTemperature(),
+ ((AccessoryWithHeatingThresholdTemperature) accessory)
+ .getMaxHeatingThresholdTemperature(),
+ ((AccessoryWithHeatingThresholdTemperature) accessory)
+ .getStepHeatingThresholdTemperature(),
((AccessoryWithHeatingThresholdTemperature) accessory)
::getHeatingThresholdTemperature,
((AccessoryWithHeatingThresholdTemperature) accessory)
diff --git a/src/main/java/io/github/hapjava/services/impl/ValveService.java b/src/main/java/io/github/hapjava/services/impl/ValveService.java
index b45c48ef4..519502a3c 100644
--- a/src/main/java/io/github/hapjava/services/impl/ValveService.java
+++ b/src/main/java/io/github/hapjava/services/impl/ValveService.java
@@ -58,6 +58,8 @@ public ValveService(ValveAccessory accessory) {
if (accessory instanceof AccessoryWithDuration) {
addOptionalCharacteristic(
new SetDurationCharacteristic(
+ ((AccessoryWithDuration) accessory).getMinDuration(),
+ ((AccessoryWithDuration) accessory).getMaxDuration(),
((AccessoryWithDuration) accessory)::getSetDuration,
((AccessoryWithDuration) accessory)::setSetDuration,
((AccessoryWithDuration) accessory)::subscribeSetDuration,
@@ -66,6 +68,8 @@ public ValveService(ValveAccessory accessory) {
if (accessory instanceof AccessoryWithRemainingDuration) {
addOptionalCharacteristic(
new RemainingDurationCharacteristic(
+ ((AccessoryWithRemainingDuration) accessory).getMinRemainingDuration(),
+ ((AccessoryWithRemainingDuration) accessory).getMaxRemainingDuration(),
((AccessoryWithRemainingDuration) accessory)::getRemainingDuration,
((AccessoryWithRemainingDuration) accessory)::subscribeRemainingDuration,
((AccessoryWithRemainingDuration) accessory)::unsubscribeRemainingDuration));
diff --git a/src/test/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiserTest.java b/src/test/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiserTest.java
new file mode 100644
index 000000000..1c04b2868
--- /dev/null
+++ b/src/test/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiserTest.java
@@ -0,0 +1,66 @@
+package io.github.hapjava.server.impl.jmdns;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import javax.jmdns.JmDNS;
+import javax.jmdns.ServiceInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+public class JmdnsHomekitAdvertiserTest {
+
+ JmdnsHomekitAdvertiser subject;
+ JmDNS jmdns;
+
+ @Before
+ public void setup() throws UnknownHostException, IOException {
+ jmdns = mock(JmDNS.class);
+ subject = new JmdnsHomekitAdvertiser(jmdns);
+ }
+
+ @Test
+ public void testAdvertiseTwiceFails() throws Exception {
+ advertise();
+ assertThatThrownBy(() -> advertise()).isNotNull();
+ }
+
+ /*
+ * Verify that the unregister call is for the initial registered service
+ * when changing discoverability causes advertising to be toggled.
+ */
+ @Test
+ public void testSetDiscoverableAfterAdvertise() throws Exception {
+ subject.setDiscoverable(false);
+ advertise();
+ subject.setDiscoverable(true);
+ assertThat(getArgumentFromUnregister().getPropertyString("sf")).isEqualTo("0");
+ }
+
+ /*
+ * Verify that the unregister call is for the initial registered service
+ * when changing the config index causes advertising to be toggled.
+ */
+ @Test
+ public void testSetConfigurationIndex() throws Exception {
+ subject.setConfigurationIndex(1);
+ advertise();
+ subject.setConfigurationIndex(2);
+ assertThat(getArgumentFromUnregister().getPropertyString("c#")).isEqualTo("1");
+ }
+
+ private ServiceInfo getArgumentFromUnregister() {
+ ArgumentCaptor serviceInfoCaptor = ArgumentCaptor.forClass(ServiceInfo.class);
+ verify(jmdns).unregisterService(serviceInfoCaptor.capture());
+ return serviceInfoCaptor.getValue();
+ }
+
+ private void advertise() throws Exception {
+ subject.advertise("test", "00:00:00:00:00:00", 1234, 1, "1");
+ }
+}