diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index 61753eab7..000000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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@v3
- - name: Set up JDK 11 for Maven Central
- uses: actions/setup-java@v3
- with:
- distribution: 'zulu'
- 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[bot]"
- git config --global user.email "41898282+github-actions[bot]@users.noreply.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
deleted file mode 100644
index 6f597043c..000000000
--- a/.github/workflows/maven.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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@v3
- - name: Set up JDK 11
- uses: actions/setup-java@v3
- with:
- distribution: 'zulu'
- 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
deleted file mode 100644
index 48b5ee7cf..000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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
-
-permissions:
- contents: write
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v3
- - uses: git-actions/set-user@v1
- - name: Set up JDK 11
- uses: actions/setup-java@v3
- with:
- distribution: 'zulu'
- 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: 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 ab4bc7e4f..e7d226df4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -62,6 +62,7 @@
* 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
diff --git a/pom.xml b/pom.xml
index ffd5798a3..600cb07a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,358 +1,300 @@
- 4.0.0
- io.github.hap-java
- hap
- hap-java
- Homekit Accessory Protocol for Java
- 2.0.8-SNAPSHOT
- jar
- https://github.com/hap-java/HAP-Java
+ 4.0.0
+ io.github.hap-java
+ hap
+ hap-java
+ Homekit Accessory Protocol for Java
+ 2.0.4-rako
+ jar
+ https://github.com/hap-java/HAP-Java
-
- UTF-8
- 4.1.72.Final
-
+
+ UTF-8
+ 4.1.121.Final
+
-
-
- MIT License
- http://www.opensource.org/licenses/mit-license.php
- repo
-
-
+
+
+ MIT License
+ http://www.opensource.org/licenses/mit-license.php
+ repo
+
+
-
- scm:git:https://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
-
+
+ scm:git:https://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
+
-
-
- Andy Lintner
- dev@beowulfe.com
- https://github.com/beowulfe
-
-
- Cody Cutrer
- cody@cutrer.us
- https://github.com/ccutrer
-
-
- Tim Harper
- timcharper@gmail.com
- https://github.com/timcharper
-
-
+
+
+ Andy Lintner
+ dev@beowulfe.com
+ https://github.com/beowulfe
+
+
+ Cody Cutrer
+ cody@cutrer.us
+ https://github.com/ccutrer
+
+
+ Tim Harper
+ timcharper@gmail.com
+ https://github.com/timcharper
+
+
-
+
-
- org.slf4j
- slf4j-api
- 1.7.10
-
+
+ org.slf4j
+ slf4j-api
+ 1.7.10
+
-
- io.netty
- netty-common
- ${netty.version}
-
+
+ io.netty
+ netty-common
+ ${netty.version}
+
-
- io.netty
- netty-buffer
- ${netty.version}
-
+
+ io.netty
+ netty-buffer
+ ${netty.version}
+
-
- io.netty
- netty-transport
- ${netty.version}
-
+
+ io.netty
+ netty-transport
+ ${netty.version}
+
-
- io.netty
- netty-handler
- ${netty.version}
-
+
+ io.netty
+ netty-handler
+ ${netty.version}
+
-
- io.netty
- netty-codec
- ${netty.version}
-
+
+ io.netty
+ netty-codec
+ ${netty.version}
+
-
- io.netty
- netty-codec-http
- ${netty.version}
-
+
+ io.netty
+ netty-codec-http
+ ${netty.version}
+
-
- io.netty
- netty-resolver
- ${netty.version}
-
+
+ io.netty
+ netty-resolver
+ ${netty.version}
+
-
- com.nimbusds
- srp6a
- 1.5.2
-
+
+ com.nimbusds
+ srp6a
+ 2.1.0
+
-
- org.bouncycastle
- bcprov-jdk15on
- 1.51
-
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.69
+
-
- net.vrallev.ecc
- ecc-25519-java
- 1.0.1
-
+
+ net.vrallev.ecc
+ ecc-25519-java
+ 1.0.3
+
-
- org.zeromq
- curve25519-java
- 0.1.0
-
+
+ javax.json
+ javax.json-api
+ 1.1.4
+
-
- javax.json
- javax.json-api
- 1.0
-
+
+ org.glassfish
+ javax.json
+ 1.1.4
+
-
- org.glassfish
- javax.json
- 1.0.4
-
+
+ org.jmdns
+ jmdns
+ 3.5.8
+
-
- org.jmdns
- jmdns
- 3.5.6
-
-
-
- junit
- junit
- 4.13.1
- test
-
-
-
- org.mockito
- mockito-core
- 3.8.0
- test
-
+
+ org.mockito
+ mockito-core
+ 3.8.0
+ test
+
-
- org.assertj
- assertj-core
- 3.19.0
- test
-
+
+ org.assertj
+ assertj-core
+ 3.19.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
-
+
-
-
-
- com.coveo
- fmt-maven-plugin
- 2.9
-
-
-
- format
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.8.0
-
- 1.8
- 1.8
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 3.0.1
-
-
- attach-sources
-
- jar-no-fork
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.2.0
-
- io.github.hapjava.server.impl
- 8
-
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-scm-publish-plugin
- 3.1.0
-
-
- scm-publish
- site-deploy
-
- publish-scm
-
-
- scm:git:https://github.com/hap-java/HAP-Java.git
- gh-pages
-
-
-
-
-
- org.apache.maven.plugins
- maven-site-plugin
- 3.7.1
-
-
- stage-for-scm-publish
- post-site
-
- stage
-
-
- false
-
-
-
-
-
+
+
+
+ com.coveo
+ fmt-maven-plugin
+ 2.9
+
+
+
+ format
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
-
-
-
- org.apache.maven.plugins
- maven-site-plugin
-
- true
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+
+ true
+
+
+
+
-
+
-
-
- website
- https://hap-java.github.io/
-
-
- ossrh
- https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
-
-
- ossrh
- https://s01.oss.sonatype.org/content/repositories/snapshots
-
-
+
+
+ website
+ https://hap-java.github.io/
+
+
+ ossrh
+ https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+ ossrh
+ https://s01.oss.sonatype.org/content/repositories/snapshots
+
+
-
-
-
- org.apache.maven.plugins
- maven-pmd-plugin
- 3.6
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.0.1
-
- io.github.hapjava.server.impl
- 8
- false
-
-
-
-
- javadoc
-
-
-
-
-
- org.codehaus.mojo
- findbugs-maven-plugin
- 3.0.3
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.6
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.1
+
+ io.github.hapjava.server.impl
+ 8
+ false
+
+
+
+
+ javadoc
+
+
+
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+ 3.0.3
+
+
+
-
-
- ossrh
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.5
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
- HAP-Java
-
- --pinentry-mode
- loopback
-
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
- true
-
- ossrh
- https://s01.oss.sonatype.org/
- true
-
-
-
-
-
-
+
+
+ ossrh
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+ HAP-Java
+
+ --pinentry-mode
+ loopback
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.3
+ true
+
+ ossrh
+ https://s01.oss.sonatype.org/
+ true
+
+
+
+
+
+
diff --git a/pom.xml.versionsBackup b/pom.xml.versionsBackup
new file mode 100644
index 000000000..fee8f26c1
--- /dev/null
+++ b/pom.xml.versionsBackup
@@ -0,0 +1,300 @@
+
+
+ 4.0.0
+ io.github.hap-java
+ hap
+ hap-java
+ Homekit Accessory Protocol for Java
+ 2.0.3-rako
+ jar
+ https://github.com/hap-java/HAP-Java
+
+
+ UTF-8
+ 4.1.121.Final
+
+
+
+
+ MIT License
+ http://www.opensource.org/licenses/mit-license.php
+ repo
+
+
+
+
+ scm:git:https://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
+
+
+
+
+ Andy Lintner
+ dev@beowulfe.com
+ https://github.com/beowulfe
+
+
+ Cody Cutrer
+ cody@cutrer.us
+ https://github.com/ccutrer
+
+
+ Tim Harper
+ timcharper@gmail.com
+ https://github.com/timcharper
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.10
+
+
+
+ io.netty
+ netty-common
+ ${netty.version}
+
+
+
+ io.netty
+ netty-buffer
+ ${netty.version}
+
+
+
+ io.netty
+ netty-transport
+ ${netty.version}
+
+
+
+ io.netty
+ netty-handler
+ ${netty.version}
+
+
+
+ io.netty
+ netty-codec
+ ${netty.version}
+
+
+
+ io.netty
+ netty-codec-http
+ ${netty.version}
+
+
+
+ io.netty
+ netty-resolver
+ ${netty.version}
+
+
+
+ com.nimbusds
+ srp6a
+ 2.1.0
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.69
+
+
+
+ net.vrallev.ecc
+ ecc-25519-java
+ 1.0.3
+
+
+
+ javax.json
+ javax.json-api
+ 1.1.4
+
+
+
+ org.glassfish
+ javax.json
+ 1.1.4
+
+
+
+ org.jmdns
+ jmdns
+ 3.5.8
+
+
+
+ org.mockito
+ mockito-core
+ 3.8.0
+ test
+
+
+
+ org.assertj
+ assertj-core
+ 3.19.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+
+
+
+
+
+ com.coveo
+ fmt-maven-plugin
+ 2.9
+
+
+
+ format
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+
+ true
+
+
+
+
+
+
+
+
+
+ website
+ https://hap-java.github.io/
+
+
+ ossrh
+ https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+ ossrh
+ https://s01.oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.6
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.1
+
+ io.github.hapjava.server.impl
+ 8
+ false
+
+
+
+
+ javadoc
+
+
+
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+ 3.0.3
+
+
+
+
+
+
+ ossrh
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+ HAP-Java
+
+ --pinentry-mode
+ loopback
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.3
+ true
+
+ ossrh
+ https://s01.oss.sonatype.org/
+ true
+
+
+
+
+
+
+
+
diff --git a/src/main/java/io/github/hapjava/accessories/HomekitAccessory.java b/src/main/java/io/github/hapjava/accessories/HomekitAccessory.java
index 64c406492..a8d01254e 100644
--- a/src/main/java/io/github/hapjava/accessories/HomekitAccessory.java
+++ b/src/main/java/io/github/hapjava/accessories/HomekitAccessory.java
@@ -23,7 +23,7 @@ public interface HomekitAccessory {
*
* @return the unique identifier.
*/
- int getId();
+ long getId();
/**
* Returns a name to display in iOS.
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/base/IntegerCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/base/IntegerCharacteristic.java
index 6d1b7df6d..e80c14823 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/base/IntegerCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/base/IntegerCharacteristic.java
@@ -56,6 +56,32 @@ public IntegerCharacteristic(
this.setter = setter;
}
+ public IntegerCharacteristic(
+ String type,
+ String description,
+ int minValue,
+ int maxValue,
+ String format,
+ String unit,
+ Optional>> getter,
+ Optional> setter,
+ Optional> subscriber,
+ Optional unsubscriber) {
+ super(
+ type,
+ format,
+ description,
+ getter.isPresent(),
+ setter.isPresent(),
+ subscriber,
+ unsubscriber);
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ this.unit = unit;
+ this.getter = getter;
+ this.setter = setter;
+ }
+
/** {@inheritDoc} */
@Override
protected CompletableFuture makeBuilder(int iid) {
@@ -77,7 +103,9 @@ public CompletableFuture getValue() {
@Override
public void setValue(Integer value) throws Exception {
- if (setter.isPresent()) setter.get().accept(value);
+ if (setter.isPresent()) {
+ setter.get().accept(value);
+ }
}
/** {@inheritDoc} */
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/battery/BatteryLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/battery/BatteryLevelCharacteristic.java
index 0fa56ff40..cb4f335a2 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/battery/BatteryLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/battery/BatteryLevelCharacteristic.java
@@ -21,7 +21,7 @@ public BatteryLevelCharacteristic(
"battery level",
0,
100,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelIndexCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelIndexCharacteristic.java
index 522cb04fe..955e032d5 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelIndexCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/common/ServiceLabelIndexCharacteristic.java
@@ -19,7 +19,7 @@ public ServiceLabelIndexCharacteristic(Supplier> gett
"service label index",
0,
100,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.empty(),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/common/WaterLavelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/common/WaterLavelCharacteristic.java
index dda11b087..121ac013e 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/common/WaterLavelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/common/WaterLavelCharacteristic.java
@@ -22,7 +22,7 @@ public WaterLavelCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationSpeedCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationSpeedCharacteristic.java
index d7a1d6929..7ef05a13c 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationSpeedCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/fan/RotationSpeedCharacteristic.java
@@ -30,7 +30,7 @@ public RotationSpeedCharacteristic(
minValue,
maxValue,
minStep,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/filtermaintenance/FilterLifeLevelCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/filtermaintenance/FilterLifeLevelCharacteristic.java
index 29cdf8d6e..0206a7193 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/filtermaintenance/FilterLifeLevelCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/filtermaintenance/FilterLifeLevelCharacteristic.java
@@ -21,7 +21,7 @@ public FilterLifeLevelCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityDehumidifierThresholdCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityDehumidifierThresholdCharacteristic.java
index b8a4ca569..9839fb9fd 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityDehumidifierThresholdCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityDehumidifierThresholdCharacteristic.java
@@ -25,7 +25,7 @@ public HumidityDehumidifierThresholdCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityHumidifierThresholdCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityHumidifierThresholdCharacteristic.java
index 2ee8adbf2..40401352a 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityHumidifierThresholdCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/humidifier/HumidityHumidifierThresholdCharacteristic.java
@@ -25,7 +25,7 @@ public HumidityHumidifierThresholdCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/CurrentRelativeHumidityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/CurrentRelativeHumidityCharacteristic.java
index be77125b6..71466c424 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/CurrentRelativeHumidityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/CurrentRelativeHumidityCharacteristic.java
@@ -20,7 +20,7 @@ public CurrentRelativeHumidityCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/TargetRelativeHumidityCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/TargetRelativeHumidityCharacteristic.java
index ab8ad7e29..ad4f35858 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/TargetRelativeHumidityCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/humiditysensor/TargetRelativeHumidityCharacteristic.java
@@ -22,7 +22,7 @@ public TargetRelativeHumidityCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/BrightnessCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/BrightnessCharacteristic.java
index 693e42efc..1da361a5f 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/BrightnessCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/BrightnessCharacteristic.java
@@ -26,7 +26,7 @@ public BrightnessCharacteristic(
"level of brightness",
0,
100,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
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 987ab5eee..31b7cd64a 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,8 @@
/** This characteristic describes color temperature in mireds */
public class ColorTemperatureCharacteristic extends IntegerCharacteristic
implements EventableCharacteristic {
- public static final int DEFAULT_MIN_VALUE = 50;
- public static final int DEFAULT_MAX_VALUE = 400;
+ public static final int DEFAULT_MIN_VALUE = 100;
+ public static final int DEFAULT_MAX_VALUE = 555;
public ColorTemperatureCharacteristic(
int minValue,
@@ -27,7 +27,8 @@ public ColorTemperatureCharacteristic(
"color temperature",
minValue,
maxValue,
- "mired",
+ "uint32",
+ null,
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/SaturationCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/SaturationCharacteristic.java
index 90694ef98..a6ff31f4b 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/SaturationCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/lightbulb/SaturationCharacteristic.java
@@ -24,7 +24,7 @@ public SaturationCharacteristic(
0,
100,
1,
- "%",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/protocolinformation/VersionCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/protocolinformation/VersionCharacteristic.java
new file mode 100644
index 000000000..fcc33016d
--- /dev/null
+++ b/src/main/java/io/github/hapjava/characteristics/impl/protocolinformation/VersionCharacteristic.java
@@ -0,0 +1,19 @@
+package io.github.hapjava.characteristics.impl.protocolinformation;
+
+import io.github.hapjava.characteristics.impl.base.StaticStringCharacteristic;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+
+/** This characteristic contains a version string. */
+public class VersionCharacteristic extends StaticStringCharacteristic {
+
+ public VersionCharacteristic(Supplier> getter) {
+ super(
+ "00000037‐0000‐1000‐8000‐0026BB765291",
+ "version",
+ Optional.of(getter),
+ Optional.empty(),
+ Optional.empty());
+ }
+}
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/CurrentPositionCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/CurrentPositionCharacteristic.java
index d51614615..5f8f50081 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/CurrentPositionCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/CurrentPositionCharacteristic.java
@@ -21,7 +21,7 @@ public CurrentPositionCharacteristic(
"current position",
0,
100,
- "%",
+ "percentage",
Optional.of(getter),
Optional.empty(),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/TargetPositionCharacteristic.java b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/TargetPositionCharacteristic.java
index 6398a0b37..9458402aa 100644
--- a/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/TargetPositionCharacteristic.java
+++ b/src/main/java/io/github/hapjava/characteristics/impl/windowcovering/TargetPositionCharacteristic.java
@@ -23,7 +23,8 @@ public TargetPositionCharacteristic(
"target position",
0,
100,
- "%",
+ "uint8",
+ "percentage",
Optional.of(getter),
Optional.of(setter),
Optional.of(subscriber),
diff --git a/src/main/java/io/github/hapjava/server/HomekitAuthInfo.java b/src/main/java/io/github/hapjava/server/HomekitAuthInfo.java
index 6441962d7..10ac5d8c9 100644
--- a/src/main/java/io/github/hapjava/server/HomekitAuthInfo.java
+++ b/src/main/java/io/github/hapjava/server/HomekitAuthInfo.java
@@ -4,7 +4,7 @@
import io.github.hapjava.server.impl.crypto.HAPSetupCodeUtils;
import java.math.BigInteger;
import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
/**
* Authentication info that must be provided when constructing a new {@link HomekitServer}. You will
@@ -99,7 +99,7 @@ default void createUser(String username, byte[] publicKey) {
* @return the previously stored list of users.
*/
default Collection listUsers() {
- return List.of();
+ return Collections.EMPTY_LIST;
}
/**
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitBridge.java b/src/main/java/io/github/hapjava/server/impl/HomekitBridge.java
index 11efb0d37..807a7ff51 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitBridge.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitBridge.java
@@ -21,7 +21,8 @@ public HomekitBridge(
String model,
String manufacturer,
String firmwareRevision,
- String hardwareRevision) {
+ String hardwareRevision,
+ String version) {
this.label = label;
this.serialNumber = serialNumber;
this.model = model;
@@ -55,13 +56,19 @@ public CompletableFuture getFirmwareRevision() {
return CompletableFuture.completedFuture(firmwareRevision);
}
+ public CompletableFuture getHardwareRevision() {
+ return CompletableFuture.completedFuture(hardwareRevision);
+ }
+
@Override
public Collection getServices() {
+ // return Collections.singleton(new ProtocolInformationService(this));
+
return Collections.emptyList();
}
@Override
- public int getId() {
+ public long getId() {
return 1;
}
}
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitRegistry.java b/src/main/java/io/github/hapjava/server/impl/HomekitRegistry.java
index 3c70cfb9e..5ef547923 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitRegistry.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitRegistry.java
@@ -21,7 +21,7 @@ public class HomekitRegistry {
private final String label;
private final SubscriptionManager subscriptions;
- private final Map accessories;
+ private final Map accessories;
private final Map> services = new HashMap<>();
private final Map> characteristics =
new HashMap<>();
@@ -79,11 +79,11 @@ public Collection getAccessories() {
return accessories.values();
}
- public Map getServices(Integer aid) {
+ public Map getServices(Long aid) {
return Collections.unmodifiableMap(services.get(accessories.get(aid)));
}
- public Map getCharacteristics(Integer aid) {
+ public Map getCharacteristics(Long aid) {
Map characteristics = this.characteristics.get(accessories.get(aid));
if (characteristics == null) {
return Collections.emptyMap();
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitRoot.java b/src/main/java/io/github/hapjava/server/impl/HomekitRoot.java
index 36bfeefa2..884ed9268 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitRoot.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitRoot.java
@@ -38,6 +38,7 @@ public class HomekitRoot {
private int configurationIndex = 1;
private int nestedBatches = 0;
private boolean madeChanges = false;
+ private int stateIndex = 1;
HomekitRoot(
String label, HomekitWebHandler webHandler, InetAddress host, HomekitAuthInfo authInfo)
@@ -94,13 +95,17 @@ public class HomekitRoot {
* completeUpdateBatch in order to publish all accumulated changes.
*/
public synchronized void batchUpdate() {
- if (this.nestedBatches == 0) madeChanges = false;
+ if (this.nestedBatches == 0) {
+ madeChanges = false;
+ }
++this.nestedBatches;
}
/** Publish accumulated accessory changes since batchUpdate() was called. */
public synchronized void completeUpdateBatch() {
- if (--this.nestedBatches == 0 && madeChanges) registry.reset();
+ if (--this.nestedBatches == 0 && madeChanges) {
+ registry.reset();
+ }
}
/**
@@ -176,7 +181,8 @@ public void start() {
authInfo.getMac(),
port,
configurationIndex,
- authInfo.getSetupId());
+ authInfo.getSetupId(),
+ this.stateIndex);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -232,7 +238,14 @@ public void setConfigurationIndex(int revision) throws IOException {
}
}
- HomekitRegistry getRegistry() {
+ public void setStateIndex(int stateIndex) throws IOException {
+ this.stateIndex = stateIndex;
+ if (this.started) {
+ advertiser.setStateIndex(stateIndex);
+ }
+ }
+
+ public HomekitRegistry getRegistry() {
return registry;
}
}
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitServer.java b/src/main/java/io/github/hapjava/server/impl/HomekitServer.java
index fc8ecaf76..b65659a11 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitServer.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitServer.java
@@ -27,6 +27,9 @@
*/
public class HomekitServer {
+ public static final String PROTOCOL_VERSION = "1.1.0";
+ public static final String PROTOCOL_VERSION_BONJOUR = "1.1";
+
private final HomekitHttpServer http;
private final InetAddress localAddress;
private final JmDNS jmdns;
@@ -117,13 +120,15 @@ public HomekitStandaloneAccessoryServer createStandaloneAccessory(
return new HomekitStandaloneAccessoryServer(accessory, http, localAddress, authInfo);
}
}
+
public HomekitStandaloneAccessoryServer createStandaloneAccessory(
HomekitAuthInfo authInfo, HomekitAccessory accessory, int category)
throws IOException, ExecutionException, InterruptedException {
if (jmdns != null) {
return new HomekitStandaloneAccessoryServer(accessory, http, jmdns, authInfo, category);
} else {
- return new HomekitStandaloneAccessoryServer(accessory, http, localAddress, authInfo, category);
+ return new HomekitStandaloneAccessoryServer(
+ accessory, http, localAddress, authInfo, category);
}
}
@@ -163,7 +168,13 @@ public HomekitRoot createBridge(
}
root.addAccessory(
new HomekitBridge(
- label, serialNumber, model, manufacturer, firmwareRevision, hardwareRevision));
+ label,
+ serialNumber,
+ model,
+ manufacturer,
+ firmwareRevision,
+ hardwareRevision,
+ PROTOCOL_VERSION));
return root;
}
diff --git a/src/main/java/io/github/hapjava/server/impl/HomekitStandaloneAccessoryServer.java b/src/main/java/io/github/hapjava/server/impl/HomekitStandaloneAccessoryServer.java
index 99ff7b746..4a5dbabee 100644
--- a/src/main/java/io/github/hapjava/server/impl/HomekitStandaloneAccessoryServer.java
+++ b/src/main/java/io/github/hapjava/server/impl/HomekitStandaloneAccessoryServer.java
@@ -40,7 +40,7 @@ public class HomekitStandaloneAccessoryServer {
root = new HomekitRoot(accessory.getName().get(), webHandler, jmdns, authInfo);
root.addAccessory(accessory);
}
-
+
HomekitStandaloneAccessoryServer(
HomekitAccessory accessory,
HomekitWebHandler webHandler,
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/connections/PendingNotification.java b/src/main/java/io/github/hapjava/server/impl/connections/PendingNotification.java
index ea9c69305..85397f5bb 100644
--- a/src/main/java/io/github/hapjava/server/impl/connections/PendingNotification.java
+++ b/src/main/java/io/github/hapjava/server/impl/connections/PendingNotification.java
@@ -3,11 +3,11 @@
import io.github.hapjava.characteristics.EventableCharacteristic;
public class PendingNotification {
- public int aid;
+ public long aid;
public int iid;
public EventableCharacteristic characteristic;
- public PendingNotification(int aid, int iid, EventableCharacteristic characteristic) {
+ public PendingNotification(long aid, int iid, EventableCharacteristic characteristic) {
this.aid = aid;
this.iid = iid;
this.characteristic = characteristic;
diff --git a/src/main/java/io/github/hapjava/server/impl/connections/SubscriptionManager.java b/src/main/java/io/github/hapjava/server/impl/connections/SubscriptionManager.java
index 9399295fb..4eeba81ac 100644
--- a/src/main/java/io/github/hapjava/server/impl/connections/SubscriptionManager.java
+++ b/src/main/java/io/github/hapjava/server/impl/connections/SubscriptionManager.java
@@ -22,9 +22,10 @@ public class SubscriptionManager {
private static class ConnectionsWithIds {
Set connections;
- int aid, iid;
+ long aid;
+ int iid;
- ConnectionsWithIds(int aid, int iid) {
+ ConnectionsWithIds(long aid, int iid) {
this.aid = aid;
this.iid = iid;
this.connections = new HashSet<>();
@@ -39,7 +40,7 @@ private static class ConnectionsWithIds {
private int nestedBatches = 0;
public synchronized void addSubscription(
- int aid,
+ long aid,
int iid,
EventableCharacteristic characteristic,
HomekitClientConnection connection) {
@@ -139,7 +140,7 @@ private void flushUpdateBatch() {
pendingNotifications.clear();
}
- public synchronized void publish(int accessoryId, int iid, EventableCharacteristic changed) {
+ public synchronized void publish(long accessoryId, int iid, EventableCharacteristic changed) {
final ConnectionsWithIds subscribers = subscriptions.get(changed);
if (subscribers == null || subscribers.connections.isEmpty()) {
LOGGER.trace("No subscribers to characteristic {} at accessory {} ", changed, accessoryId);
@@ -233,7 +234,7 @@ public synchronized void resync(HomekitRegistry registry) {
subscriptions.putAll(newSubscriptions);
}
- private void subscribe(int aid, int iid, EventableCharacteristic characteristic) {
+ private void subscribe(long aid, int iid, EventableCharacteristic characteristic) {
characteristic.subscribe(
() -> {
publish(aid, iid, characteristic);
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..d616d2e0f 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];
diff --git a/src/main/java/io/github/hapjava/server/impl/http/impl/AccessoryHandler.java b/src/main/java/io/github/hapjava/server/impl/http/impl/AccessoryHandler.java
index 6b840c713..ede93d271 100644
--- a/src/main/java/io/github/hapjava/server/impl/http/impl/AccessoryHandler.java
+++ b/src/main/java/io/github/hapjava/server/impl/http/impl/AccessoryHandler.java
@@ -42,6 +42,7 @@ public void channelActive(ChannelHandlerContext ctx) throws Exception {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ this.connection.close();
LOGGER.trace("Terminated HomeKit connection from " + ctx.channel().remoteAddress().toString());
super.channelInactive(ctx);
}
diff --git a/src/main/java/io/github/hapjava/server/impl/http/impl/HomekitHttpServer.java b/src/main/java/io/github/hapjava/server/impl/http/impl/HomekitHttpServer.java
index 085d632cf..3eef12c2b 100644
--- a/src/main/java/io/github/hapjava/server/impl/http/impl/HomekitHttpServer.java
+++ b/src/main/java/io/github/hapjava/server/impl/http/impl/HomekitHttpServer.java
@@ -17,6 +17,7 @@ public void stop() {
if (this.service != null) {
this.service.shutdown();
}
+ this.service = null;
}
public HomekitHttpServer(InetAddress localAddress, int port, int nThreads) {
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 9086acb3e..eb78c854d 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
@@ -20,6 +20,7 @@ public class JmdnsHomekitAdvertiser {
private boolean discoverable = true;
private static final Logger logger = LoggerFactory.getLogger(JmdnsHomekitAdvertiser.class);
private boolean isAdvertising = false;
+ private boolean isStarted = false;
private String label;
private String mac;
@@ -28,6 +29,7 @@ public class JmdnsHomekitAdvertiser {
private int configurationIndex;
private ServiceInfo serviceInfo;
private int category;
+ private int stateIndex = 1;
public JmdnsHomekitAdvertiser(JmDNS jmdns) {
this.jmdns = jmdns;
@@ -38,7 +40,13 @@ public JmdnsHomekitAdvertiser(InetAddress localAddress) throws UnknownHostExcept
}
public synchronized void advertise(
- String label, int category, String mac, int port, int configurationIndex, String setupId)
+ String label,
+ int category,
+ String mac,
+ int port,
+ int configurationIndex,
+ String setupId,
+ int stateIndex)
throws Exception {
if (isAdvertising) {
throw new IllegalStateException("HomeKit advertiser is already running");
@@ -49,11 +57,17 @@ public synchronized void advertise(
this.setupId = setupId;
this.category = category;
this.configurationIndex = configurationIndex;
+ this.stateIndex = stateIndex;
logger.trace("Advertising accessory " + label);
registerService();
+ if (isStarted) {
+ return;
+ }
+ this.isStarted = true;
+
Runtime.getRuntime()
.addShutdownHook(
new Thread(
@@ -61,13 +75,16 @@ public synchronized void advertise(
logger.trace("Stopping advertising in response to shutdown.");
jmdns.unregisterAllServices();
}));
- isAdvertising = true;
}
public synchronized void stop() {
unregisterService();
}
+ public void setStateIndex(int stateIndex) {
+ this.stateIndex = stateIndex;
+ }
+
public synchronized void setDiscoverable(boolean discoverable) throws IOException {
if (this.discoverable != discoverable) {
this.discoverable = discoverable;
@@ -102,20 +119,14 @@ public synchronized void setConfigurationIndex(int revision) throws IOException
}
private void unregisterService() {
- if (serviceInfo != null) {
- jmdns.unregisterService(serviceInfo);
- serviceInfo = null;
- }
+ jmdns.unregisterService(buildServiceInfo());
+ isAdvertising = false;
}
private void registerService() throws IOException {
logger.info("Registering " + SERVICE_TYPE + " on port " + port);
- if (this.serviceInfo != null) {
- throw new AssertionError(
- "Registering an already registered service without unregistering first is not allowed");
- }
- serviceInfo = buildServiceInfo();
- jmdns.registerService(serviceInfo);
+ jmdns.registerService(buildServiceInfo());
+ isAdvertising = true;
}
private ServiceInfo buildServiceInfo() {
@@ -126,7 +137,7 @@ private ServiceInfo buildServiceInfo() {
props.put("md", label);
props.put("sh", generateSHA512Hash(setupId + mac));
props.put("c#", Integer.toString(configurationIndex));
- props.put("s#", "1");
+ props.put("s#", Integer.toString(stateIndex));
props.put("ff", "0");
props.put("ci", Integer.toString(category));
props.put("pv", "1.1");
diff --git a/src/main/java/io/github/hapjava/server/impl/json/AccessoryController.java b/src/main/java/io/github/hapjava/server/impl/json/AccessoryController.java
index fdd223ec3..742bc65ca 100644
--- a/src/main/java/io/github/hapjava/server/impl/json/AccessoryController.java
+++ b/src/main/java/io/github/hapjava/server/impl/json/AccessoryController.java
@@ -31,7 +31,7 @@ public AccessoryController(HomekitRegistry registry) {
public HttpResponse listing() throws Exception {
JsonArrayBuilder accessories = Json.createArrayBuilder();
- Map>> accessoryServiceFutures = new HashMap<>();
+ Map>> accessoryServiceFutures = new HashMap<>();
for (HomekitAccessory accessory : registry.getAccessories()) {
List> serviceFutures = new ArrayList<>();
@@ -48,8 +48,8 @@ public HttpResponse listing() throws Exception {
accessoryServiceFutures.put(accessory.getId(), serviceFutures);
}
- Map serviceArrayBuilders = new HashMap<>();
- for (Entry>> entry :
+ Map serviceArrayBuilders = new HashMap<>();
+ for (Entry>> entry :
accessoryServiceFutures.entrySet()) {
JsonArrayBuilder arr = Json.createArrayBuilder();
for (CompletableFuture future : entry.getValue()) {
diff --git a/src/main/java/io/github/hapjava/server/impl/json/CharacteristicsController.java b/src/main/java/io/github/hapjava/server/impl/json/CharacteristicsController.java
index d061a11fc..f30b5ee34 100644
--- a/src/main/java/io/github/hapjava/server/impl/json/CharacteristicsController.java
+++ b/src/main/java/io/github/hapjava/server/impl/json/CharacteristicsController.java
@@ -39,7 +39,7 @@ public HttpResponse get(HttpRequest request) throws Exception {
logger.warn("Unexpected characteristics request: " + uri);
return new NotFoundResponse();
}
- int aid = Integer.parseInt(parts[0]);
+ long aid = Long.parseLong(parts[0]);
int iid = Integer.parseInt(parts[1]);
JsonObjectBuilder characteristic = Json.createObjectBuilder();
Map characteristicMap = registry.getCharacteristics(aid);
@@ -75,7 +75,7 @@ public HttpResponse put(HttpRequest request, HomekitClientConnection connection)
Json.createReader(bais).readObject().getJsonArray("characteristics");
for (JsonValue value : jsonCharacteristics) {
JsonObject jsonCharacteristic = (JsonObject) value;
- int aid = jsonCharacteristic.getInt("aid");
+ long aid = jsonCharacteristic.getJsonNumber("aid").longValue();
int iid = jsonCharacteristic.getInt("iid");
Map accessory = registry.getCharacteristics(aid);
if (accessory.isEmpty()) {
diff --git a/src/main/java/io/github/hapjava/server/impl/json/EventController.java b/src/main/java/io/github/hapjava/server/impl/json/EventController.java
index 0c7c2bc7c..2f99a6ae9 100644
--- a/src/main/java/io/github/hapjava/server/impl/json/EventController.java
+++ b/src/main/java/io/github/hapjava/server/impl/json/EventController.java
@@ -13,7 +13,7 @@
public class EventController {
- public HttpResponse getMessage(int accessoryId, int iid, EventableCharacteristic changed)
+ public HttpResponse getMessage(long accessoryId, long iid, EventableCharacteristic changed)
throws Exception {
JsonArrayBuilder characteristics = Json.createArrayBuilder();
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..87ddf3907 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
@@ -8,9 +8,7 @@
class ClientEvidenceRoutineImpl implements ClientEvidenceRoutine {
- public ClientEvidenceRoutineImpl() {
- // TODO Auto-generated constructor stub
- }
+ public ClientEvidenceRoutineImpl() {}
/**
* Calculates M1 according to the following formula:
@@ -27,10 +25,10 @@ public BigInteger computeClientEvidence(
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Could not locate requested algorithm", e);
}
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.N));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(cryptoParams.N));
byte[] hN = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(cryptoParams.g));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(cryptoParams.g));
byte[] hg = digest.digest();
byte[] hNhg = xor(hN, hg);
@@ -38,14 +36,14 @@ public BigInteger computeClientEvidence(
digest.update(ctx.userID.getBytes(StandardCharsets.UTF_8));
byte[] hu = digest.digest();
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.S));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(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(BigIntegerUtils.bigIntegerToBytes(ctx.s));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.A));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(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/PairVerifyManager.java b/src/main/java/io/github/hapjava/server/impl/pairing/PairVerifyManager.java
index 44f25c6d1..5042132b3 100644
--- a/src/main/java/io/github/hapjava/server/impl/pairing/PairVerifyManager.java
+++ b/src/main/java/io/github/hapjava/server/impl/pairing/PairVerifyManager.java
@@ -14,6 +14,7 @@
import io.github.hapjava.server.impl.pairing.TypeLengthValueUtils.DecodeResult;
import io.github.hapjava.server.impl.pairing.TypeLengthValueUtils.Encoder;
import io.github.hapjava.server.impl.responses.NotFoundResponse;
+import io.github.hapjava.server.impl.responses.OkResponse;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import org.bouncycastle.crypto.digests.SHA512Digest;
@@ -114,8 +115,13 @@ private HttpResponse handleVerifyFinishRequest(VerifyFinishRequest request) thro
}
Encoder encoder = TypeLengthValueUtils.getEncoder();
+ encoder.add(MessageType.STATE, (short) 4);
+ if (clientLtpk == null) {
+ logger.error("Unknown user: {}", new String(clientUsername, StandardCharsets.UTF_8));
+ return new OkResponse(encoder.toByteArray());
+ }
+
if (new EdsaVerifier(clientLtpk).verify(material, clientSignature)) {
- encoder.add(MessageType.STATE, (short) 4);
logger.trace("Completed pair verification for " + registry.getLabel());
return new UpgradeResponse(
encoder.toByteArray(),
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..6c032ce59 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,6 @@
package io.github.hapjava.server.impl.pairing;
+import com.nimbusds.srp6.BigIntegerUtils;
import com.nimbusds.srp6.SRP6CryptoParams;
import com.nimbusds.srp6.SRP6ServerEvidenceContext;
import com.nimbusds.srp6.ServerEvidenceRoutine;
@@ -20,10 +21,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(BigIntegerUtils.bigIntegerToBytes(ctx.S));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.A));
- digest.update(SrpHandler.bigIntegerToUnsignedByteArray(ctx.M1));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(ctx.A));
+ digest.update(BigIntegerUtils.bigIntegerToBytes(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 5c1c23353..334d44f7f 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
@@ -82,7 +82,7 @@ private HttpResponse handleSrpVerifyRequest(SRPVerifyRequest request) throws Exc
public byte[] getK() {
MessageDigest digest = session.getCryptoParams().getMessageDigestInstance();
- BigInteger S = session.getSessionKey(false);
+ BigInteger S = session.getSessionKey();
byte[] sBytes = bigIntegerToUnsignedByteArray(S);
return digest.digest(sBytes);
}
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 cbd76f118..0f2e8efac 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
@@ -1,5 +1,6 @@
package io.github.hapjava.server.impl.pairing;
+import com.nimbusds.srp6.BigIntegerUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -45,7 +46,7 @@ public void add(MessageType type) {
}
public void add(MessageType type, BigInteger i) throws IOException {
- add(type, ByteUtils.toByteArray(i));
+ add(type, BigIntegerUtils.bigIntegerToBytes(i));
}
public void add(MessageType type, short b) {
diff --git a/src/main/java/io/github/hapjava/services/impl/ProtocolInformationService.java b/src/main/java/io/github/hapjava/services/impl/ProtocolInformationService.java
new file mode 100644
index 000000000..2be2f346b
--- /dev/null
+++ b/src/main/java/io/github/hapjava/services/impl/ProtocolInformationService.java
@@ -0,0 +1,20 @@
+package io.github.hapjava.services.impl;
+
+import static io.github.hapjava.server.impl.HomekitServer.PROTOCOL_VERSION;
+
+import io.github.hapjava.accessories.HomekitAccessory;
+import io.github.hapjava.characteristics.impl.common.VersionCharacteristic;
+import java.util.concurrent.CompletableFuture;
+
+/** Accessory Information service. */
+public class ProtocolInformationService extends AbstractServiceImpl {
+
+ public ProtocolInformationService(VersionCharacteristic version) {
+ super("000000A2‐0000‐1000‐8000‐0026BB765291");
+ addCharacteristic(version);
+ }
+
+ public ProtocolInformationService(HomekitAccessory accessory) {
+ this(new VersionCharacteristic(() -> CompletableFuture.completedFuture(PROTOCOL_VERSION)));
+ }
+}
diff --git a/src/test/java/io/github/hapjava/server/impl/HomekitRootTest.java b/src/test/java/io/github/hapjava/server/impl/HomekitRootTest.java
index 81d2666e5..2c93e9fd9 100644
--- a/src/test/java/io/github/hapjava/server/impl/HomekitRootTest.java
+++ b/src/test/java/io/github/hapjava/server/impl/HomekitRootTest.java
@@ -1,5 +1,8 @@
package io.github.hapjava.server.impl;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -14,9 +17,8 @@
import io.github.hapjava.server.impl.http.HomekitClientConnectionFactory;
import io.github.hapjava.server.impl.jmdns.JmdnsHomekitAdvertiser;
import java.util.concurrent.CompletableFuture;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
public class HomekitRootTest {
@@ -31,10 +33,10 @@ public class HomekitRootTest {
private static final String LABEL = "Test Label";
- @Before
+ @BeforeEach
public void setup() throws Exception {
accessory = mock(HomekitAccessory.class);
- when(accessory.getId()).thenReturn(2);
+ when(accessory.getId()).thenReturn(2l);
webHandler = mock(HomekitWebHandler.class);
when(webHandler.start(any())).thenReturn(CompletableFuture.completedFuture(PORT));
advertiser = mock(JmdnsHomekitAdvertiser.class);
@@ -46,18 +48,18 @@ public void setup() throws Exception {
@Test
public void verifyRegistryAdded() throws Exception {
root.addAccessory(accessory);
- Assert.assertTrue(
- "Registry does not contain accessory",
- root.getRegistry().getAccessories().contains(accessory));
+ assertTrue(
+ root.getRegistry().getAccessories().contains(accessory),
+ "Registry does not contain accessory");
}
@Test
public void verifyRegistryRemoved() throws Exception {
root.addAccessory(accessory);
root.removeAccessory(accessory);
- Assert.assertFalse(
- "Registry still contains accessory",
- root.getRegistry().getAccessories().contains(accessory));
+ assertFalse(
+ root.getRegistry().getAccessories().contains(accessory),
+ "Registry still contains accessory");
}
@Test
@@ -80,7 +82,7 @@ public void testAdvertiserStarts() throws Exception {
when(authInfo.getSetupId()).thenReturn(SETUPID);
root.start();
- verify(advertiser).advertise(eq(LABEL), eq(1), eq(mac), eq(PORT), eq(1), eq(SETUPID));
+ verify(advertiser).advertise(eq(LABEL), eq(1), eq(mac), eq(PORT), eq(1), eq(SETUPID), eq(1));
}
@Test
@@ -105,9 +107,13 @@ public void testRemoveAccessoryDoesntResetWeb() {
verify(webHandler, never()).resetConnections();
}
- @Test(expected = IndexOutOfBoundsException.class)
+ @Test
public void testAddIndexOneAccessory() throws Exception {
- when(accessory.getId()).thenReturn(1);
- root.addAccessory(accessory);
+ assertThrows(
+ IndexOutOfBoundsException.class,
+ () -> {
+ when(accessory.getId()).thenReturn(1l);
+ root.addAccessory(accessory);
+ });
}
}
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
index 870bd739b..c58b37782 100644
--- a/src/test/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiserTest.java
+++ b/src/test/java/io/github/hapjava/server/impl/jmdns/JmdnsHomekitAdvertiserTest.java
@@ -9,8 +9,8 @@
import java.net.UnknownHostException;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
public class JmdnsHomekitAdvertiserTest {
@@ -18,7 +18,7 @@ public class JmdnsHomekitAdvertiserTest {
JmdnsHomekitAdvertiser subject;
JmDNS jmdns;
- @Before
+ @BeforeEach
public void setup() throws UnknownHostException, IOException {
jmdns = mock(JmDNS.class);
subject = new JmdnsHomekitAdvertiser(jmdns);
@@ -39,7 +39,7 @@ public void testSetDiscoverableAfterAdvertise() throws Exception {
subject.setDiscoverable(false);
advertise();
subject.setDiscoverable(true);
- assertThat(getArgumentFromUnregister().getPropertyString("sf")).isEqualTo("0");
+ assertThat(getArgumentFromUnregister().getPropertyString("sf")).isEqualTo("1");
}
/*
@@ -51,7 +51,7 @@ public void testSetConfigurationIndex() throws Exception {
subject.setConfigurationIndex(1);
advertise();
subject.setConfigurationIndex(2);
- assertThat(getArgumentFromUnregister().getPropertyString("c#")).isEqualTo("1");
+ assertThat(getArgumentFromUnregister().getPropertyString("c#")).isEqualTo("2");
}
private ServiceInfo getArgumentFromUnregister() {
@@ -61,6 +61,6 @@ private ServiceInfo getArgumentFromUnregister() {
}
private void advertise() throws Exception {
- subject.advertise("test", 1, "00:00:00:00:00:00", 1234, 1, "1");
+ subject.advertise("test", 1, "00:00:00:00:00:00", 1234, 1, "1", 1);
}
}