Compare commits
No commits in common. "419f70d8d27d2cb89c3bfaca0a51a5f1eb5e7d7a" and "55ec47e3af30c2001b3ac0a3eba5bc4170117e9a" have entirely different histories.
419f70d8d2
...
55ec47e3af
|
@ -1,41 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
esphome:
|
|
||||||
name: arbeitszimmer-oben-ble-tracker
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
board: m5stack-atom
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
ota:
|
|
||||||
password: !secret ota_password
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: WLAN
|
|
||||||
password: !secret wifi_password
|
|
||||||
|
|
||||||
mqtt:
|
|
||||||
broker: homeassistant.fritz.box
|
|
||||||
username: !secret mqtt_ble_username
|
|
||||||
password: !secret mqtt_ble_password
|
|
||||||
discovery: false
|
|
||||||
|
|
||||||
esp32_ble_tracker:
|
|
||||||
scan_parameters:
|
|
||||||
interval: 1.2s
|
|
||||||
window: 500ms
|
|
||||||
active: false
|
|
||||||
on_ble_advertise:
|
|
||||||
- then:
|
|
||||||
- lambda: |-
|
|
||||||
auto build_json = [&](JsonObject obj) {
|
|
||||||
obj["rssi"] = x.get_rssi();
|
|
||||||
obj["address"] = x.address_str();
|
|
||||||
obj["address_uint64"] = x.address_uint64();
|
|
||||||
if(x.get_tx_powers().size() > 0)
|
|
||||||
obj["tx_power"] = x.get_tx_powers()[0];
|
|
||||||
};
|
|
||||||
global_mqtt_client->publish_json("my_btmonitor/raw_measurements/az_oben", build_json);
|
|
|
@ -111,13 +111,13 @@ packages:
|
||||||
name: "ventil-sprinkler-westen"
|
name: "ventil-sprinkler-westen"
|
||||||
dev_addr: 0x1
|
dev_addr: 0x1
|
||||||
register_addr: 0x03
|
register_addr: 0x03
|
||||||
relay04: !include
|
#relay04: !include
|
||||||
file: "modbus_relay.yaml"
|
# file: "modbus_relay.yaml"
|
||||||
vars:
|
# vars:
|
||||||
cid: relayboard32
|
# cid: relayboard32
|
||||||
name: "ventil-giessanlage-vorne"
|
# name: "ventil-gartenhaus-kein-rohr-angeschlossen"
|
||||||
dev_addr: 0x1
|
# dev_addr: 0x1
|
||||||
register_addr: 0x04
|
# register_addr: 0x04
|
||||||
relay05: !include
|
relay05: !include
|
||||||
file: "modbus_relay.yaml"
|
file: "modbus_relay.yaml"
|
||||||
vars:
|
vars:
|
||||||
|
@ -125,13 +125,13 @@ packages:
|
||||||
name: "ventil-sprinkler-sud"
|
name: "ventil-sprinkler-sud"
|
||||||
dev_addr: 0x1
|
dev_addr: 0x1
|
||||||
register_addr: 0x05
|
register_addr: 0x05
|
||||||
relay06: !include
|
#relay06: !include
|
||||||
file: "modbus_relay.yaml"
|
# file: "modbus_relay.yaml"
|
||||||
vars:
|
# vars:
|
||||||
cid: relayboard32
|
# cid: relayboard32
|
||||||
name: "ventil-beet-sued"
|
# name: "ventil-gartenhaus-kein-ventil-angeschlossen"
|
||||||
dev_addr: 0x1
|
# dev_addr: 0x1
|
||||||
register_addr: 0x06
|
# register_addr: 0x06
|
||||||
relay07: !include
|
relay07: !include
|
||||||
file: "modbus_relay.yaml"
|
file: "modbus_relay.yaml"
|
||||||
vars:
|
vars:
|
||||||
|
|
|
@ -18,6 +18,7 @@ api:
|
||||||
ota:
|
ota:
|
||||||
password: !secret ota_password
|
password: !secret ota_password
|
||||||
|
|
||||||
|
|
||||||
ethernet:
|
ethernet:
|
||||||
type: LAN8720
|
type: LAN8720
|
||||||
mdc_pin: GPIO23
|
mdc_pin: GPIO23
|
||||||
|
@ -153,30 +154,6 @@ binary_sensor:
|
||||||
device_class: LIGHT
|
device_class: LIGHT
|
||||||
|
|
||||||
|
|
||||||
mqtt:
|
|
||||||
broker: homeassistant.fritz.box
|
|
||||||
username: !secret mqtt_ble_username
|
|
||||||
password: !secret mqtt_ble_password
|
|
||||||
discovery: false
|
|
||||||
|
|
||||||
|
|
||||||
esp32_ble_tracker:
|
|
||||||
scan_parameters:
|
|
||||||
interval: 1.2s
|
|
||||||
window: 500ms
|
|
||||||
active: false
|
|
||||||
on_ble_advertise:
|
|
||||||
- then:
|
|
||||||
- lambda: |-
|
|
||||||
auto build_json = [&](JsonObject obj) {
|
|
||||||
obj["rssi"] = x.get_rssi();
|
|
||||||
obj["address"] = x.address_str();
|
|
||||||
obj["address_uint64"] = x.address_uint64();
|
|
||||||
if(x.get_tx_powers().size() > 0)
|
|
||||||
obj["tx_power"] = x.get_tx_powers()[0];
|
|
||||||
};
|
|
||||||
global_mqtt_client->publish_json("my_btmonitor/raw_measurements/garten", build_json);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ light:
|
||||||
id: gartenhaus_wandlicht
|
id: gartenhaus_wandlicht
|
||||||
name: Gartenhaus Wandlicht
|
name: Gartenhaus Wandlicht
|
||||||
pin: 3
|
pin: 3
|
||||||
num_leds: 306
|
num_leds: 305
|
||||||
is_rgbw: true
|
is_rgbw: true
|
||||||
rmt_channel: 0
|
rmt_channel: 0
|
||||||
effects:
|
effects:
|
||||||
|
|
104
m5stackfire.yaml
104
m5stackfire.yaml
|
@ -1,24 +1,8 @@
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: m5stackfire
|
name: m5stackfire
|
||||||
|
platform: ESP32
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/ssieb/custom_components
|
|
||||||
components: [ip5306]
|
|
||||||
- source:
|
|
||||||
type: local
|
|
||||||
path: ./my_components
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
board: m5stack-fire
|
board: m5stack-fire
|
||||||
flash_size: 16MB
|
|
||||||
#framework:
|
|
||||||
# type: arduino
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
psram:
|
|
||||||
|
|
||||||
substitutions:
|
substitutions:
|
||||||
friendly_name: "M5StackFire"
|
friendly_name: "M5StackFire"
|
||||||
|
@ -30,7 +14,6 @@ api:
|
||||||
- service: mhz19_calibrate_zero
|
- service: mhz19_calibrate_zero
|
||||||
then:
|
then:
|
||||||
- mhz19.calibrate_zero: my_mhz19
|
- mhz19.calibrate_zero: my_mhz19
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: WLAN
|
ssid: WLAN
|
||||||
password: !secret wifi_password
|
password: !secret wifi_password
|
||||||
|
@ -39,8 +22,15 @@ ota:
|
||||||
password: !secret ota_password
|
password: !secret ota_password
|
||||||
|
|
||||||
logger:
|
logger:
|
||||||
|
hardware_uart: UART2
|
||||||
|
baud_rate: 0
|
||||||
|
|
||||||
# Power Management
|
# Power Management
|
||||||
|
external_components:
|
||||||
|
- source:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/ssieb/custom_components
|
||||||
|
components: [ip5306]
|
||||||
|
|
||||||
ip5306:
|
ip5306:
|
||||||
battery_level:
|
battery_level:
|
||||||
|
@ -83,7 +73,7 @@ switch:
|
||||||
pin: 32
|
pin: 32
|
||||||
name: "Backlight"
|
name: "Backlight"
|
||||||
id: backlight
|
id: backlight
|
||||||
restore_mode: ALWAYS_OFF
|
restore_mode: ALWAYS_ON
|
||||||
|
|
||||||
light:
|
light:
|
||||||
#- platform: monochromatic # backlight
|
#- platform: monochromatic # backlight
|
||||||
|
@ -114,6 +104,7 @@ light:
|
||||||
from: 5
|
from: 5
|
||||||
to: 9
|
to: 9
|
||||||
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
sda: 21
|
sda: 21
|
||||||
scl: 22
|
scl: 22
|
||||||
|
@ -139,12 +130,9 @@ image:
|
||||||
display:
|
display:
|
||||||
- platform: ili9xxx
|
- platform: ili9xxx
|
||||||
model: M5STACK
|
model: M5STACK
|
||||||
spi_mode: MODE3
|
|
||||||
data_rate: 20MHz
|
|
||||||
cs_pin: 14
|
cs_pin: 14
|
||||||
dc_pin: 27
|
dc_pin: 27
|
||||||
reset_pin: 33
|
reset_pin: 33
|
||||||
update_interval: 20s
|
|
||||||
id: my_display
|
id: my_display
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.image(0, 0, id(img_background));
|
it.image(0, 0, id(img_background));
|
||||||
|
@ -152,7 +140,48 @@ display:
|
||||||
it.printf(240, 125, id(roboto), Color(255, 255, 255), TextAlign::TOP_CENTER, "%.1f °C", id(co2temp).state );
|
it.printf(240, 125, id(roboto), Color(255, 255, 255), TextAlign::TOP_CENTER, "%.1f °C", id(co2temp).state );
|
||||||
it.printf(240, 184, id(roboto), Color(255, 255, 255), TextAlign::TOP_CENTER, "%.1f %%", id(m5stackfire_dht22_humidity).state );
|
it.printf(240, 184, id(roboto), Color(255, 255, 255), TextAlign::TOP_CENTER, "%.1f %%", id(m5stackfire_dht22_humidity).state );
|
||||||
|
|
||||||
|
#display:
|
||||||
|
# - platform: ili9xxx
|
||||||
|
# model: M5STACK
|
||||||
|
# cs_pin: 14
|
||||||
|
# dc_pin: 27
|
||||||
|
# reset_pin: 33
|
||||||
|
# id: my_display
|
||||||
|
# lambda: |-
|
||||||
|
# Color RED(1,0,0);
|
||||||
|
# Color BLUE(0,0,1);
|
||||||
|
# Color WHITE(1,1,1);
|
||||||
|
#
|
||||||
|
# it.rectangle(0, 0, it.get_width(), it.get_height(), BLUE);
|
||||||
|
# it.rectangle(0, 22, it.get_width(), it.get_height(), BLUE); // header bar
|
||||||
|
# it.print(it.get_width() / 2, 11, id(font_roboto_medium22), RED, TextAlign::CENTER, "Particulate matter");
|
||||||
|
#
|
||||||
|
# it.print(11, 33, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "PM1");
|
||||||
|
# it.print(11, 55, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "PM2.5");
|
||||||
|
# it.print(11, 77, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "PM10");
|
||||||
|
#
|
||||||
|
# ////it.printf(it.get_width() - 11, 33, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f µg/m³", 0.0);
|
||||||
|
# ////it.printf(it.get_width() - 11, 55, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f µg/m³", 0.0);
|
||||||
|
# ////it.printf(it.get_width() - 11, 77, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f µg/m³", 0.0);
|
||||||
|
#
|
||||||
|
# //it.rectangle(0, 110, it.get_width(), 22, BLUE); // header bar
|
||||||
|
# //it.print(it.get_width() / 2, 121, id(font_roboto_medium22), RED, TextAlign::CENTER, "Environment");
|
||||||
|
#
|
||||||
|
# //it.print(11, 143, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "T");
|
||||||
|
# //it.print(11, 165, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "H");
|
||||||
|
# //it.print(11, 187, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "VPD");
|
||||||
|
# //it.print(11, 209, id(font_roboto_medium22), WHITE, TextAlign::LEFT, "Tdp");
|
||||||
|
#
|
||||||
|
# ////it.printf(it.get_width() - 77, 143, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f", 0.0);
|
||||||
|
# ////it.printf(it.get_width() - 77, 165, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f", 0.0);
|
||||||
|
# ////it.printf(it.get_width() - 77, 187, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f", 0.0);
|
||||||
|
# ////it.printf(it.get_width() - 77, 209, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%.0f", 0.0);
|
||||||
|
#
|
||||||
|
# //it.printf(it.get_width() - 11, 143, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "°C");
|
||||||
|
# //it.printf(it.get_width() - 11, 165, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "%%");
|
||||||
|
# //it.printf(it.get_width() - 11, 187, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "kPa");
|
||||||
|
# //it.printf(it.get_width() - 11, 209, id(font_roboto_medium22), WHITE, TextAlign::RIGHT, "°C");
|
||||||
|
#
|
||||||
uart:
|
uart:
|
||||||
id: uart_co2
|
id: uart_co2
|
||||||
tx_pin: GPIO17
|
tx_pin: GPIO17
|
||||||
|
@ -180,32 +209,5 @@ sensor:
|
||||||
id: m5stackfire_dht22_humidity
|
id: m5stackfire_dht22_humidity
|
||||||
name: "DHT22 humidity"
|
name: "DHT22 humidity"
|
||||||
|
|
||||||
# BTLE doesn't work - not enough RAM
|
|
||||||
# PSRAM isn't usable because chip is wired to same pins as UART PORT-C :(
|
|
||||||
|
|
||||||
#
|
|
||||||
#mqtt:
|
|
||||||
# broker: homeassistant.fritz.box
|
|
||||||
# username: !secret mqtt_ble_username
|
|
||||||
# password: !secret mqtt_ble_password
|
|
||||||
# discovery: false
|
|
||||||
#
|
|
||||||
#nimble_tracker:
|
|
||||||
|
|
||||||
#esp32_ble_tracker:
|
|
||||||
# scan_parameters:
|
|
||||||
# interval: 1.2s
|
|
||||||
# window: 500ms
|
|
||||||
# active: false
|
|
||||||
# on_ble_advertise:
|
|
||||||
# - then:
|
|
||||||
# - lambda: |-
|
|
||||||
# auto build_json = [&](JsonObject obj) {
|
|
||||||
# obj["rssi"] = x.get_rssi();
|
|
||||||
# obj["address"] = x.address_str();
|
|
||||||
# obj["address_uint64"] = x.address_uint64();
|
|
||||||
# if(x.get_tx_powers().size() > 0)
|
|
||||||
# obj["tx_power"] = x.get_tx_powers()[0];
|
|
||||||
# };
|
|
||||||
# global_mqtt_client->publish_json("my_btmonitor/raw_measurements/az_oben", build_json);
|
|
||||||
#
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
|
||||||
nvs, data, nvs, 0x9000, 0x5000,
|
|
||||||
otadata, data, ota, 0xe000, 0x2000,
|
|
||||||
app0, app, ota_0, 0x10000, 0x640000,
|
|
||||||
app1, app, ota_1, 0x650000,0x640000,
|
|
||||||
spiffs, data, spiffs, 0xc90000,0x360000,
|
|
||||||
coredump, data, coredump,0xFF0000,0x10000,
|
|
|
|
@ -1,31 +0,0 @@
|
||||||
import esphome.config_validation as cv
|
|
||||||
import esphome.codegen as cg
|
|
||||||
|
|
||||||
from esphome.const import (
|
|
||||||
CONF_ACTIVE,
|
|
||||||
CONF_ID,
|
|
||||||
CONF_INTERVAL,
|
|
||||||
CONF_DURATION,
|
|
||||||
)
|
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
|
||||||
|
|
||||||
nimble_tracker_ns = cg.esphome_ns.namespace("my_nimble_tracker")
|
|
||||||
NimbleTracker = nimble_tracker_ns.class_("MyNimbleTracker", cg.Component)
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.Schema({
|
|
||||||
cv.GenerateID(): cv.declare_id(NimbleTracker),
|
|
||||||
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
|
|
||||||
}).extend(cv.COMPONENT_SCHEMA)
|
|
||||||
|
|
||||||
cg.add_library(
|
|
||||||
name="NimBLE",
|
|
||||||
repository="https://github.com/h2zero/NimBLE-Arduino.git",
|
|
||||||
version="release/1.4",
|
|
||||||
)
|
|
||||||
|
|
||||||
def to_code(config):
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
|
||||||
yield cg.register_component(var, config)
|
|
||||||
|
|
||||||
#cg.add(var.set_my_required_key(config[CONF_MY_REQUIRED_KEY]))
|
|
|
@ -1,93 +0,0 @@
|
||||||
#include "my_nimble_tracker.h"
|
|
||||||
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "nvs_flash.h"
|
|
||||||
|
|
||||||
/* BLE */
|
|
||||||
/*
|
|
||||||
#include "nimble/nimble_port.h"
|
|
||||||
#include "nimble/nimble_port_freertos.h"
|
|
||||||
#include "host/ble_hs.h"
|
|
||||||
#include "host/util/util.h"
|
|
||||||
#include "console/console.h"
|
|
||||||
#include "services/gap/ble_svc_gap.h"
|
|
||||||
#include "ble_prox_cent.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace my_nimble_tracker {
|
|
||||||
|
|
||||||
static const char *const TAG = "my_nimble_tracker";
|
|
||||||
|
|
||||||
/*
|
|
||||||
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
|
|
||||||
{
|
|
||||||
void onResult(BLEAdvertisedDevice *advertisedDevice)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Received advertisement for %s", advertisedDevice->getAddress().toString().c_str());
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MyNimbleTracker::setup()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
NimBLEDevice::init("my_nimble_tracker");
|
|
||||||
pBLEScan_ = NimBLEDevice::getScan(); //create new scan
|
|
||||||
pBLEScan_->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
|
|
||||||
pBLEScan_->setActiveScan(false); //active scan uses more power, but get results faster
|
|
||||||
pBLEScan_->setInterval(1200);
|
|
||||||
pBLEScan_->setWindow(500); // less or equal setInterval value
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int rc;
|
|
||||||
/* Initialize NVS — it is used to store PHY calibration data */
|
|
||||||
esp_err_t ret = nvs_flash_init();
|
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
||||||
ret = nvs_flash_init();
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(ret);
|
|
||||||
|
|
||||||
nimble_port_init();
|
|
||||||
/* Configure the host. */
|
|
||||||
ble_hs_cfg.reset_cb = ble_prox_cent_on_reset;
|
|
||||||
ble_hs_cfg.sync_cb = ble_prox_cent_on_sync;
|
|
||||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
|
||||||
|
|
||||||
/* Initialize data structures to track connected peers. */
|
|
||||||
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
|
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
/* Set the default device name. */
|
|
||||||
rc = ble_svc_gap_device_name_set("nimble-prox-cent");
|
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
/* XXX Need to have template for store */
|
|
||||||
ble_store_config_init();
|
|
||||||
|
|
||||||
nimble_port_freertos_init(ble_prox_cent_host_task);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyNimbleTracker::loop()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
auto completion_func = [](NimBLEScanResults) { };
|
|
||||||
//ESP_LOGI(TAG, "Entering loop");
|
|
||||||
if(!pBLEScan_->isScanning()) {
|
|
||||||
ESP_LOGI(TAG, "Starting scan");
|
|
||||||
pBLEScan_->start(4, completion_func, false);
|
|
||||||
}
|
|
||||||
vTaskDelay(1);
|
|
||||||
//ESP_LOGI(TAG, "Exiting loop");
|
|
||||||
delay(1);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace my_nimble_tracker
|
|
||||||
} // namespace esphome
|
|
|
@ -1,20 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
|
|
||||||
class NimBLEScan;
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace my_nimble_tracker {
|
|
||||||
|
|
||||||
class MyNimbleTracker : public Component {
|
|
||||||
public:
|
|
||||||
void setup() override;
|
|
||||||
void loop() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
NimBLEScan *pBLEScan_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
|
||||||
from esphome.const import (
|
|
||||||
CONF_ACTIVE,
|
|
||||||
CONF_ID,
|
|
||||||
CONF_INTERVAL,
|
|
||||||
CONF_DURATION,
|
|
||||||
)
|
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
|
||||||
|
|
||||||
CONF_NIMBLE_ID = "nimble_ble_id"
|
|
||||||
CONF_SCAN_PARAMETERS = "scan_parameters"
|
|
||||||
|
|
||||||
CONF_WINDOW = "window"
|
|
||||||
CONF_CONTINUOUS = "continuous"
|
|
||||||
|
|
||||||
nimble_tracker_ns = cg.esphome_ns.namespace("nimble_tracker")
|
|
||||||
|
|
||||||
NimbleTracker = nimble_tracker_ns.class_("NimbleTracker", cg.Component)
|
|
||||||
NimbleDeviceListener = nimble_tracker_ns.class_("NimbleDeviceListener", cg.Component)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_scan_parameters(config):
|
|
||||||
duration = config[CONF_DURATION]
|
|
||||||
interval = config[CONF_INTERVAL]
|
|
||||||
window = config[CONF_WINDOW]
|
|
||||||
|
|
||||||
if window > interval:
|
|
||||||
raise cv.Invalid(
|
|
||||||
f"Scan window ({window}) needs to be smaller than scan interval ({interval})"
|
|
||||||
)
|
|
||||||
|
|
||||||
if interval.total_milliseconds * 3 > duration.total_milliseconds:
|
|
||||||
raise cv.Invalid(
|
|
||||||
"Scan duration needs to be at least three times the scan interval to"
|
|
||||||
"cover all BLE channels."
|
|
||||||
)
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.Schema(
|
|
||||||
{
|
|
||||||
cv.GenerateID(): cv.declare_id(NimbleTracker),
|
|
||||||
cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All(
|
|
||||||
cv.Schema(
|
|
||||||
{
|
|
||||||
cv.Optional(
|
|
||||||
CONF_DURATION, default="5min"
|
|
||||||
): cv.positive_time_period_seconds,
|
|
||||||
cv.Optional(
|
|
||||||
CONF_INTERVAL, default="320ms"
|
|
||||||
): cv.positive_time_period_milliseconds,
|
|
||||||
cv.Optional(
|
|
||||||
CONF_WINDOW, default="30ms"
|
|
||||||
): cv.positive_time_period_milliseconds,
|
|
||||||
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
|
|
||||||
cv.Optional(CONF_CONTINUOUS, default=True): cv.boolean,
|
|
||||||
cv.Optional(CONF_CONTINUOUS, default=True): cv.boolean,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
validate_scan_parameters,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
|
||||||
|
|
||||||
CONF_IRK = "irk"
|
|
||||||
|
|
||||||
NIMBLE_DEVICE_LISTENER_SCHEMA = cv.Schema(
|
|
||||||
{
|
|
||||||
cv.GenerateID(CONF_NIMBLE_ID): cv.use_id(NimbleTracker),
|
|
||||||
cv.Optional(CONF_IRK): cv.string,
|
|
||||||
},
|
|
||||||
cv.has_exactly_one_key(CONF_IRK),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
|
||||||
# this initializes the component in the generated code
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
|
||||||
await cg.register_component(var, config)
|
|
||||||
|
|
||||||
params = config[CONF_SCAN_PARAMETERS]
|
|
||||||
cg.add(var.set_scan_duration(params[CONF_DURATION]))
|
|
||||||
cg.add(var.set_scan_interval(int(params[CONF_INTERVAL].total_milliseconds / 0.625)))
|
|
||||||
cg.add(var.set_scan_window(int(params[CONF_WINDOW].total_milliseconds / 0.625)))
|
|
||||||
cg.add(var.set_scan_active(params[CONF_ACTIVE]))
|
|
||||||
cg.add(var.set_scan_continuous(params[CONF_CONTINUOUS]))
|
|
||||||
|
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_BLUEDROID_ENABLED", False)
|
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_NIMBLE_ENABLED", True)
|
|
||||||
add_idf_sdkconfig_option("CONFIG_MBEDTLS_HARDWARE_AES", False)
|
|
||||||
add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True)
|
|
||||||
|
|
||||||
cg.add_library(
|
|
||||||
"esp-nimble-cpp=https://github.com/h2zero/esp-nimble-cpp.git#v1.4.1", None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def register_ble_device(var, config):
|
|
||||||
paren = await cg.get_variable(config[CONF_NIMBLE_ID])
|
|
||||||
cg.add(paren.register_listener(var))
|
|
||||||
return var
|
|
||||||
|
|
||||||
|
|
||||||
async def device_listener_to_code(var, config):
|
|
||||||
if CONF_IRK in config:
|
|
||||||
cg.add(var.set_irk(config[CONF_IRK]))
|
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
https://github.com/vgijssel/setup/tree/master
|
|
|
@ -1,61 +0,0 @@
|
||||||
// Copied from https://github.com/ESPresense/ESPresense/blob/master/lib/BleFingerprint/BleFingerprint.cpp
|
|
||||||
#include "irk_utils.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data)
|
|
||||||
{
|
|
||||||
mbedtls_aes_context s = {0};
|
|
||||||
mbedtls_aes_init(&s);
|
|
||||||
|
|
||||||
if (mbedtls_aes_setkey_enc(&s, key, 128) != 0)
|
|
||||||
{
|
|
||||||
mbedtls_aes_free(&s);
|
|
||||||
return BLE_HS_EUNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mbedtls_aes_crypt_ecb(&s, MBEDTLS_AES_ENCRYPT, plaintext, enc_data) != 0)
|
|
||||||
{
|
|
||||||
mbedtls_aes_free(&s);
|
|
||||||
return BLE_HS_EUNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
mbedtls_aes_free(&s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk)
|
|
||||||
{
|
|
||||||
struct encryption_block ecb;
|
|
||||||
|
|
||||||
auto irk32 = (const uint32_t *)irk;
|
|
||||||
auto key32 = (uint32_t *)&ecb.key[0];
|
|
||||||
auto pt32 = (uint32_t *)&ecb.plain_text[0];
|
|
||||||
|
|
||||||
key32[0] = irk32[0];
|
|
||||||
key32[1] = irk32[1];
|
|
||||||
key32[2] = irk32[2];
|
|
||||||
key32[3] = irk32[3];
|
|
||||||
|
|
||||||
pt32[0] = 0;
|
|
||||||
pt32[1] = 0;
|
|
||||||
pt32[2] = 0;
|
|
||||||
pt32[3] = 0;
|
|
||||||
|
|
||||||
ecb.plain_text[15] = rpa[3];
|
|
||||||
ecb.plain_text[14] = rpa[4];
|
|
||||||
ecb.plain_text[13] = rpa[5];
|
|
||||||
|
|
||||||
auto err = bt_encrypt_be(ecb.key, ecb.plain_text, ecb.cipher_text);
|
|
||||||
|
|
||||||
if (ecb.cipher_text[15] != rpa[0] || ecb.cipher_text[14] != rpa[1] || ecb.cipher_text[13] != rpa[2])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copied from https://github.com/ESPresense/ESPresense/blob/master/lib/BleFingerprint/BleFingerprint.cpp
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
#include "NimBLEDevice.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
|
|
||||||
|
|
||||||
struct encryption_block
|
|
||||||
{
|
|
||||||
uint8_t key[16];
|
|
||||||
uint8_t plain_text[16];
|
|
||||||
uint8_t cipher_text[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk);
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,44 +0,0 @@
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "nimble_device_listener.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
static const char *const TAG = "nimble_device_listener";
|
|
||||||
|
|
||||||
void NimbleDeviceListener::set_irk(std::string irk_hex)
|
|
||||||
{
|
|
||||||
this->match_by_ = MATCH_BY_IRK;
|
|
||||||
this->irk_ = new uint8_t[16];
|
|
||||||
|
|
||||||
if (!hextostr(irk_hex.c_str(), this->irk_, 16))
|
|
||||||
{
|
|
||||||
// TODO: this logic should be moved to Python validation
|
|
||||||
ESP_LOGE(TAG, "Something is wrong with the irk!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NimbleDeviceListener::parse_event(NimbleTrackerEvent *tracker_event)
|
|
||||||
{
|
|
||||||
if (tracker_event->getAddressType() != BLE_ADDR_RANDOM)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto address = tracker_event->getAddress();
|
|
||||||
auto naddress = address.getNative();
|
|
||||||
|
|
||||||
if (ble_ll_resolv_rpa(naddress, this->irk_))
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "Found device %s", tracker_event->toString().c_str());
|
|
||||||
return this->update_state(tracker_event);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,32 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "string_utils.h"
|
|
||||||
#include "irk_utils.h"
|
|
||||||
#include "nimble_tracker_event.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
class NimbleDeviceListener
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool parse_event(NimbleTrackerEvent *tracker_event);
|
|
||||||
void set_irk(std::string irk_hex);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool update_state(NimbleTrackerEvent *tracker_event) = 0;
|
|
||||||
|
|
||||||
enum MatchType
|
|
||||||
{
|
|
||||||
MATCH_BY_IRK,
|
|
||||||
};
|
|
||||||
MatchType match_by_;
|
|
||||||
|
|
||||||
uint8_t *irk_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,93 +0,0 @@
|
||||||
#include "nimble_tracker.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/core/hal.h"
|
|
||||||
|
|
||||||
// using namespace esphome;
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
static const char *const TAG = "nimble_tracker";
|
|
||||||
|
|
||||||
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MyAdvertisedDeviceCallbacks(NimbleTracker *nimble_tracker)
|
|
||||||
{
|
|
||||||
nimble_tracker_ = nimble_tracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onResult(BLEAdvertisedDevice *advertised_device)
|
|
||||||
{
|
|
||||||
// Because setMaxResults is set to 0 for the NimBLEScan, we need to make a copy
|
|
||||||
// of the data of the advertised device, because this is deleted immediately by NimBLESCan
|
|
||||||
// after this callback is called.
|
|
||||||
auto *tracker_event = new NimbleTrackerEvent(
|
|
||||||
advertised_device->getAddress(),
|
|
||||||
advertised_device->getAddressType(),
|
|
||||||
advertised_device->getRSSI(),
|
|
||||||
advertised_device->getTXPower());
|
|
||||||
|
|
||||||
nimble_tracker_->tracker_events_.push(tracker_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
NimbleTracker *nimble_tracker_;
|
|
||||||
};
|
|
||||||
|
|
||||||
void NimbleTracker::setup()
|
|
||||||
{
|
|
||||||
// Set the name to empty string to not broadcast the name
|
|
||||||
NimBLEDevice::init("");
|
|
||||||
this->pBLEScan_ = NimBLEDevice::getScan();
|
|
||||||
this->pBLEScan_->setInterval(this->scan_interval_);
|
|
||||||
this->pBLEScan_->setWindow(this->scan_window_);
|
|
||||||
this->pBLEScan_->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(this), true);
|
|
||||||
this->pBLEScan_->setActiveScan(this->scan_active_);
|
|
||||||
this->pBLEScan_->setDuplicateFilter(false);
|
|
||||||
this->pBLEScan_->setMaxResults(0);
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Trying to start the scan");
|
|
||||||
|
|
||||||
if (!pBLEScan_->start(0, nullptr, false))
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Error starting continuous ble scan");
|
|
||||||
// this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: It takes some time to setup bluetooth? Why not just move this to loop?
|
|
||||||
delay(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NimbleTracker::loop()
|
|
||||||
{
|
|
||||||
if (!this->pBLEScan_->isScanning())
|
|
||||||
{
|
|
||||||
if (!this->pBLEScan_->start(0, nullptr, false))
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Error starting continuous ble scan");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: we shouldn't block the main thread here, instead work with a setTimeout callback?
|
|
||||||
delay(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
NimbleTrackerEvent *tracker_event = this->tracker_events_.pop();
|
|
||||||
|
|
||||||
while (tracker_event != nullptr)
|
|
||||||
{
|
|
||||||
for (NimbleDeviceListener *listener : this->listeners_)
|
|
||||||
{
|
|
||||||
listener->parse_event(tracker_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete tracker_event;
|
|
||||||
tracker_event = this->tracker_events_.pop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace esp32_ble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,41 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include "queue.h"
|
|
||||||
#include "NimBLEDevice.h"
|
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
|
||||||
#include "nimble_device_listener.h"
|
|
||||||
#include "nimble_tracker_event.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
class NimbleTracker : public Component
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
void set_scan_duration(uint32_t scan_duration) { scan_duration_ = scan_duration; }
|
|
||||||
void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
|
|
||||||
void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
|
|
||||||
void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
|
|
||||||
void set_scan_continuous(bool scan_continuous) { scan_continuous_ = scan_continuous; }
|
|
||||||
Queue<NimbleTrackerEvent> tracker_events_;
|
|
||||||
|
|
||||||
void setup() override;
|
|
||||||
void loop() override;
|
|
||||||
|
|
||||||
void register_listener(NimbleDeviceListener *listener) { listeners_.push_back(listener); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
uint32_t scan_duration_;
|
|
||||||
uint32_t scan_interval_;
|
|
||||||
uint32_t scan_window_;
|
|
||||||
bool scan_active_;
|
|
||||||
bool scan_continuous_;
|
|
||||||
NimBLEScan *pBLEScan_;
|
|
||||||
std::vector<NimbleDeviceListener *> listeners_;
|
|
||||||
};
|
|
||||||
} // namespace esp32_ble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,45 +0,0 @@
|
||||||
#include "nimble_tracker_event.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
NimbleTrackerEvent::NimbleTrackerEvent(NimBLEAddress address, uint8_t address_type, int rssi, int8_t tx_power)
|
|
||||||
{
|
|
||||||
this->address_ = address;
|
|
||||||
this->address_type_ = address_type;
|
|
||||||
this->rssi_ = rssi;
|
|
||||||
this->tx_power_ = tx_power;
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t NimbleTrackerEvent::getTXPower()
|
|
||||||
{
|
|
||||||
return this->tx_power_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NimbleTrackerEvent::getRSSI()
|
|
||||||
{
|
|
||||||
return this->rssi_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t NimbleTrackerEvent::getAddressType()
|
|
||||||
{
|
|
||||||
return this->address_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
NimBLEAddress NimbleTrackerEvent::getAddress()
|
|
||||||
{
|
|
||||||
return this->address_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NimbleTrackerEvent::toString()
|
|
||||||
{
|
|
||||||
std::string result = "Address: " + this->address_.toString();
|
|
||||||
result += " Address type: " + std::to_string(this->address_type_);
|
|
||||||
result += " RSSI: " + std::to_string(this->rssi_);
|
|
||||||
result += " TX Power: " + std::to_string(this->tx_power_);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "NimBLEDevice.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
class NimbleTrackerEvent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NimbleTrackerEvent(NimBLEAddress address, uint8_t address_type, int rssi, int8_t tx_power);
|
|
||||||
int8_t getTXPower();
|
|
||||||
int getRSSI();
|
|
||||||
uint8_t getAddressType();
|
|
||||||
NimBLEAddress getAddress();
|
|
||||||
std::string toString();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int8_t tx_power_;
|
|
||||||
int rssi_;
|
|
||||||
uint8_t address_type_;
|
|
||||||
NimBLEAddress address_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,65 +0,0 @@
|
||||||
// Copied from https://github.com/esphome/esphome/blob/dev/esphome/components/esp32_ble_tracker/queue.h
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include "esphome/core/helpers.h"
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <mutex>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
#include <freertos/semphr.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BLE events come in from a separate Task (thread) in the ESP32 stack. Rather
|
|
||||||
* than trying to deal with various locking strategies, all incoming GAP and GATT
|
|
||||||
* events will simply be placed on a semaphore guarded queue. The next time the
|
|
||||||
* component runs loop(), these events are popped off the queue and handed at
|
|
||||||
* this safer time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class Queue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Queue() { m_ = xSemaphoreCreateMutex(); }
|
|
||||||
|
|
||||||
void push(T *element)
|
|
||||||
{
|
|
||||||
if (element == nullptr)
|
|
||||||
return;
|
|
||||||
if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS))
|
|
||||||
{
|
|
||||||
q_.push(element);
|
|
||||||
xSemaphoreGive(m_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T *pop()
|
|
||||||
{
|
|
||||||
T *element = nullptr;
|
|
||||||
|
|
||||||
if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS))
|
|
||||||
{
|
|
||||||
if (!q_.empty())
|
|
||||||
{
|
|
||||||
element = q_.front();
|
|
||||||
q_.pop();
|
|
||||||
}
|
|
||||||
xSemaphoreGive(m_);
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::queue<T *> q_;
|
|
||||||
SemaphoreHandle_t m_;
|
|
||||||
};
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
} // namespace esphome
|
|
|
@ -1,47 +0,0 @@
|
||||||
// Copied from https://github.com/ESPresense/ESPresense/blob/master/lib/BleFingerprint/string_utils.cpp
|
|
||||||
#include "string_utils.h"
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
|
|
||||||
static constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
|
||||||
|
|
||||||
std::string hexStr(const uint8_t *data, int len)
|
|
||||||
{
|
|
||||||
std::string s(len * 2, ' ');
|
|
||||||
for (int i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
|
|
||||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t hextob(char ch)
|
|
||||||
{
|
|
||||||
if (ch >= '0' && ch <= '9')
|
|
||||||
return ch - '0';
|
|
||||||
if (ch >= 'A' && ch <= 'F')
|
|
||||||
return ch - 'A' + 10;
|
|
||||||
if (ch >= 'a' && ch <= 'f')
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hextostr(const std::string &hexStr, uint8_t *output, size_t len)
|
|
||||||
{
|
|
||||||
if (len & 1)
|
|
||||||
return false;
|
|
||||||
if (hexStr.length() < len * 2)
|
|
||||||
return false;
|
|
||||||
int k = 0;
|
|
||||||
for (size_t i = 0; i < len * 2; i += 2)
|
|
||||||
output[k++] = (hextob(hexStr[i]) << 4) | hextob(hexStr[i + 1]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespece esphome
|
|
|
@ -1,18 +0,0 @@
|
||||||
// Copied from https://github.com/ESPresense/ESPresense/blob/master/lib/BleFingerprint/string_utils.h
|
|
||||||
#pragma once
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define Sprintf(f, ...) ({ char* s; asprintf(&s, f, __VA_ARGS__); std::string r = s; free(s); r; })
|
|
||||||
|
|
||||||
namespace esphome
|
|
||||||
{
|
|
||||||
namespace nimble_tracker
|
|
||||||
{
|
|
||||||
|
|
||||||
std::string hexStr(const uint8_t *data, int len);
|
|
||||||
uint8_t hextob(char ch);
|
|
||||||
bool hextostr(const std::string &hexStr, uint8_t *output, size_t len);
|
|
||||||
|
|
||||||
} // namespace nimble_tracker
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
|
@ -1,42 +0,0 @@
|
||||||
|
|
||||||
esphome:
|
|
||||||
name: wohnzimmer-ble-tracker
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
board: m5stack-atom
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
ota:
|
|
||||||
password: !secret ota_password
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: WLAN
|
|
||||||
password: !secret wifi_password
|
|
||||||
|
|
||||||
mqtt:
|
|
||||||
broker: homeassistant.fritz.box
|
|
||||||
username: !secret mqtt_ble_username
|
|
||||||
password: !secret mqtt_ble_password
|
|
||||||
discovery: false
|
|
||||||
|
|
||||||
|
|
||||||
esp32_ble_tracker:
|
|
||||||
scan_parameters:
|
|
||||||
interval: 1.2s
|
|
||||||
window: 500ms
|
|
||||||
active: false
|
|
||||||
on_ble_advertise:
|
|
||||||
- then:
|
|
||||||
- lambda: |-
|
|
||||||
auto build_json = [&](JsonObject obj) {
|
|
||||||
obj["rssi"] = x.get_rssi();
|
|
||||||
obj["address"] = x.address_str();
|
|
||||||
obj["address_uint64"] = x.address_uint64();
|
|
||||||
if(x.get_tx_powers().size() > 0)
|
|
||||||
obj["tx_power"] = x.get_tx_powers()[0];
|
|
||||||
};
|
|
||||||
global_mqtt_client->publish_json("my_btmonitor/raw_measurements/wohnzimmer", build_json);
|
|
||||||
|
|
Loading…
Reference in New Issue