Índice:

IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS: 8 Steps
IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS: 8 Steps

Vídeo: IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS: 8 Steps

Vídeo: IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS: 8 Steps
Vídeo: Indefinite Pitch PREMIERES. Mod.1 - Into The Circle [Linderluft Records] 2024, Julho
Anonim
IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS
IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS
IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS
IOT123 - ASSIMILATE SENSOR HUB: ICOS10 CORS WEBCOMPONENTS

Os escravos ASSIMILATE SENSOR / ACTOR incorporam metadados que são usados para as visualizações de definição no Crouton. Esta construção é ligeiramente diferente das anteriores; não há mudanças de hardware. O firmware agora suporta hospedagem de editores personalizados (mais ricos) que podem ser integrados na última compilação do AssimilateCrouton. Mais atenção será dada para explicar o firmware e o painel MQTT neste artigo.

Uma das vantagens de servir WebComponents a partir do dispositivo que eles controlam, é que o controle mais avançado do dispositivo é limitado à rede a que o dispositivo está conectado: seu ponto de acesso WiFi. Embora ao usar um servidor MQTT com autenticação haja uma semelhança de proteção, em redes públicas, se você deixar seu navegador momentaneamente (site AssimilateCrouton), alguém pode entrar e controlar seus dispositivos de automação. Este recurso CORS WebComponent torna possível ter apenas leituras (temperatura, níveis de luz, umidade) mostradas publicamente e funções de comando (ligar / desligar, programação) disponíveis apenas na rede do dispositivo.

No dispositivo, todos os recursos do servidor web com autenticação e hospedagem em SPIFFS ainda são suportados, mas o foco especial foi dado para o suporte CORS (Cross Origin Resource Sharing) para Polymer WebComponents (Crouton usa Polymer 1.4.0).

Em AssimilateCrouton (o fork do Crouton usado para Assimilate IOT Network), as mudanças incluem

  • suporte para um cartão de dispositivo (assim-device) que, entre outras coisas, mostra e oculta, para um usuário, cartões individuais para um dispositivo
  • propriedade info em todos os cartões que mostra um brinde de informações contextuais úteis para um cartão
  • suporte para componentes da web CORS, neste caso hospedado no servidor da web no dispositivo (ESP8266).

Etapa 1: CROUTON

CROUTON
CROUTON
CROUTON
CROUTON

Crouton é um painel que permite visualizar e controlar seus dispositivos IOT com configuração mínima. Essencialmente, é o painel mais fácil de configurar para qualquer entusiasta de hardware IOT usando apenas MQTT e JSON.

Os ASSIMILATE SLAVES (sensores e atores) possuem metadados e propriedades embutidos que o mestre usa para construir o pacote deviceInfo json que Crouton usa para construir o painel. O intermediário entre ASSIMILATE NODES e Crouton é um broker MQTT compatível com websockets: o Mosquito é usado para a demonstração.

À medida que ASSIMILATE MASTER solicita propriedades, ele formata os valores de resposta no formato necessário para atualizações de Crouton. A bifurcação AssimilateCrouton adiciona alguns recursos que permitem descentralizar as regras de negócios que executam seu dispositivo, ou seja, o dispositivo IOT não precisa de nenhuma regra de negócios incorporada, é apenas um pipeline para comunicação MQTT / I2C com os atores e sensores escravos mais inteligentes (controlados por ATTINY).

Etapa 2: ASSIMILAR CROUTON

ASSIMILAR CROUTÃO
ASSIMILAR CROUTÃO

MUDANÇAS PARA CROUTON

As alterações da versão bifurcada incluem:

  • se um endpoint tiver uma propriedade de caminho definida, o WebComponent para o cartão fará um HTMLImport para um recurso CORS (o servidor da web no ESP8266 nesta construção).
  • quaisquer recursos upstream de (dependências de) um CORS WebComponent são referenciados como se fossem servidos a partir do site Crouton; quando eles não conseguem carregar um manipulador de exceção, reorganiza os caminhos e carrega-os a partir do site.
  • uma hora local atual é exibida no canto superior direito, útil para verificação de agendamento.

DEPENDÊNCIAS DE POLÍMERO E CORS

As folhas de uma árvore de dependência do Polymer podem ser hospedadas no CORS. Como as dependências raiz podem ser usadas várias vezes em um aplicativo, elas não podem ser referenciadas a partir de 2 locais (o site e o dispositivo) porque o Polymer Module Loader as trata como 2 recursos separados e vários erros de registro atrapalham rapidamente um aplicativo.

Por esse motivo, o WebComponent para um cartão (arquivo HTML em 1.4.0) e o arquivo CSS associado são os únicos arquivos hospedados no dispositivo. As outras dependências são referenciadas como se o WebComponent estivesse hospedado na pasta "html" no site de origem, o que torna mais fácil desenvolver os WebComponents a partir dessa pasta até que esteja pronto para fazer upload para SPIFFS no ESP8266. O AssimilateCrouton descobrirá como obter os arquivos corretos.

DESDOBRAMENTO, DESENVOLVIMENTO

O criador edfungus do Crouton original escreveu a fonte em Pug / Less e tinha um conjunto de ferramentas NPM / Grunt. Eu renderizei o Pug / Less como HTML / css e apenas editei / distribuí os arquivos renderizados. Isso quebrou o conjunto de ferramentas NPM / Grunt. A correção disso é abordada na seção FUTURO.

Você pode testar o painel localmente em sua caixa DEV:

  • Da linha de comando na pasta raiz
  • npm start
  • o lite-server é ligado para https:// localhost: 10001

Implante em um servidor da web estático:

  • copie todas as pastas exceto node_modules
  • copie index.html (e possivelmente web.config)

FUTURO

Um dos principais objetivos é fazer o upgrade para o Polymer3 e trabalhar a partir do Polymer CLI. Adicionar editores avançados e estrutura para os desenvolvedores de IOT desenvolverem seus próprios é uma alta prioridade. Eventualmente, o sistema automatizado avançado será executado totalmente a partir de clientes MQTT separados, como AssimilateCrouton.

Um exemplo do pacote deviceInfo usado para AssimilateCrouton:

{
"informação do dispositivo": {
"endPoints": {
"CC_device": {
"device_name": "ash_mezz_A3",
"tipo de cartão": "assim-dispositivo",
"ssid": "Corelines_2",
"ip_addr": "192.168.8.104",
"endpoints": [
{
"title": "Grow Lights",
"tipo de cartão": "crouton-simple-toggle",
"endpoint": "switch"
},
{
"title": "Planter Lights",
"tipo de cartão": "crouton-assim-weekview",
"endpoint": "CC_switch"
}
]
},
"CC_switch": {
"tipo de cartão": "assim-weekview",
"info": "Acende ou apaga as luzes em intervalos de 15 minutos",
"caminho": "https://192.168.8.104/cors",
"title": "Planter Lights",
"intervalo_mins": 15,
"valores": {
"valor": ""
}
},
"trocar": {
"title": "Grow Lights",
"tipo de cartão": "crouton-simple-toggle",
"info": "Liga ou desliga as luzes em uma base ad hoc",
"rótulos": {
"false": "OFF",
"true": "ON"
},
"ícones": {
"false": "sun-o",
"true": "sun-o"
},
"valores": {
"valor": 0
}
}
},
"status": "bom",
"nome": "ash_mezz_A3",
"descrição": "Escritório em Ashmore, Mezanino, Área A2",
"color": "# 4D90FE"
}
}

visualizar rawdeviceInfo.json hospedado com ❤ por GitHub

Etapa 3: MONTAGEM DO DISPOSITIVO

MONTAGEM DO DISPOSITIVO
MONTAGEM DO DISPOSITIVO
MONTAGEM DO DISPOSITIVO
MONTAGEM DO DISPOSITIVO
MONTAGEM DO DISPOSITIVO
MONTAGEM DO DISPOSITIVO

Como não há mudanças de hardware, aqui estão os links para as informações relevantes:

  • Conjunto Shell
  • Materiais e Ferramentas
  • Preparação MCU
  • Preparação da carcaça MCU
  • Construindo o Interruptor de Lado Baixo dos Escravos / Placa filha de RESET
  • Montagem dos componentes principais

Etapa 4: FIRMWARE

FIRMWARE
FIRMWARE
FIRMWARE
FIRMWARE
FIRMWARE
FIRMWARE
FIRMWARE
FIRMWARE

PRINCIPAIS ALTERAÇÕES DESTE CONSTRUÇÃO

Para que o aplicativo AssimilateCrouton possa usar os recursos CORS do dispositivo, os cabeçalhos de resposta precisam ser configurados de uma maneira particular. Isso foi implementado nesta versão do firmware (static_server.ino => server_file_read ()).

Além disso, o gráfico de dependência principal do Polymer precisava ser de uma única origem. Uma estratégia foi usada para adicionar um manipulador onerror (corsLinkOnError) aos arquivos SPIFFS CORS para recarregar os recursos do site AssimilateCrouton quando eles não forem encontrados no dispositivo.

Existem 2 novas convenções adicionadas ao sistema de arquivos SPIFFS para personalizar os terminais que são criados em deviceInfo - que AssimilateCrouton usa para criar os cartões de painel:

  • /config/user_card_base.json Definição de terminal com variáveis de tempo de execução sendo trocadas primeiro:,,. Normalmente, é aqui que o cartão do dispositivo assim será adicionado. Isso não se comunica de volta com o dispositivo.
  • /config/user_card_#.json Definição de terminal com variáveis de tempo de execução sendo trocadas primeiro:,,. Normalmente é aqui que os editores ricos, como o cartão assim-weekview, serão adicionados conectados ao escravo I2C (ator / sensor) que se relaciona com #.

O ESBOÇO / BIBLIOTECAS

Neste estágio, o projeto foi empacotado como um exemplo para a biblioteca AssimilateBus Arduino. Isso é principalmente para tornar todos os arquivos necessários fáceis de acessar a partir do IDE do Arduino. Os principais artefatos de código são:

  • mqtt_crouton_esp8266_cors_webcomponents.ino - o ponto de entrada principal.
  • assimilate_bus.h / assimilate_bus.cpp - a biblioteca que lida com a comunicação I2C com o Sensor / Atores Escravo
  • VizJson.h / VizJson.cpp - a biblioteca que formata / constrói qualquer JSON publicado via MQTT
  • config.h / config.cpp - a biblioteca que lê / caixas / grava arquivos de configuração em SPIFFS
  • static_i2c_callbacks.ino - os retornos de chamada I2C para uma propriedade sendo recebida e o ciclo de solicitações de escravos sendo concluídas static_mqtt.ino - as funções MQTT
  • static_server.ino - as funções do servidor web
  • static_utility.ino - funções auxiliares

As funções INO estáticas foram usadas (em vez de bibliotecas) por uma variedade de razões, mas principalmente para que as funções do servidor da Web e do MQTT pudessem funcionar bem juntas.

OS RECURSOS SPIFFS

Explicações detalhadas sobre os arquivos SPIFFS podem ser encontradas aqui.

  • favicon.ico - recurso usado pelo Ace Editor
  • config

    • device.json - a configuração do dispositivo (Wifi, MQTT…)
    • slave_metas _ #. json - gerado em tempo de execução para cada número de endereço de escravo (#)
    • user_card _ #. json - endpoint personalizado a ser integrado em deviceInfo para cada número de endereço escravo (#)
    • user_card_base.json - endpoint personalizado a ser integrado em deviceInfo para o dispositivo
    • user_meta _ #. json - os metadados personalizados substituem os dos escravos para cada número de endereço do escravo (#)
    • user_props.json - nomes de propriedades personalizadas para substituir aqueles nos metadados dos escravos
  • cors

    • card-webcomponent.css - folha de estilo para vários cartões personalizados
    • card-webcomponent.html - webcomponent para vários cartões personalizados
  • editor

    • assimilate-logo-p.webp" />
    • edit.htm.gz - gzip do Ace Editor HTML
    • edit.htm.src - HTML original do Ace Editor
    • favicon-32x32-p.webp" />

FAZENDO O UPLOAD DO FIRMWARE

  • O repositório de código pode ser encontrado aqui (instantâneo).
  • Um ZIP da biblioteca pode ser encontrado aqui (instantâneo).
  • Instruções para "Importar uma biblioteca ZIP" aqui.
  • Assim que a biblioteca estiver instalada, você pode abrir o exemplo "mqtt_crouton_esp8266_cors_webcomponents".
  • Instruções para configurar o Arduino para o Wemos D1 Mini aqui.
  • Dependências: ArduinoJson, TimeLib, PubSubClient, NeoTimer (veja os anexos se houver alterações nos repositórios).

CARREGAR PARA SPIFFS

Depois que o código foi carregado no IDE do Arduino, abra device.json na pasta data / config:

  • Modifique o valor de wifi_ssid com seu SSID WiFi.
  • Modifique o valor de wifi_key com sua chave WiFi.
  • Modifique o valor de mqtt_device_name com sua identificação de dispositivo preferida (sem necessidade de junção).
  • Modifique o valor de mqtt_device_description com sua descrição de dispositivo preferida (em Crouton).
  • Salve device.json.
  • Faça upload dos arquivos de dados para SPIFFS.

O principal ponto de entrada para o exemplo AssimilateBus:

/*
*
* ESPERA-SE QUE AS REGRAS DE NEGÓCIO PARA SEU DISPOSITIVO SEJAM CONTROLADAS VIA MQTT - NÃO DIFICULDADES NESTE FIRMWARE
*
* Diferente de configuração e loop neste arquivo
* as partes móveis importantes são
* on_bus_received e on_bus_complete em static_i2c_callbacks.ino
* e
* mqtt_publish e mqtt_callback em static_mqtt.ino
*
*/
#include "types.h"
#include "VizJson.h"
#include "assimilate_bus.h"
#include "debug.h"
#include "config.h"
#incluir

#incluir

// defina MQTT_MAX_PACKET_SIZE para ~ 3000 (ou suas necessidades para deviceInfo json)

#incluir
#incluir
#incluir
#incluir
#incluir
// --------------------------------- DECLARAÇÕES DE MEMÓRIA
// ------------------------------------------------ - define
# defineDBG_OUTPUT_FLAG2 // 0, 1, 2 MÍNIMO, RELEASE, FULL
#define_mqtt_pub_topic "outbox" // CROUTON CONVENTIONS
#define_mqtt_sub_topic "caixa de entrada"
// ------------------------------------------------ - objetos de classe
Debug _debug (DBG_OUTPUT_FLAG);
AssimilateBus _assimilate_bus;
VizJson _viz_json;
Config _config_data;
WiFiClient _esp_client;
PubSubClient _client (_esp_client);
WiFiUDP Udp;
ESP8266WebServer _server (80);
Neotimer _timer_property_request = Neotimer (5000);
// ------------------------------------------------ - estruturas / variáveis de dados
RuntimeDeviceData _runtime_device_data;
PropertyDto _dto_props [50]; // máximo de 10 escravos x máximo de 5 propriedades
// ------------------------------------------------ -- controle de fluxo
volatilebool _sent_device_info = false;
byte _dto_props_index = 0;
bool _fatal_error = false;
// --------------------------------- DECLARAÇÕES DE ESCOPO DE FUNÇÃO
// ------------------------------------------------ - static_i2c_callbacks.ino
voidon_bus_received (byte slave_address, byte prop_index, Role role, char name [16], char value [16]);
voidon_bus_complete ();
// ------------------------------------------------ - static_mqtt.ino
voidmqtt_callback (char * tópico, byte * carga útil, comprimento não assinado);
voidmqtt_loop ();
int8_tmqtt_get_topic_index (char * tópico);
voidmqtt_init (constchar * wifi_ssid, constchar * wifi_password, constchar * mqtt_broker, int mqtt_port);
voidmqtt_create_subscriptions ();
voidmqtt_publish (char * root_topic, char * deviceName, char * endpoint, constchar * payload);
boolmqtt_ensure_connect ();
voidmqtt_subscribe (char * root_topic, char * deviceName, char * endpoint);
voidi2c_set_and_get (endereço de byte, código de byte, parâmetro constchar *);
// ------------------------------------------------ - static_server.ino
String server_content_type_get (String nome do arquivo);
boolserver_path_in_auth_exclusion (caminho da string);
boolserver_auth_read (caminho da string);
boolserver_file_read (caminho da string);
voidserver_file_upload ();
voidserver_file_delete ();
voidserver_file_create ();
voidserver_file_list ();
voidserver_init ();
voidtime_services_init (char * ntp_server_name, byte time_zone);
time_tget_ntp_time ();
voidsend_ntp_packet (endereço IP e endereço);
char * time_stamp_get ();
// ------------------------------------------------ - static_utility.ino
String spiffs_file_list_build (String caminho);
voidreport_deserialize_error ();
voidreport_spiffs_error ();
boolcheck_fatal_error ();
boolget_json_card_type (byte slave_address, byte prop_index, char * card_type);
boolget_struct_card_type (byte slave_address, byte prop_index, char * card_type);
boolget_json_is_series (byte slave_address, byte prop_index);
voidstr_replace (char * src, constchar * oldchars, char * newchars);
byte get_prop_dto_idx (byte slave_address, byte prop_index);
//---------------------------------A PRINCIPAL
voidsetup () {
DBG_OUTPUT_PORT.begin (115200);
SetupDeviceData device_data;
Serial.println (); Serial.println (); // margem para lixo do console
atraso (5000);
if (DBG_OUTPUT_FLAG == 2) DBG_OUTPUT_PORT.setDebugOutput (true);
_debug.out_fla (F ("configuração"), verdadeiro, 2);
// obter a configuração necessária
if (SPIFFS.begin ()) {
_debug.out_str (spiffs_file_list_build ("/"), verdadeiro, 2);
if (! _config_data.get_device_data (device_data, _runtime_device_data)) {
report_deserialize_error ();
Retorna;
}
}outro{
report_spiffs_error ();
Retorna;
}
// use o valor do temporizador definido em device.json
_timer_property_request.set (device_data.sensor_interval);
mqtt_init (device_data.wifi_ssid, device_data.wifi_key, device_data.mqtt_broker, device_data.mqtt_port);
time_services_init (device_data.ntp_server_name, device_data.time_zone);
server_init ();
// inicie a coleção de metadados
_assimilate_bus.get_metadata ();
_assimilate_bus.print_metadata_details ();
mqtt_ensure_connect ();
// precisa da propriedade do sensor (nomes) para completar a coleta de metadados
_assimilate_bus.get_properties (on_bus_received, on_bus_complete);
_timer_property_request.reset (); // pode decorrer um tempo perceptível até este ponto, então comece novamente
}
voidloop () {
if (! check_fatal_error ()) return;
mqtt_loop ();
_server.handleClient ();
if (_timer_property_request.repeat ()) {
_assimilate_bus.get_properties (on_bus_received, on_bus_complete);
}
}

ver rawmqtt_crouton_esp8266_cors_webcomponents.ino hospedado com ❤ por GitHub

Etapa 5: CARTÃO DE DISPOSITIVO

CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO
CARTÃO DE DISPOSITIVO

O cartão do dispositivo (tipo cartão: assim-device) está hospedado no site e não é necessário atendê-lo a partir do dispositivo (CORS).

Sua página padrão lista:

  • Os tópicos MQTT para leitura e gravação no dispositivo
  • O ponto de acesso ao qual o dispositivo está conectado
  • Um link para o editor de arquivo SPIFFS hospedado no dispositivo usando o ACE EDITOR
  • Um ícone de olho que revela a página Mostrar / Ocultar cartão.

As listas de páginas de cartão Mostrar / Ocultar:

  • Cada cartão como um item separado
  • Fonte em negrito azul ao mostrar
  • Fonte normal preta quando oculta
  • Um ícone que descreve o tipo de cartão.

O cartão pode ser oculto clicando no botão ocultar nos cartões ou clicando em um item de fonte em negrito azul na lista. Os cartões podem ser exibidos clicando em um item de fonte normal preta na lista.

Vagamente relacionado a esse recurso estão os brindes de informações. Se qualquer um dos endpoints em deviceInfo tiver uma propriedade info atribuída, um botão de informações será mostrado próximo ao botão ocultar no cartão. Quando clicada, a informação contextual definida no endpoint será "torrada" na janela.

Se o cartão do dispositivo não estiver definido, os botões de ocultar não serão exibidos nos cartões. Isso ocorre porque, uma vez escondidos, não há como mostrá-los novamente.

Consulte PERSONALIZAÇÃO DO ENDPOINT para detalhes de como o cartão assim-device pode ser adicionado por meio dos arquivos SPIFFS no ESP8266.

AssimilateCrouton WebComponent

sinais de ferro>
div>
MOSTRAR ÍCONE OCULTAR
i> span>
FORMULÁRIO DE DISPOSITIVO
MQTT TOPICSdiv>
/ outbox / {{endPointJson.device_name}} / * div>
/ inbox / {{endPointJson.device_name}} / * div>
WIFI SSIDdiv>
{{endPointJson.ssid}} div>
ENDEREÇO IP div>
{{endPointJson.ip_addr}} a> div>
div>
MOSTRAR OCULTAR LISTA
elemento>item de papel>
template>
caixa de listagem de papel>
div>
cartão de pão torrado>
template>
módulo dom>

visualizar rawassim-device.html hospedado com ❤ por GitHub

Etapa 6: CARTÃO WEEKVIEW

CARTÃO DE VISUALIZAÇÃO DA SEMANA
CARTÃO DE VISUALIZAÇÃO DA SEMANA
CARTÃO DE VISUALIZAÇÃO DA SEMANA
CARTÃO DE VISUALIZAÇÃO DA SEMANA
CARTÃO DE VISUALIZAÇÃO DA SEMANA
CARTÃO DE VISUALIZAÇÃO DA SEMANA

O cartão de visualização semanal (tipo de cartão: assim-visualização semanal) está hospedado no dispositivo (pasta cors). Ele é injetado no pacote deviceInfo publicado para AssimilateCrouton, adicionando um arquivo config / user_card _ #. Json ao SPIFFS (neste caso user_card_9.json).

VISÃO GLOBAL

Os dias da semana são apresentados como listas de intervalos de tempo. A granularidade do intervalo de tempo é definida com a propriedade "interval_mins" em config / user_card _ #. Json. Precisa ser uma fração de hora ou múltiplos de uma hora, por exemplo, 10, 15, 20, 30, 60, 120, 360. Clicar em um intervalo de tempo garante que um estado ligado seja comandado para o dispositivo associado naquele momento. Se o intervalo de tempo for agora, um comando é enviado (publicado) imediatamente para o dispositivo. Normalmente, o estado é verificado / publicado a cada minuto. As seleções são salvas em LocalStorage, de modo que os horários sejam recarregados com uma atualização do navegador.

CASOS DE USO

Em seu estado atual, a visualização da semana é adequada para dispositivos que podem usar um botão de alternância para visualizar seu estado, ou seja, eles estão ligados ou desligados e, após serem configurados, permanecem nesse estado. Luzes, ventiladores e aquecedores de água são bons candidatos.

LIMITAÇÕES / CAVEATS

  • O intervalo_mins deve ser um dos valores mencionados acima
  • A visualização semanal não suporta ações momentâneas que também são programadas, como abrir uma torneira brevemente (5 segundos) duas vezes por dia.

FUTURO

  • Espera-se que ações momentâneas sejam apoiadas.
  • Armazenamento sincronizado entre dispositivos, para as seleções de programação, está sendo considerado.

Etapa 7: PERSONALIZAÇÃO DO ENDPOINT

Conforme mencionado brevemente no FIRMWARE, existem 2 novas convenções adicionadas ao sistema de arquivos SPIFFS para personalizar os terminais. Os arquivos JSON são fragmentos que são incluídos na propriedade de terminais no pacote deviceInfo postado no broker MQTT que se torna a definição do painel.

As chaves dos endpoints são geradas no firmware:

  • CC_device (cartão personalizado) para o user_card_base.json
  • CC_SLAVE_ENDPOINT NAME para o user_card _ #. Json (# sendo o endereço escravo)

Conforme mencionado antes, existem variáveis que são substituídas por valores em tempo de execução:

  • mqtt_device_name
  • wifi_ssid
  • local_ip

user_card_base.json

Um exemplo:

user_card _ #. json

Um exemplo:

Etapa 8: VÍDEOS

Recomendado: