mirror of
https://github.com/esphome/esphome.git
synced 2024-12-01 13:13:54 +01:00
Add friendly_name to device (#4296)
This commit is contained in:
parent
3d2d681a7b
commit
c301ae3645
@ -206,6 +206,8 @@ message DeviceInfoResponse {
|
|||||||
uint32 bluetooth_proxy_version = 11;
|
uint32 bluetooth_proxy_version = 11;
|
||||||
|
|
||||||
string manufacturer = 12;
|
string manufacturer = 12;
|
||||||
|
|
||||||
|
string friendly_name = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListEntitiesRequest {
|
message ListEntitiesRequest {
|
||||||
|
@ -930,6 +930,7 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|||||||
DeviceInfoResponse resp{};
|
DeviceInfoResponse resp{};
|
||||||
resp.uses_password = this->parent_->uses_password();
|
resp.uses_password = this->parent_->uses_password();
|
||||||
resp.name = App.get_name();
|
resp.name = App.get_name();
|
||||||
|
resp.friendly_name = App.get_friendly_name();
|
||||||
resp.mac_address = get_mac_address_pretty();
|
resp.mac_address = get_mac_address_pretty();
|
||||||
resp.esphome_version = ESPHOME_VERSION;
|
resp.esphome_version = ESPHOME_VERSION;
|
||||||
resp.compilation_time = App.get_compilation_time();
|
resp.compilation_time = App.get_compilation_time();
|
||||||
|
@ -628,6 +628,10 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
|
|||||||
this->manufacturer = value.as_string();
|
this->manufacturer = value.as_string();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 13: {
|
||||||
|
this->friendly_name = value.as_string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -645,6 +649,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_uint32(10, this->webserver_port);
|
buffer.encode_uint32(10, this->webserver_port);
|
||||||
buffer.encode_uint32(11, this->bluetooth_proxy_version);
|
buffer.encode_uint32(11, this->bluetooth_proxy_version);
|
||||||
buffer.encode_string(12, this->manufacturer);
|
buffer.encode_string(12, this->manufacturer);
|
||||||
|
buffer.encode_string(13, this->friendly_name);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DeviceInfoResponse::dump_to(std::string &out) const {
|
void DeviceInfoResponse::dump_to(std::string &out) const {
|
||||||
@ -699,6 +704,10 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
|
|||||||
out.append(" manufacturer: ");
|
out.append(" manufacturer: ");
|
||||||
out.append("'").append(this->manufacturer).append("'");
|
out.append("'").append(this->manufacturer).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" friendly_name: ");
|
||||||
|
out.append("'").append(this->friendly_name).append("'");
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -276,6 +276,7 @@ class DeviceInfoResponse : public ProtoMessage {
|
|||||||
uint32_t webserver_port{0};
|
uint32_t webserver_port{0};
|
||||||
uint32_t bluetooth_proxy_version{0};
|
uint32_t bluetooth_proxy_version{0};
|
||||||
std::string manufacturer{};
|
std::string manufacturer{};
|
||||||
|
std::string friendly_name{};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
|
from esphome import git
|
||||||
from esphome.components.packages import validate_source_shorthand
|
from esphome.components.packages import validate_source_shorthand
|
||||||
from esphome.const import CONF_WIFI, CONF_REF
|
from esphome.const import CONF_REF, CONF_WIFI
|
||||||
from esphome.wizard import wizard_file
|
from esphome.wizard import wizard_file
|
||||||
from esphome.yaml_util import dump
|
from esphome.yaml_util import dump
|
||||||
from esphome import git
|
|
||||||
|
|
||||||
|
|
||||||
dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import")
|
dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import")
|
||||||
|
|
||||||
@ -66,7 +67,12 @@ async def to_code(config):
|
|||||||
|
|
||||||
|
|
||||||
def import_config(
|
def import_config(
|
||||||
path: str, name: str, project_name: str, import_url: str, network: str = CONF_WIFI
|
path: str,
|
||||||
|
name: str,
|
||||||
|
friendly_name: Optional[str],
|
||||||
|
project_name: str,
|
||||||
|
import_url: str,
|
||||||
|
network: str = CONF_WIFI,
|
||||||
) -> None:
|
) -> None:
|
||||||
p = Path(path)
|
p = Path(path)
|
||||||
|
|
||||||
@ -77,6 +83,7 @@ def import_config(
|
|||||||
p.write_text(
|
p.write_text(
|
||||||
wizard_file(
|
wizard_file(
|
||||||
name=name,
|
name=name,
|
||||||
|
friendly_name=friendly_name,
|
||||||
platform="ESP32" if "esp32" in import_url else "ESP8266",
|
platform="ESP32" if "esp32" in import_url else "ESP8266",
|
||||||
board="esp32dev" if "esp32" in import_url else "esp01_1m",
|
board="esp32dev" if "esp32" in import_url else "esp01_1m",
|
||||||
ssid="!secret wifi_ssid",
|
ssid="!secret wifi_ssid",
|
||||||
@ -98,13 +105,15 @@ def import_config(
|
|||||||
p.write_text(req.text, encoding="utf8")
|
p.write_text(req.text, encoding="utf8")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
substitutions = {"name": name}
|
||||||
|
esphome_core = {"name": "${name}", "name_add_mac_suffix": False}
|
||||||
|
if friendly_name:
|
||||||
|
substitutions["friendly_name"] = friendly_name
|
||||||
|
esphome_core["friendly_name"] = "${friendly_name}"
|
||||||
config = {
|
config = {
|
||||||
"substitutions": {"name": name},
|
"substitutions": substitutions,
|
||||||
"packages": {project_name: import_url},
|
"packages": {project_name: import_url},
|
||||||
"esphome": {
|
"esphome": esphome_core,
|
||||||
"name": "${name}",
|
|
||||||
"name_add_mac_suffix": False,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
output = dump(config)
|
output = dump(config)
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ void MDNSComponent::compile_records_() {
|
|||||||
service.service_type = "_esphomelib";
|
service.service_type = "_esphomelib";
|
||||||
service.proto = "_tcp";
|
service.proto = "_tcp";
|
||||||
service.port = api::global_api_server->get_port();
|
service.port = api::global_api_server->get_port();
|
||||||
|
if (App.get_friendly_name().empty()) {
|
||||||
|
service.txt_records.push_back({"friendly_name", App.get_friendly_name()});
|
||||||
|
}
|
||||||
service.txt_records.push_back({"version", ESPHOME_VERSION});
|
service.txt_records.push_back({"version", ESPHOME_VERSION});
|
||||||
service.txt_records.push_back({"mac", get_mac_address()});
|
service.txt_records.push_back({"mac", get_mac_address()});
|
||||||
const char *platform = nullptr;
|
const char *platform = nullptr;
|
||||||
|
@ -104,7 +104,7 @@ void WebServer::setup() {
|
|||||||
// Configure reconnect timeout and send config
|
// Configure reconnect timeout and send config
|
||||||
|
|
||||||
client->send(json::build_json([this](JsonObject root) {
|
client->send(json::build_json([this](JsonObject root) {
|
||||||
root["title"] = App.get_name();
|
root["title"] = App.get_friendly_name().empty() ? App.get_name() : App.get_friendly_name();
|
||||||
root["ota"] = this->allow_ota_;
|
root["ota"] = this->allow_ota_;
|
||||||
root["lang"] = "en";
|
root["lang"] = "en";
|
||||||
}).c_str(),
|
}).c_str(),
|
||||||
|
@ -260,6 +260,7 @@ CONF_FRAGMENTATION = "fragmentation"
|
|||||||
CONF_FRAMEWORK = "framework"
|
CONF_FRAMEWORK = "framework"
|
||||||
CONF_FREE = "free"
|
CONF_FREE = "free"
|
||||||
CONF_FREQUENCY = "frequency"
|
CONF_FREQUENCY = "frequency"
|
||||||
|
CONF_FRIENDLY_NAME = "friendly_name"
|
||||||
CONF_FROM = "from"
|
CONF_FROM = "from"
|
||||||
CONF_FULL_SPECTRUM = "full_spectrum"
|
CONF_FULL_SPECTRUM = "full_spectrum"
|
||||||
CONF_FULL_UPDATE_EVERY = "full_update_every"
|
CONF_FULL_UPDATE_EVERY = "full_update_every"
|
||||||
|
@ -453,6 +453,8 @@ class EsphomeCore:
|
|||||||
self.ace = False
|
self.ace = False
|
||||||
# The name of the node
|
# The name of the node
|
||||||
self.name: Optional[str] = None
|
self.name: Optional[str] = None
|
||||||
|
# The friendly name of the node
|
||||||
|
self.friendly_name: Optional[str] = None
|
||||||
# Additional data components can store temporary data in
|
# Additional data components can store temporary data in
|
||||||
# The first key to this dict should always be the integration name
|
# The first key to this dict should always be the integration name
|
||||||
self.data = {}
|
self.data = {}
|
||||||
@ -492,6 +494,7 @@ class EsphomeCore:
|
|||||||
def reset(self):
|
def reset(self):
|
||||||
self.dashboard = False
|
self.dashboard = False
|
||||||
self.name = None
|
self.name = None
|
||||||
|
self.friendly_name = None
|
||||||
self.data = {}
|
self.data = {}
|
||||||
self.config_path = None
|
self.config_path = None
|
||||||
self.build_path = None
|
self.build_path = None
|
||||||
|
@ -53,13 +53,20 @@ namespace esphome {
|
|||||||
|
|
||||||
class Application {
|
class Application {
|
||||||
public:
|
public:
|
||||||
void pre_setup(const std::string &name, const char *compilation_time, bool name_add_mac_suffix) {
|
void pre_setup(const std::string &name, const std::string &friendly_name, const char *compilation_time,
|
||||||
|
bool name_add_mac_suffix) {
|
||||||
arch_init();
|
arch_init();
|
||||||
this->name_add_mac_suffix_ = name_add_mac_suffix;
|
this->name_add_mac_suffix_ = name_add_mac_suffix;
|
||||||
if (name_add_mac_suffix) {
|
if (name_add_mac_suffix) {
|
||||||
this->name_ = name + "-" + get_mac_address().substr(6);
|
this->name_ = name + "-" + get_mac_address().substr(6);
|
||||||
|
if (friendly_name.empty()) {
|
||||||
|
this->friendly_name_ = "";
|
||||||
|
} else {
|
||||||
|
this->friendly_name_ = friendly_name + " " + get_mac_address().substr(6);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this->name_ = name;
|
this->name_ = name;
|
||||||
|
this->friendly_name_ = friendly_name;
|
||||||
}
|
}
|
||||||
this->compilation_time_ = compilation_time;
|
this->compilation_time_ = compilation_time;
|
||||||
}
|
}
|
||||||
@ -134,6 +141,9 @@ class Application {
|
|||||||
/// Get the name of this Application set by set_name().
|
/// Get the name of this Application set by set_name().
|
||||||
const std::string &get_name() const { return this->name_; }
|
const std::string &get_name() const { return this->name_; }
|
||||||
|
|
||||||
|
/// Get the friendly name of this Application set by set_friendly_name().
|
||||||
|
const std::string &get_friendly_name() const { return this->friendly_name_; }
|
||||||
|
|
||||||
bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; }
|
bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; }
|
||||||
|
|
||||||
const std::string &get_compilation_time() const { return this->compilation_time_; }
|
const std::string &get_compilation_time() const { return this->compilation_time_; }
|
||||||
@ -338,6 +348,7 @@ class Application {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
std::string friendly_name_;
|
||||||
std::string compilation_time_;
|
std::string compilation_time_;
|
||||||
bool name_add_mac_suffix_;
|
bool name_add_mac_suffix_;
|
||||||
uint32_t last_loop_{0};
|
uint32_t last_loop_{0};
|
||||||
|
@ -19,6 +19,7 @@ from esphome.const import (
|
|||||||
CONF_LIBRARIES,
|
CONF_LIBRARIES,
|
||||||
CONF_MIN_VERSION,
|
CONF_MIN_VERSION,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
|
CONF_FRIENDLY_NAME,
|
||||||
CONF_ON_BOOT,
|
CONF_ON_BOOT,
|
||||||
CONF_ON_LOOP,
|
CONF_ON_LOOP,
|
||||||
CONF_ON_SHUTDOWN,
|
CONF_ON_SHUTDOWN,
|
||||||
@ -124,6 +125,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_NAME): cv.valid_name,
|
cv.Required(CONF_NAME): cv.valid_name,
|
||||||
|
cv.Optional(CONF_FRIENDLY_NAME, ""): cv.string,
|
||||||
cv.Optional(CONF_COMMENT): cv.string,
|
cv.Optional(CONF_COMMENT): cv.string,
|
||||||
cv.Required(CONF_BUILD_PATH): cv.string,
|
cv.Required(CONF_BUILD_PATH): cv.string,
|
||||||
cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema(
|
cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema(
|
||||||
@ -192,6 +194,7 @@ def preload_core_config(config, result):
|
|||||||
conf = PRELOAD_CONFIG_SCHEMA(config[CONF_ESPHOME])
|
conf = PRELOAD_CONFIG_SCHEMA(config[CONF_ESPHOME])
|
||||||
|
|
||||||
CORE.name = conf[CONF_NAME]
|
CORE.name = conf[CONF_NAME]
|
||||||
|
CORE.friendly_name = conf.get(CONF_FRIENDLY_NAME, CORE.name)
|
||||||
CORE.data[KEY_CORE] = {}
|
CORE.data[KEY_CORE] = {}
|
||||||
|
|
||||||
if CONF_BUILD_PATH not in conf:
|
if CONF_BUILD_PATH not in conf:
|
||||||
@ -346,6 +349,7 @@ async def to_code(config):
|
|||||||
cg.add(
|
cg.add(
|
||||||
cg.App.pre_setup(
|
cg.App.pre_setup(
|
||||||
config[CONF_NAME],
|
config[CONF_NAME],
|
||||||
|
config[CONF_FRIENDLY_NAME],
|
||||||
cg.RawExpression('__DATE__ ", " __TIME__'),
|
cg.RawExpression('__DATE__ ", " __TIME__'),
|
||||||
config[CONF_NAME_ADD_MAC_SUFFIX],
|
config[CONF_NAME_ADD_MAC_SUFFIX],
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ from esphome.storage_json import (
|
|||||||
from esphome.util import get_serial_ports, shlex_quote
|
from esphome.util import get_serial_ports, shlex_quote
|
||||||
from esphome.zeroconf import DashboardImportDiscovery, DashboardStatus, EsphomeZeroconf
|
from esphome.zeroconf import DashboardImportDiscovery, DashboardStatus, EsphomeZeroconf
|
||||||
|
|
||||||
from .util import password_hash
|
from .util import password_hash, friendly_name_slugify
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -390,12 +390,24 @@ class WizardRequestHandler(BaseHandler):
|
|||||||
for k, v in json.loads(self.request.body.decode()).items()
|
for k, v in json.loads(self.request.body.decode()).items()
|
||||||
if k in ("name", "platform", "board", "ssid", "psk", "password")
|
if k in ("name", "platform", "board", "ssid", "psk", "password")
|
||||||
}
|
}
|
||||||
|
if not kwargs["name"]:
|
||||||
|
self.set_status(422)
|
||||||
|
self.set_header("content-type", "application/json")
|
||||||
|
self.write(json.dumps({"error": "Name is required"}))
|
||||||
|
return
|
||||||
|
|
||||||
|
kwargs["friendly_name"] = kwargs["name"]
|
||||||
|
kwargs["name"] = friendly_name_slugify(kwargs["friendly_name"])
|
||||||
|
|
||||||
kwargs["ota_password"] = secrets.token_hex(16)
|
kwargs["ota_password"] = secrets.token_hex(16)
|
||||||
noise_psk = secrets.token_bytes(32)
|
noise_psk = secrets.token_bytes(32)
|
||||||
kwargs["api_encryption_key"] = base64.b64encode(noise_psk).decode()
|
kwargs["api_encryption_key"] = base64.b64encode(noise_psk).decode()
|
||||||
destination = settings.rel_path(f"{kwargs['name']}.yaml")
|
filename = f"{kwargs['name']}.yaml"
|
||||||
|
destination = settings.rel_path(filename)
|
||||||
wizard.wizard_write(path=destination, **kwargs)
|
wizard.wizard_write(path=destination, **kwargs)
|
||||||
self.set_status(200)
|
self.set_status(200)
|
||||||
|
self.set_header("content-type", "application/json")
|
||||||
|
self.write(json.dumps({"configuration": filename}))
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
|
|
||||||
@ -407,6 +419,7 @@ class ImportRequestHandler(BaseHandler):
|
|||||||
args = json.loads(self.request.body.decode())
|
args = json.loads(self.request.body.decode())
|
||||||
try:
|
try:
|
||||||
name = args["name"]
|
name = args["name"]
|
||||||
|
friendly_name = args.get("friendly_name")
|
||||||
|
|
||||||
imported_device = next(
|
imported_device = next(
|
||||||
(res for res in IMPORT_RESULT.values() if res.device_name == name), None
|
(res for res in IMPORT_RESULT.values() if res.device_name == name), None
|
||||||
@ -414,12 +427,15 @@ class ImportRequestHandler(BaseHandler):
|
|||||||
|
|
||||||
if imported_device is not None:
|
if imported_device is not None:
|
||||||
network = imported_device.network
|
network = imported_device.network
|
||||||
|
if friendly_name is None:
|
||||||
|
friendly_name = imported_device.friendly_name
|
||||||
else:
|
else:
|
||||||
network = const.CONF_WIFI
|
network = const.CONF_WIFI
|
||||||
|
|
||||||
import_config(
|
import_config(
|
||||||
settings.rel_path(f"{name}.yaml"),
|
settings.rel_path(f"{name}.yaml"),
|
||||||
name,
|
name,
|
||||||
|
friendly_name,
|
||||||
args["project_name"],
|
args["project_name"],
|
||||||
args["package_import_url"],
|
args["package_import_url"],
|
||||||
network,
|
network,
|
||||||
@ -434,6 +450,8 @@ class ImportRequestHandler(BaseHandler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.set_status(200)
|
self.set_status(200)
|
||||||
|
self.set_header("content-type", "application/json")
|
||||||
|
self.write(json.dumps({"configuration": f"{name}.yaml"}))
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
|
|
||||||
@ -581,6 +599,12 @@ class DashboardEntry:
|
|||||||
return self.filename.replace(".yml", "").replace(".yaml", "")
|
return self.filename.replace(".yml", "").replace(".yaml", "")
|
||||||
return self.storage.name
|
return self.storage.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def friendly_name(self):
|
||||||
|
if self.storage is None:
|
||||||
|
return self.name
|
||||||
|
return self.storage.friendly_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def comment(self):
|
def comment(self):
|
||||||
if self.storage is None:
|
if self.storage is None:
|
||||||
@ -628,6 +652,7 @@ class ListDevicesHandler(BaseHandler):
|
|||||||
"configured": [
|
"configured": [
|
||||||
{
|
{
|
||||||
"name": entry.name,
|
"name": entry.name,
|
||||||
|
"friendly_name": entry.friendly_name,
|
||||||
"configuration": entry.filename,
|
"configuration": entry.filename,
|
||||||
"loaded_integrations": entry.loaded_integrations,
|
"loaded_integrations": entry.loaded_integrations,
|
||||||
"deployed_version": entry.update_old,
|
"deployed_version": entry.update_old,
|
||||||
@ -643,6 +668,7 @@ class ListDevicesHandler(BaseHandler):
|
|||||||
"importable": [
|
"importable": [
|
||||||
{
|
{
|
||||||
"name": res.device_name,
|
"name": res.device_name,
|
||||||
|
"friendly_name": res.friendly_name,
|
||||||
"package_import_url": res.package_import_url,
|
"package_import_url": res.package_import_url,
|
||||||
"project_name": res.project_name,
|
"project_name": res.project_name,
|
||||||
"project_version": res.project_version,
|
"project_version": res.project_version,
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
|
from esphome.const import ALLOWED_NAME_CHARS
|
||||||
|
|
||||||
|
|
||||||
def password_hash(password: str) -> bytes:
|
def password_hash(password: str) -> bytes:
|
||||||
@ -7,3 +10,23 @@ def password_hash(password: str) -> bytes:
|
|||||||
Note this is not meant for secure storage, but for securely comparing passwords.
|
Note this is not meant for secure storage, but for securely comparing passwords.
|
||||||
"""
|
"""
|
||||||
return hashlib.sha256(password.encode()).digest()
|
return hashlib.sha256(password.encode()).digest()
|
||||||
|
|
||||||
|
|
||||||
|
def strip_accents(value):
|
||||||
|
return "".join(
|
||||||
|
c
|
||||||
|
for c in unicodedata.normalize("NFD", str(value))
|
||||||
|
if unicodedata.category(c) != "Mn"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def friendly_name_slugify(value):
|
||||||
|
value = (
|
||||||
|
strip_accents(value)
|
||||||
|
.lower()
|
||||||
|
.replace(" ", "-")
|
||||||
|
.replace("_", "-")
|
||||||
|
.replace("--", "-")
|
||||||
|
.strip("-")
|
||||||
|
)
|
||||||
|
return "".join(c for c in value if c in ALLOWED_NAME_CHARS)
|
||||||
|
@ -36,6 +36,7 @@ class StorageJSON:
|
|||||||
self,
|
self,
|
||||||
storage_version,
|
storage_version,
|
||||||
name,
|
name,
|
||||||
|
friendly_name,
|
||||||
comment,
|
comment,
|
||||||
esphome_version,
|
esphome_version,
|
||||||
src_version,
|
src_version,
|
||||||
@ -51,6 +52,8 @@ class StorageJSON:
|
|||||||
self.storage_version: int = storage_version
|
self.storage_version: int = storage_version
|
||||||
# The name of the node
|
# The name of the node
|
||||||
self.name: str = name
|
self.name: str = name
|
||||||
|
# The friendly name of the node
|
||||||
|
self.friendly_name: str = friendly_name
|
||||||
# The comment of the node
|
# The comment of the node
|
||||||
self.comment: str = comment
|
self.comment: str = comment
|
||||||
# The esphome version this was compiled with
|
# The esphome version this was compiled with
|
||||||
@ -77,6 +80,7 @@ class StorageJSON:
|
|||||||
return {
|
return {
|
||||||
"storage_version": self.storage_version,
|
"storage_version": self.storage_version,
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
|
"friendly_name": self.friendly_name,
|
||||||
"comment": self.comment,
|
"comment": self.comment,
|
||||||
"esphome_version": self.esphome_version,
|
"esphome_version": self.esphome_version,
|
||||||
"src_version": self.src_version,
|
"src_version": self.src_version,
|
||||||
@ -106,6 +110,7 @@ class StorageJSON:
|
|||||||
return StorageJSON(
|
return StorageJSON(
|
||||||
storage_version=1,
|
storage_version=1,
|
||||||
name=esph.name,
|
name=esph.name,
|
||||||
|
friendly_name=esph.friendly_name,
|
||||||
comment=esph.comment,
|
comment=esph.comment,
|
||||||
esphome_version=const.__version__,
|
esphome_version=const.__version__,
|
||||||
src_version=1,
|
src_version=1,
|
||||||
@ -118,10 +123,13 @@ class StorageJSON:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_wizard(name: str, address: str, platform: str) -> "StorageJSON":
|
def from_wizard(
|
||||||
|
name: str, friendly_name: str, address: str, platform: str
|
||||||
|
) -> "StorageJSON":
|
||||||
return StorageJSON(
|
return StorageJSON(
|
||||||
storage_version=1,
|
storage_version=1,
|
||||||
name=name,
|
name=name,
|
||||||
|
friendly_name=friendly_name,
|
||||||
comment=None,
|
comment=None,
|
||||||
esphome_version=None,
|
esphome_version=None,
|
||||||
src_version=1,
|
src_version=1,
|
||||||
@ -139,6 +147,7 @@ class StorageJSON:
|
|||||||
storage = json.load(f_handle)
|
storage = json.load(f_handle)
|
||||||
storage_version = storage["storage_version"]
|
storage_version = storage["storage_version"]
|
||||||
name = storage.get("name")
|
name = storage.get("name")
|
||||||
|
friendly_name = storage.get("friendly_name")
|
||||||
comment = storage.get("comment")
|
comment = storage.get("comment")
|
||||||
esphome_version = storage.get(
|
esphome_version = storage.get(
|
||||||
"esphome_version", storage.get("esphomeyaml_version")
|
"esphome_version", storage.get("esphomeyaml_version")
|
||||||
@ -153,6 +162,7 @@ class StorageJSON:
|
|||||||
return StorageJSON(
|
return StorageJSON(
|
||||||
storage_version,
|
storage_version,
|
||||||
name,
|
name,
|
||||||
|
friendly_name,
|
||||||
comment,
|
comment,
|
||||||
esphome_version,
|
esphome_version,
|
||||||
src_version,
|
src_version,
|
||||||
|
@ -46,6 +46,11 @@ BASE_CONFIG = """esphome:
|
|||||||
name: {name}
|
name: {name}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
BASE_CONFIG_FRIENDLY = """esphome:
|
||||||
|
name: {name}
|
||||||
|
friendly_name: {friendly_name}
|
||||||
|
"""
|
||||||
|
|
||||||
LOGGER_API_CONFIG = """
|
LOGGER_API_CONFIG = """
|
||||||
# Enable logging
|
# Enable logging
|
||||||
logger:
|
logger:
|
||||||
@ -110,7 +115,12 @@ def wizard_file(**kwargs):
|
|||||||
kwargs["fallback_name"] = ap_name
|
kwargs["fallback_name"] = ap_name
|
||||||
kwargs["fallback_psk"] = "".join(random.choice(letters) for _ in range(12))
|
kwargs["fallback_psk"] = "".join(random.choice(letters) for _ in range(12))
|
||||||
|
|
||||||
config = BASE_CONFIG.format(**kwargs)
|
if kwargs.get("friendly_name"):
|
||||||
|
base = BASE_CONFIG_FRIENDLY
|
||||||
|
else:
|
||||||
|
base = BASE_CONFIG
|
||||||
|
|
||||||
|
config = base.format(**kwargs)
|
||||||
|
|
||||||
config += HARDWARE_BASE_CONFIGS[kwargs["platform"]].format(**kwargs)
|
config += HARDWARE_BASE_CONFIGS[kwargs["platform"]].format(**kwargs)
|
||||||
|
|
||||||
@ -192,7 +202,7 @@ def wizard_write(path, **kwargs):
|
|||||||
hardware = kwargs["platform"]
|
hardware = kwargs["platform"]
|
||||||
|
|
||||||
write_file(path, wizard_file(**kwargs))
|
write_file(path, wizard_file(**kwargs))
|
||||||
storage = StorageJSON.from_wizard(name, f"{name}.local", hardware)
|
storage = StorageJSON.from_wizard(name, name, f"{name}.local", hardware)
|
||||||
storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path))
|
storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path))
|
||||||
storage.save(storage_path)
|
storage.save(storage_path)
|
||||||
|
|
||||||
|
@ -119,10 +119,12 @@ TXT_RECORD_PACKAGE_IMPORT_URL = b"package_import_url"
|
|||||||
TXT_RECORD_PROJECT_NAME = b"project_name"
|
TXT_RECORD_PROJECT_NAME = b"project_name"
|
||||||
TXT_RECORD_PROJECT_VERSION = b"project_version"
|
TXT_RECORD_PROJECT_VERSION = b"project_version"
|
||||||
TXT_RECORD_NETWORK = b"network"
|
TXT_RECORD_NETWORK = b"network"
|
||||||
|
TXT_RECORD_FRIENDLY_NAME = b"friendly_name"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DiscoveredImport:
|
class DiscoveredImport:
|
||||||
|
friendly_name: Optional[str]
|
||||||
device_name: str
|
device_name: str
|
||||||
package_import_url: str
|
package_import_url: str
|
||||||
project_name: str
|
project_name: str
|
||||||
@ -174,8 +176,12 @@ class DashboardImportDiscovery:
|
|||||||
project_name = info.properties[TXT_RECORD_PROJECT_NAME].decode()
|
project_name = info.properties[TXT_RECORD_PROJECT_NAME].decode()
|
||||||
project_version = info.properties[TXT_RECORD_PROJECT_VERSION].decode()
|
project_version = info.properties[TXT_RECORD_PROJECT_VERSION].decode()
|
||||||
network = info.properties.get(TXT_RECORD_NETWORK, b"wifi").decode()
|
network = info.properties.get(TXT_RECORD_NETWORK, b"wifi").decode()
|
||||||
|
friendly_name = info.properties.get(TXT_RECORD_FRIENDLY_NAME)
|
||||||
|
if friendly_name is not None:
|
||||||
|
friendly_name = friendly_name.decode()
|
||||||
|
|
||||||
self.import_state[name] = DiscoveredImport(
|
self.import_state[name] = DiscoveredImport(
|
||||||
|
friendly_name=friendly_name,
|
||||||
device_name=node_name,
|
device_name=node_name,
|
||||||
package_import_url=import_url,
|
package_import_url=import_url,
|
||||||
project_name=project_name,
|
project_name=project_name,
|
||||||
|
@ -9,7 +9,7 @@ pyserial==3.5
|
|||||||
platformio==6.1.5 # When updating platformio, also update Dockerfile
|
platformio==6.1.5 # When updating platformio, also update Dockerfile
|
||||||
esptool==4.4
|
esptool==4.4
|
||||||
click==8.1.3
|
click==8.1.3
|
||||||
esphome-dashboard==20221231.0
|
esphome-dashboard==20230117.0
|
||||||
aioesphomeapi==13.0.2
|
aioesphomeapi==13.0.2
|
||||||
zeroconf==0.47.1
|
zeroconf==0.47.1
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
using namespace esphome;
|
using namespace esphome;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
App.pre_setup("livingroom", __DATE__ ", " __TIME__, false);
|
App.pre_setup("livingroom", "LivingRoom", __DATE__ ", " __TIME__, false);
|
||||||
auto *log = new logger::Logger(115200, 512); // NOLINT
|
auto *log = new logger::Logger(115200, 512); // NOLINT
|
||||||
log->pre_setup();
|
log->pre_setup();
|
||||||
log->set_uart_selection(logger::UART_SELECTION_UART0);
|
log->set_uart_selection(logger::UART_SELECTION_UART0);
|
||||||
|
Loading…
Reference in New Issue
Block a user