mirror of
https://github.com/esphome/esphome.git
synced 2025-04-11 21:30:29 +01:00
beacon demo
This commit is contained in:
parent
469aaecec9
commit
ecfbca8522
22
esphome/components/beacon/__init__.py
Normal file
22
esphome/components/beacon/__init__.py
Normal file
@ -0,0 +1,22 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
)
|
||||
|
||||
dfu_ns = cg.esphome_ns.namespace("ble")
|
||||
Beacon = dfu_ns.class_("Beacon", cg.Component)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(Beacon),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
cv.only_on_nrf52,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
76
esphome/components/beacon/beacon.cpp
Normal file
76
esphome/components/beacon/beacon.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "beacon.h"
|
||||
#include <bluefruit.h>
|
||||
|
||||
// Beacon uses the Manufacturer Specific Data field in the advertising packet,
|
||||
// which means you must provide a valid Manufacturer ID. Update
|
||||
// the field below to an appropriate value. For a list of valid IDs see:
|
||||
// https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
|
||||
// - 0x004C is Apple
|
||||
// - 0x0822 is Adafruit
|
||||
// - 0x0059 is Nordic
|
||||
// For testing with this sketch, you can use nRF Beacon app
|
||||
// - on Android you may need change the MANUFACTURER_ID to Nordic
|
||||
// - on iOS you may need to change the MANUFACTURER_ID to Apple.
|
||||
// You will also need to "Add Other Beacon, then enter Major, Minor that you set in the sketch
|
||||
#define MANUFACTURER_ID 0x0059
|
||||
|
||||
// "nRF Connect" app can be used to detect beacon
|
||||
uint8_t beaconUuid[16] = {
|
||||
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
|
||||
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
|
||||
};
|
||||
|
||||
// A valid Beacon packet consists of the following information:
|
||||
// UUID, Major, Minor, RSSI @ 1M
|
||||
BLEBeacon beacon(beaconUuid, 1, 2, -54);
|
||||
|
||||
void startAdv(void)
|
||||
{
|
||||
// Advertising packet
|
||||
// Set the beacon payload using the BLEBeacon class populated
|
||||
// earlier in this example
|
||||
Bluefruit.Advertising.setBeacon(beacon);
|
||||
|
||||
// Secondary Scan Response packet (optional)
|
||||
// Since there is no room for 'Name' in Advertising packet
|
||||
Bluefruit.ScanResponse.addName();
|
||||
|
||||
/* Start Advertising
|
||||
* - Enable auto advertising if disconnected
|
||||
* - Timeout for fast mode is 30 seconds
|
||||
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
|
||||
*
|
||||
* Apple Beacon specs
|
||||
* - Type: Non-connectable, scannable, undirected
|
||||
* - Fixed interval: 100 ms -> fast = slow = 100 ms
|
||||
*/
|
||||
Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED);
|
||||
Bluefruit.Advertising.restartOnDisconnect(true);
|
||||
Bluefruit.Advertising.setInterval(160, 160); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
||||
}
|
||||
|
||||
namespace esphome {
|
||||
namespace ble {
|
||||
|
||||
void Beacon::loop() {
|
||||
}
|
||||
|
||||
void Beacon::setup(){
|
||||
Bluefruit.begin();
|
||||
|
||||
// off Blue LED for lowest power consumption
|
||||
Bluefruit.autoConnLed(false);
|
||||
Bluefruit.setTxPower(0); // Check bluefruit.h for supported values
|
||||
Bluefruit.setName("ESPHome");
|
||||
|
||||
// Manufacturer ID is required for Manufacturer Specific Data
|
||||
beacon.setManufacturer(MANUFACTURER_ID);
|
||||
|
||||
// Setup the advertising packet
|
||||
startAdv();
|
||||
}
|
||||
|
||||
} // namespace dfu
|
||||
} // namespace esphome
|
11
esphome/components/beacon/beacon.h
Normal file
11
esphome/components/beacon/beacon.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ble {
|
||||
class Beacon : public Component {
|
||||
void loop() override;
|
||||
void setup() override;
|
||||
};
|
||||
}
|
||||
}
|
83
esphome/components/nrf52/__init__.py
Normal file
83
esphome/components/nrf52/__init__.py
Normal file
@ -0,0 +1,83 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_BOARD,
|
||||
CONF_FRAMEWORK,
|
||||
KEY_CORE,
|
||||
KEY_TARGET_FRAMEWORK,
|
||||
KEY_TARGET_PLATFORM,
|
||||
PLATFORM_NRF52,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
|
||||
# force import gpio to register pin schema
|
||||
from .gpio import nrf52_pin_to_code # noqa
|
||||
|
||||
|
||||
def set_core_data(config):
|
||||
CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_NRF52
|
||||
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino"
|
||||
return config
|
||||
|
||||
|
||||
# https://github.com/platformio/platform-nordicnrf52/releases
|
||||
ARDUINO_PLATFORM_VERSION = cv.Version(10, 3, 0)
|
||||
|
||||
|
||||
def _arduino_check_versions(value):
|
||||
value = value.copy()
|
||||
value[CONF_PLATFORM_VERSION] = value.get(
|
||||
CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
def _parse_platform_version(value):
|
||||
try:
|
||||
# if platform version is a valid version constraint, prefix the default package
|
||||
cv.platformio_version_constraint(value)
|
||||
return f"platformio/nordicnrf52@{value}"
|
||||
except cv.Invalid:
|
||||
return value
|
||||
|
||||
|
||||
CONF_PLATFORM_VERSION = "platform_version"
|
||||
|
||||
ARDUINO_FRAMEWORK_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version,
|
||||
}
|
||||
),
|
||||
_arduino_check_versions,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_BOARD): cv.string_strict,
|
||||
cv.Optional(CONF_FRAMEWORK, default={}): ARDUINO_FRAMEWORK_SCHEMA,
|
||||
}
|
||||
),
|
||||
set_core_data,
|
||||
)
|
||||
|
||||
nrf52_ns = cg.esphome_ns.namespace("nrf52")
|
||||
|
||||
|
||||
@coroutine_with_priority(1000)
|
||||
async def to_code(config):
|
||||
cg.add(nrf52_ns.setup_preferences())
|
||||
if config[CONF_BOARD] == "nrf52840":
|
||||
# it has most generic GPIO mapping
|
||||
config[CONF_BOARD] = "nrf52840_dk_adafruit"
|
||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||
cg.add_build_flag("-DUSE_NRF52")
|
||||
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
||||
cg.add_define("ESPHOME_VARIANT", "nrf52840")
|
||||
conf = config[CONF_FRAMEWORK]
|
||||
cg.add_platformio_option("framework", "arduino")
|
||||
cg.add_build_flag("-DUSE_ARDUINO")
|
||||
cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION])
|
||||
# make sure that firmware.zip is created
|
||||
cg.add_platformio_option("board_upload.protocol", "nrfutil")
|
39
esphome/components/nrf52/core.cpp
Normal file
39
esphome/components/nrf52/core.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifdef USE_NRF52
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Adafruit_nRFCrypto.h"
|
||||
|
||||
namespace esphome {
|
||||
|
||||
void yield() { ::yield(); }
|
||||
uint32_t millis() { return ::millis(); }
|
||||
void delay(uint32_t ms) { ::delay(ms); }
|
||||
uint32_t micros() { return ::micros(); }
|
||||
|
||||
void arch_init() {
|
||||
nRFCrypto.begin();
|
||||
// Init random seed
|
||||
union seedParts {
|
||||
uint32_t seed32;
|
||||
uint8_t seed8[4];
|
||||
} seed;
|
||||
nRFCrypto.Random.generate(seed.seed8, sizeof(seed.seed8));
|
||||
randomSeed(seed.seed32);
|
||||
|
||||
}
|
||||
void arch_feed_wdt() { /* TODO */ }
|
||||
|
||||
void nrf52GetMacAddr(uint8_t *mac)
|
||||
{
|
||||
const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR;
|
||||
mac[5] = src[0];
|
||||
mac[4] = src[1];
|
||||
mac[3] = src[2];
|
||||
mac[2] = src[3];
|
||||
mac[1] = src[4];
|
||||
mac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack
|
||||
}
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_RP2040
|
3
esphome/components/nrf52/core.h
Normal file
3
esphome/components/nrf52/core.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void nrf52GetMacAddr(uint8_t *mac);
|
46
esphome/components/nrf52/preferences.cpp
Normal file
46
esphome/components/nrf52/preferences.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#ifdef USE_NRF52
|
||||
|
||||
#include "esphome/core/preferences.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace nrf52 {
|
||||
|
||||
class NRF52Preferences : public ESPPreferences {
|
||||
public:
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override {
|
||||
return make_preference(length, type);
|
||||
}
|
||||
|
||||
ESPPreferenceObject make_preference(size_t length, uint32_t type) override {
|
||||
//TODO
|
||||
return {};
|
||||
}
|
||||
|
||||
bool sync() override {
|
||||
//TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reset() override {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
// protected:
|
||||
// uint8_t *eeprom_sector_;
|
||||
};
|
||||
|
||||
void setup_preferences() {
|
||||
auto *prefs = new NRF52Preferences(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
global_preferences = prefs;
|
||||
}
|
||||
//TODO
|
||||
// void preferences_prevent_write(bool prevent) { s_prevent_write = prevent; }
|
||||
|
||||
} // namespace nrf52
|
||||
|
||||
ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_RP2040
|
15
esphome/components/nrf52/preferences.h
Normal file
15
esphome/components/nrf52/preferences.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_NRF52
|
||||
|
||||
namespace esphome {
|
||||
namespace nrf52 {
|
||||
|
||||
void setup_preferences();
|
||||
//TODO
|
||||
// void preferences_prevent_write(bool prevent);
|
||||
|
||||
} // namespace nrf52
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_RP2040
|
@ -47,6 +47,11 @@
|
||||
#include <WiFi.h> // for macAddress()
|
||||
#endif
|
||||
|
||||
#ifdef USE_NRF52
|
||||
#include "Adafruit_nRFCrypto.h"
|
||||
#include "esphome/components/nrf52/core.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
|
||||
static const char *const TAG = "helpers";
|
||||
@ -201,6 +206,8 @@ uint32_t random_uint32() {
|
||||
std::mt19937 rng(dev());
|
||||
std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint32_t>::max());
|
||||
return dist(rng);
|
||||
#elif defined(USE_NRF52)
|
||||
return rand();
|
||||
#else
|
||||
#error "No random source available for this configuration."
|
||||
#endif
|
||||
@ -238,6 +245,8 @@ bool random_bytes(uint8_t *data, size_t len) {
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
#elif defined(USE_NRF52)
|
||||
return nRFCrypto.Random.generate(data, len);
|
||||
#else
|
||||
#error "No random source available for this configuration."
|
||||
#endif
|
||||
@ -515,7 +524,7 @@ Mutex::Mutex() {}
|
||||
void Mutex::lock() {}
|
||||
bool Mutex::try_lock() { return true; }
|
||||
void Mutex::unlock() {}
|
||||
#elif defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
#elif defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_NRF52)
|
||||
Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); }
|
||||
void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); }
|
||||
bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; }
|
||||
@ -569,6 +578,8 @@ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parame
|
||||
WiFi.macAddress(mac);
|
||||
#elif defined(USE_LIBRETINY)
|
||||
WiFi.macAddress(mac);
|
||||
#elif defined(USE_NRF52)
|
||||
nrf52GetMacAddr(mac);
|
||||
#endif
|
||||
}
|
||||
std::string get_mac_address() {
|
||||
|
@ -36,3 +36,5 @@ sensor:
|
||||
update_interval: 3s
|
||||
|
||||
dfu:
|
||||
|
||||
beacon:
|
||||
|
Loading…
x
Reference in New Issue
Block a user