Skip to content

Commit

Permalink
Merge 89cb5d8 into 96d278a
Browse files Browse the repository at this point in the history
  • Loading branch information
seime authored Jul 22, 2024
2 parents 96d278a + 89cb5d8 commit c4ec44a
Show file tree
Hide file tree
Showing 18 changed files with 830 additions and 105 deletions.
41 changes: 25 additions & 16 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [ "*" ]
push:
branches:
- "!master"
- "!master"

jobs:

Expand All @@ -19,19 +19,28 @@ jobs:
name: Build OH4 (Java ${{ matrix.java }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ${{matrix.java}}
distribution: 'temurin'
- name: Cache local Maven repository
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.java }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.java }}-maven-
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ${{matrix.java}}
distribution: 'temurin'
- name: Cache local Maven repository
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.java }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.java }}-maven-
- name: Build
run: mvn -P 'standalone' --batch-mode -DskipChecks -Doh.java.version=17 clean verify
- name: Build
run: mvn -P 'standalone' --batch-mode -DskipChecks -Doh.java.version=17 clean verify

- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: ${{ github.head_ref || github.ref_name }}
prerelease: true
title: "Latest Build"
files: |
target/*.jar
191 changes: 120 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,120 @@ Read more here: https://esphome.io/components/api#advantages-over-mqtt
> **Note:** At the current state of the binding, it is highly recommended to use file based configuration for things and
> items as channel types etc most likely will change.
## Streaming device logs
## Discovery

The binding uses mDNS to automatically discover devices on the network.

## Thing Configuration

### `device` Thing Configuration

| Name | Type | Description | Default | Required | Advanced |
|------------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|----------|
| `hostname` | `text` | Hostname or IP address of the device. Typically something like 'myboard.local' | N/A | yes | no |
| `port` | `integer` | IP Port of the device | 6053 | no | no |
| `encryptionKey` | `text` | Encryption key as defined in `api: encryption: key: <BASE64ENCODEDKEY>`. See https://esphome.io/components/api#configuration-variables | N/A | no | no |
| ~~`password`~~ | `text` | Password to access the device if password protected. **DEPRECATED. Use `encryptionKey` instead** | N/A | no | no |
| `enableBluetoothProxy` | `boolean` | Allow this device to proxy Bluetooth traffic. Requires ESPHome device to be configured with `bluetooth_proxy` | false | no | no |
| `pingInterval` | `integer` | Seconds between sending ping requests to device to check if alive | 10 | no | yes |
| `maxPingTimeouts` | `integer` | Number of missed ping requests before deeming device unresponsive. | 4 | no | yes |
| `server` | `text` | Expected name of ESPHome. Used to ensure that we're communicating with the correct device. Use value from `esphome.name` in ESPHome device configuration | | no | yes |
| `logPrefix` | `text` | Log prefix to use for this device. | hostname | no | yes |
| `deviceLogLevel` | `text` | ESPHome device log level to stream from the device. | NONE | no | yes |

## Channels

Channels are auto-generated based on actual device configuration.

## Full Example file example

### Thing Configuration for ESPHome device

```
esphome:device:esp1 "ESPHome Test card 1" [ hostname="testkort1.local", encryptionKey="JVWAgubY1nCe3x/5xeyMBfaN9y68OOUMh5dACIeVmjk=", pingInterval=10, maxPingTimeouts=4, server="esphomename", logPrefix="esp1", deviceLogLevel="INFO"]
```

### Item Configuration

```
Number:Temperature ESP1_Temperature "Temperature" <temperature> {channel="esphome:device:esp1:temperature"}
Number:Dimensionless ESP1_Humidity "Humidity" <humidity> {channel="esphome:device:esp1:humidity"}
Switch ESP1_Switch "Relay" <switch> {channel="esphome:device:esp1:relay_4"}
```

## Bluetooth proxy support

It is now possible to utilize the built-in Bluetooth proxy in ESPHome. This allows you to use ESPHome devices as proxies
for other Bluetooth devices such as BTHome sensors or a range of other Bluetooth devices.

> NOTE: Only beacons / devices broadcasting data are supported at the moment. Connectable devices will be supported in a
> future release.
The feature is still experimental and may not work as expected.

1. Configure the ESPHome device with the `bluetooth_proxy` component. See https://esphome.io/components/bluetooth_proxy

```yaml
bluetooth_proxy:
active: true
```
2. Configure the ESPHome `device` in openHAB with `enableBluetoothProxy = true`

```yaml
esphome:device:esp1 "ESPHome Test card 1" [ ... enableBluetoothProxy=true ]
```

3. Configure a Bluetooth Proxy bridge of type `esphome`

This is the standard configuration for any type of Bluetooth adapter in openHAB (not documented elsewhere)

| Name | Type | Description | Default | Required | Advanced |
|----------------------------------|-----------|-----------------------------------------------------------------------------|---------|----------|----------|
| `backgroundDiscovery` | `boolean` | Add discovered device automatically to tihe inbox in the background | false | no | no |
| `inactiveDeviceCleanupInterval` | `integer` | Number of seconds of Bluetooth device inactivity before removing from inbox | 60 | no | no |
| `inactiveDeviceCleanupThreshold` | `integer` | | 300 | no | no |

```
Bridge bluetooth:esphome:proxy "ESPHome BLE Advertisement listener" [backgroundDiscovery = false] {
bthome parasite1 "b-Parasite #4354" [address="XX:XX:XX:XX:18:91", expectedReportingIntervalSeconds = 600]
}
```
> **NOTE:** Set backgroundDiscovery to true if you want to automatically add discovered devices to the inbox. If not use
> manual
> scanning from the inbox.
## FAQ
- I get warnings
like `No device_class reported by sensor '<name of sensor>'. Add device_class to sensor configuration in ESPHome. Defaulting to plain Number without dimension`
> This is because the ESP sensor does not report a `device_class`. This field is used to determine item and category
> type in openHAB.
> Solution: Specify a `device_class` to your ESPHome configuration. Example: <br/>
> ![img.png](esphomeconfig_deviceclass.png)
> <br/>See https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes for valid
device_class values (**use lowercase values**)
> Also note that you may override default device_class by specifying `device_class: ""` to remove any device class
from the sensor.
Also see https://community.openhab.org/t/esphome-binding-for-the-native-api/146849/1 for more information.
## Limitations as of 2024-06-17
Most entity types and functions are now supported. However, there are some limitations:
The following entity types are **not** yet supported (please submit a PR of file a feature request!)
- `lock`,
- `camera`
- `voice`
- `valve`
In addition, the Bluetooth proxy isn't fully ready yet.
## Streaming logs from ESPHome device to openHAB
As an alternative to manually streaming device logs via ESPHome dashboard, you can have openHAB stream
the device logs directly to openHAB - which will write them using the standard log system.
Expand Down Expand Up @@ -67,10 +180,14 @@ log:set INFO ESPHOMEDEVICE
This will produce logs on level `INFO` in the openHAB logs like this:

```
[2024-04-04 15:06:25.822] [varmtvann] [D][dallas.sensor:143]: 'VV Temp bunn': Got Temperature=21.0°C
[2024-04-04 15:06:25.834] [varmtvann] [D][sensor:094]: 'VV Temp bunn': Sending state 21.00000 °C with 1 decimals of accuracy
[2024-04-04 15:06:25.834] [varmtvann] [D][sensor:094]: 'VV Temp bunn': Sending state 21.00000 °C with 1 decimals of
accuracy
[2024-04-04 15:06:25.850] [varmtvann] [D][dallas.sensor:143]: 'VV Temp midt': Got Temperature=71.7°C
[2024-04-04 15:06:25.863] [varmtvann] [D][sensor:094]: 'VV Temp midt': Sending state 71.68750 °C with 1 decimals of accuracy
[2024-04-04 15:06:25.863] [varmtvann] [D][sensor:094]: 'VV Temp midt': Sending state 71.68750 °C with 1 decimals of
accuracy
```

To redirect device logs to a separate log file, edit your `log4j.xml` file and add the following in the `<Appenders>`
Expand Down Expand Up @@ -173,71 +290,3 @@ sensor:
icon: "mdi:counter"
```

## FAQ

- I get warnings
like `No device_class reported by sensor '<name of sensor>'. Add device_class to sensor configuration in ESPHome. Defaulting to plain Number without dimension`

> This is because the ESP sensor does not report a `device_class`. This field is used to determine item and category
> type in openHAB.
> Solution: Specify a `device_class` to your ESPHome configuration. Example: <br/>
> ![img.png](esphomeconfig_deviceclass.png)
> <br/>See https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes for valid
device_class values (**use lowercase values**)
> Also note that you may override default device_class by specifying `device_class: ""` to remove any device class
from the sensor.

Also see https://community.openhab.org/t/esphome-binding-for-the-native-api/146849/1 for more information.

## Limitations as of 2024-06-17

Most entity types and functions are now supported. However, there are some limitations:

The following entity types are **not** yet supported (please submit a PR of file a feature request!)

- `lock`,
- `camera`
- `voice`
- `valve`

In addition, the Bluetooth proxy isn't ready yet.

## Discovery

The binding uses mDNS to automatically discover devices on the network.

## Thing Configuration

### `device` Thing Configuration

| Name | Type | Description | Default | Required | Advanced |
|-------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------------|----------|----------|----------|
| `hostname` | `text` | Hostname or IP address of the device. Typically something like 'myboard.local' | N/A | yes | no |
| `port` | `integer` | IP Port of the device | 6053 | no | no |
| `encryptionKey` | `text` | Encryption key as defined in `api: encryption: key: <BASE64ENCODEDKEY>`. See https://esphome.io/components/api#configuration-variables | N/A | no | no |
| ~~`password`~~ | `text` | Password to access the device if password protected. **DEPRECATED. Use `encryptionKey` instead** | N/A | no | no |
| `pingInterval` | `integer` | Seconds between sending ping requests to device to check if alive | 10 | no | yes |
| `maxPingTimeouts` | `integer` | Number of missed ping requests before deeming device unresponsive. | 4 | no | yes |
| `server` | `text` | Expected name of ESPHome. Used to ensure that we're communicating with the correct device | | no | yes |
| `logPrefix` | `text` | Log prefix to use for this device. | hostname | no | yes |
| `deviceLogLevel` | `text` | ESPHome device log level to stream from the device. | NONE | no | yes |

## Channels

Channels are auto-generated based on actual device configuration.

## Full Example

### Thing Configuration

```
esphome:device:esp1 "ESPHome Test card 1" [ hostname="testkort1.local", encryptionKey="JVWAgubY1nCe3x/5xeyMBfaN9y68OOUMh5dACIeVmjk=", pingInterval=10, maxPingTimeouts=4, server="esphomename", logPrefix="esp1", deviceLogLevel="INFO"]
```
### Item Configuration
```
Number:Temperature ESP1_Temperature "Temperature" <temperature> {channel="esphome:device:esp1:temperature"}
Number:Dimensionless ESP1_Humidity "Humidity" <humidity> {channel="esphome:device:esp1:humidity"}
Switch ESP1_Switch "Relay" <switch> {channel="esphome:device:esp1:relay_4"}
```
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.bluetooth</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>


<dependency>
<groupId>org.slf4j</groupId>
Expand Down Expand Up @@ -149,6 +156,7 @@
<protocArtifact>com.google.protobuf:protoc:${proto.version}:exe:${os.detected.classifier}</protocArtifact>
<attachProtoSources>false</attachProtoSources>
<useArgumentFile>true</useArgumentFile>
<checkStaleness>true</checkStaleness>
</configuration>
</execution>
</executions>
Expand Down
3 changes: 2 additions & 1 deletion src/main/feature/feature.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-mdns</feature>

<bundle start-level="80">mvn:org.openhab.addons.bundles/no.seime.openhab.binding.esphome/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version}</bundle>
<bundle start-level="81">mvn:org.openhab.addons.bundles/no.seime.openhab.binding.esphome/${project.version}</bundle>
</feature>
</features>
1 change: 1 addition & 0 deletions src/main/history/dependencies.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<feature>wrap</feature>
<bundle>mvn:com.google.protobuf/protobuf-java/3.25.2</bundle>
<bundle>mvn:org.openhab.addons.bundles/no.seime.openhab.binding.esphome/4.1.0-SNAPSHOT</bundle>
<bundle>mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/4.1.0-SNAPSHOT</bundle>
<bundle>wrap:mvn:org.lastnpe.eea/eea-all/2.2.1</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class BindingConstants {

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device");
public static final ThingTypeUID THING_TYPE_BLE_PROXY = new ThingTypeUID("bluetooth", "esphome");

public static final String COMMAND_KEY = "command_key";
public static final String COMMAND_CLASS = "command_class";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ public class ESPHomeConfiguration {
public String logPrefix;

public LogLevel deviceLogLevel = LogLevel.NONE;

public boolean enableBluetoothProxy = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package no.seime.openhab.binding.esphome.internal.bluetooth;

import java.util.HexFormat;

import org.openhab.binding.bluetooth.BluetoothAddress;

public class BluetoothAddressUtil {
public static BluetoothAddress createAddress(long address) {
String hexDigits = HexFormat.of().toHexDigits(address);

StringBuilder addressBuilder = new StringBuilder();

// Skip first 2 bytes as addresses are 48 bits and not 64 bits
for (int i = 4; i < hexDigits.length(); i += 2) {
addressBuilder.append(hexDigits.substring(i, i + 2));
if (i < hexDigits.length() - 2) {
addressBuilder.append(":");
}
}

return new BluetoothAddress(addressBuilder.toString().toUpperCase());
}

public static long convertAddressToLong(BluetoothAddress address) {
String[] parts = address.toString().split(":");
long result = 0;
for (int i = 0; i < parts.length; i++) {
result = result << 8;
result |= Integer.parseInt(parts[i], 16);
}
return result;
}
}
Loading

0 comments on commit c4ec44a

Please sign in to comment.