WiFi not coming up with matter devices
Posted: Tue Apr 16, 2024 8:16 pm
I am working on creating/learning about the matter implementations using the arduino IDE with a ESP32-Wroom based design. Mostly just using a generic development kit while I wait for next gen custom pcbs to be designed and fabricated.
I am using the https://github.com/Yacubane/esp32-arduino-matter library as a launching point, and can successfully commission a thermostat device (although limits to temperature imposed by amazon will be a problem here, but that's later). During the commissioning process (Bluetooth I assume is used), I am asked for my Wi-Fi credentials which are given, and that appears to be accepted, no errors in the serial port logs that I can catch. After this point, the device is registered in my Alexa devices and data is updated so I think that is all working.
Now, I want to be able to do an http(s) over the air update based on a web server. To implement this I have implemented the unsecure implementation of https://github.com/chrisjoyce911/esp32FOTA, specifically https://github.com/chrisjoyce911/esp32F ... t_cert.ino with applicable pointers to the json, firmware type, on L27-28 to match my needs. This works as well in a stand-alone implementation.
Now I am trying to merge them, and finding that in-fact the WiFi is not connecting to my network based on the credentials acquired in the commissioning process so the update routine fails to contact the server.
How can I merge these two and get the user provided (as opposed to hard coded) WiFi credentials to bring up the WiFi network?
when I try to bring up my network manually with hard coded values (line 265 in sourcecode), I get error
source code to reproduce
I am using the https://github.com/Yacubane/esp32-arduino-matter library as a launching point, and can successfully commission a thermostat device (although limits to temperature imposed by amazon will be a problem here, but that's later). During the commissioning process (Bluetooth I assume is used), I am asked for my Wi-Fi credentials which are given, and that appears to be accepted, no errors in the serial port logs that I can catch. After this point, the device is registered in my Alexa devices and data is updated so I think that is all working.
Now, I want to be able to do an http(s) over the air update based on a web server. To implement this I have implemented the unsecure implementation of https://github.com/chrisjoyce911/esp32FOTA, specifically https://github.com/chrisjoyce911/esp32F ... t_cert.ino with applicable pointers to the json, firmware type, on L27-28 to match my needs. This works as well in a stand-alone implementation.
Now I am trying to merge them, and finding that in-fact the WiFi is not connecting to my network based on the credentials acquired in the commissioning process so the update routine fails to contact the server.
How can I merge these two and get the user provided (as opposed to hard coded) WiFi credentials to bring up the WiFi network?
when I try to bring up my network manually with hard coded values (line 265 in sourcecode), I get error
Code: Select all
E (8450) esp_netif_lwip: esp_netif_new: Failed to configure netif with config=0x3ffd9104 (config or if_key is NULL or duplicate key)
assert failed: esp_netif_create_default_wifi_ap wifi_default.c:319 (netif)
Backtrace: 0x40083801:0x3ffd8ba0 0x40095b61:0x3ffd8bc0 0x4009b2f9:0x3ffd8be0 0x400f07cd:0x3ffd8d10 0x400d7e11:0x3ffd8d40 0x400d7f8e:0x3ffd8ed0 0x400d806c:0x3ffd8ef0 0x400d8824:0x3ffd8f10 0x400d2da2:0x3ffd8f30 0x400dde69:0x3ffd8f80
Code: Select all
/* there is a limitation on alexa that thermostats cannot go higher than 90F
* so they will not work for this application. It will be reverted to a temp
* sensor and some other form of set-point comparison
*/
#include <esp_task_wdt.h>
#include <Arduino.h>
//#include <WiFi.h>
#include <esp_wifi.h>
// ----------------------------- Over The Air updates -------------------------
//#include <FS.h>
//#include <SPIFFS.h>
#include <esp32fota.h>
const char *manifest_url = "https://ics-ctrl.com/files/ArduinoFirmware/Kitchenery/fota.json";
const String VERSION = "0.0.1";
const String TYPE = "esp32-Kettle-http";
esp32FOTA esp32FOTA(TYPE, VERSION, false, true);
// -----------------------------------------------------------------------------
// ------------------------------ MATTER BEGIN ---------------------------------
// -----------------------------------------------------------------------------
// update platform.txt to change esp32 -std=gnu++11 to -std=gnu++17
// C:\Users\<user>\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.14
// manually install matter library
// https://github.com/Yacubane/esp32-arduino-matter
#include <Matter.h>
#include <app/server/OnboardingCodesUtil.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <esp_matter_attribute_utils.h>
// Configure device version, vendor names, see here for comments and details
// C:\Users\<user>\Documents\Arduino\libraries\ESP32_Arduino_Matter\src\include\platform\CHIPDeviceConfig.h"
// ...
// lots more options, go see the file mentioned above
using namespace chip;
using namespace chip::app::Clusters;
using namespace esp_matter;
using namespace esp_matter::endpoint;
// Cluster and attribute ID used by Matter Temperature device
const uint32_t CLUSTER_ID_TEMP = TemperatureMeasurement::Id;
const uint32_t ATTRIBUTE_ID_TEMP = TemperatureMeasurement::Attributes::MeasuredValue::Id;
const uint16_t temperature_endpoint_id = 1;
int16_t Temper; // formatted temperature for matter updates
int16_t Mode = 4; //mode for the system to use under matter
int16_t HeatingTemp = 60; //(Degrees C)
// Cluster and attribute ID used by Matter Thermostat device
const uint16_t thermostat_endpoint_id = 1;
const uint32_t CLUSTER_ID_THERM = Thermostat::Id;
esp_matter_attr_val_t matterValue; //share variable that should be set locally prior to usage
// There is possibility to listen for various device events, related for example
// to setup process. Leaved as empty for simplicity.
static void on_device_event(const ChipDeviceEvent *event, intptr_t arg) {}
static esp_err_t on_identification(identification::callback_type_t type,
uint16_t endpoint_id, uint8_t effect_id,
uint8_t effect_variant, void *priv_data) {
return ESP_OK;
}
// Listener on attribute update requests.
int newValue = 0;
static esp_err_t on_attribute_update(attribute::callback_type_t type,
uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id,
esp_matter_attr_val_t *val,
void *priv_data) {
// do something useful here
if (type == attribute::PRE_UPDATE) {
Serial.print("Update on endpoint: ");
Serial.print(endpoint_id);
Serial.print(" cluster: ");
Serial.print(cluster_id);
Serial.print(" attribute: ");
Serial.print(attribute_id);
newValue = val->val.i;
Serial.print(" value: ");
Serial.println(newValue);
//.val_print(endpoint_id,cluster_id,attribute_id,*val,true);
}
if (endpoint_id == thermostat_endpoint_id) {
//Serial.println("entering into endpoint ID checkpoint");
if (cluster_id == CLUSTER_ID_THERM) {
// Update the thermostat occupied setpoint value
if (attribute_id == Thermostat::Attributes::OccupiedHeatingSetpoint::Id) {
Serial.println("entering into Occupied Setpoint checkpoint");
HeatingTemp = newValue;
}
}
}
return ESP_OK;
}
void print_endpoint_info(String clusterName, endpoint_t *endpoint) {
uint16_t endpoint_id = endpoint::get_id(endpoint);
Serial.print(clusterName);
Serial.print(" has endpoint: ");
Serial.println(endpoint_id);
}
// ------------------------------ General user timers--------------------------
#define SERIAL_BAUDRATE 115200
unsigned long sysTimer5000 = 0;
unsigned long sysTimer500 = 0;
unsigned long sysTimer50 = 0;
unsigned long sysTimer1 = 0;
// -----------------------------------------------------------------------------
// ------------------------------ADC SENSORS BEGIN -----------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --------------------- ADC SENSORS - NTC TEMP BEGIN --------------------------
// -----------------------------------------------------------------------------
#define TEMP_SENSOR_POWER_PIN 32
#define TEMP_SENSOR_PIN A3
#define TEMP_REFERENCE_RESISTANCE 10000
#define TEMP_NOMINAL_RESISTANCE 10000
#define TEMP_NOMINAL_TEMPERATURE 25
#define TEMP_B_VALUE 3950
#define ESP32_ANALOG_RESOLUTION 4095
#include "NTC_Thermistor.h"
Thermistor *thermistor;
float ntcReadTemp(bool Celsius) {
float temp;
// power up the power (GPIO power supply)
digitalWrite(TEMP_SENSOR_POWER_PIN, HIGH);
delay(3); // need ~3ms to ramp up the capacitor due to RC time constant
// * delay and power has been left ON as the delay causes the LCD to flicker
thermistor = new NTC_Thermistor(
TEMP_SENSOR_PIN,
TEMP_REFERENCE_RESISTANCE,
TEMP_NOMINAL_RESISTANCE,
TEMP_NOMINAL_TEMPERATURE,
TEMP_B_VALUE,
ESP32_ANALOG_RESOLUTION // <- for a thermistor calibration
);
if (!Celsius) {
temp = thermistor->readFahrenheit(); // Read temperature F
} else {
temp = thermistor->readCelsius(); // Read temperature C
}
//power down the power pin
digitalWrite(TEMP_SENSOR_POWER_PIN, LOW);
return (temp);
}
// -----------------------------------------------------------------------------
// --------------------- ADC SENSORS - NTC TEMP END ----------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// ----------------------------- ADC SENSORS END--------------------------------
// -----------------------------------------------------------------------------
#define WLAN_SSID "Loranger_U"
#define WLAN_PASS "FFFFF00000"
void setup() {
// some online examples thought there might be some watchdog timeouts on http,
// give it some extra time to work.
esp_task_wdt_init(60, true);
// Init serial port and clean garbage
Serial.begin(115200);
Serial.println();
delay(3000); //debugging delay to allow the serial port to enumerate in windows
//make sure the wifi is in a good state
esp_log_level_set("wifi", ESP_LOG_INFO); // Enable wifi driver logging
tcpip_adapter_init();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//power pin for the NTC temp probe
pinMode(TEMP_SENSOR_POWER_PIN, OUTPUT);
// ------------------------------ MATTER STUFF --------------------------------
// Enable debug logging
esp_log_level_set("*", ESP_LOG_ERROR);
// Create the node (layer 2)
node::config_t node_config;
node_t *node = node::create(&node_config, on_attribute_update, on_identification);
//create thermostat endpoint
endpoint_t *therm_endpoint;
cluster_t *therm_cluster;
thermostat::config_t therm_config;
therm_config.thermostat.local_temperature = 2400;
therm_endpoint = thermostat::create(node, &therm_config, ENDPOINT_FLAG_NONE, NULL);
print_endpoint_info("thermostat", therm_endpoint);
uint16_t therm_endpoint_id = endpoint::get_id(therm_endpoint);
print_endpoint_info("Thermostat_endpoint", therm_endpoint);
// Add additional feature
therm_cluster = cluster::get(therm_endpoint, Thermostat::Id);
cluster::thermostat::feature::heating::config_t heating_config;
//units of temperature are in 0.01 Celsius for matter interactions
heating_config.abs_max_heat_setpoint_limit = 10500;
heating_config.abs_min_heat_setpoint_limit = 1500;
heating_config.max_heat_setpoint_limit = 10500;
heating_config.min_heat_setpoint_limit = 1500;
heating_config.pi_heating_demand = 0;
heating_config.occupied_heating_setpoint = 10500;
cluster::thermostat::feature::heating::add(therm_cluster, &heating_config);
//set heating step size
matterValue = esp_matter_int16(5); //5C
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::SetpointChangeAmount::Id, &matterValue);
// set operating mode to heating (default to "auto", trying to override that)
matterValue = esp_matter_int16(4);
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::ThermostatRunningMode::Id, &matterValue);
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::SystemMode::Id, &matterValue);
//set heating occupied setpoint temp (units of degrees C)
matterValue = esp_matter_int16(HeatingTemp);
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::OccupiedHeatingSetpoint::Id, &matterValue);
// set maximum set point
matterValue = esp_matter_int16(HeatingTemp + 5);
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::AbsMaxHeatSetpointLimit::Id, &matterValue);
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::MaxHeatSetpointLimit::Id, &matterValue);
// Setup DAC (this is good place to also set custom commission data, passcodes etc.)
esp_matter::set_custom_dac_provider(chip::Credentials::Examples::GetExampleDACProvider());
esp_matter::start(on_device_event);
PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
}
void loop() {
if (millis() > (sysTimer5000)) {
sysTimer5000 = millis() + 5000; // update timer
esp32FOTA.setManifestURL(manifest_url);
esp32FOTA.printConfig();
//if (false) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WIFI IS CONNECTED -- HOORAY");
bool OTAneeded = esp32FOTA.execHTTPcheck();
Serial.print("OTAneeded: ");
Serial.println(OTAneeded);
if (OTAneeded) {
Serial.println("OTA update is needed, running updates now");
Serial.print("OTA update starting");
esp32FOTA.execOTA();
Serial.print("OTA update completed");
ESP.restart();
}
} else {
Serial.println("WIFI IS NOT CONNECTED -- BOOOO");
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println(WiFi.localIP());
}
if (millis() > (sysTimer500)) {
sysTimer500 = millis() + 1500; // update timer
//Send temperature to Matter
matterValue = esp_matter_int16(((75 - 32) * 5 / 9) * 100); //scale measured value to matter input
attribute::update(thermostat_endpoint_id, CLUSTER_ID_THERM, Thermostat::Attributes::LocalTemperature::Id, &matterValue);
}
if (millis() > (sysTimer50)) {
sysTimer50 = millis() + 50; // update timer
}
if (millis() > (sysTimer1)) {
sysTimer1 = millis() + 1; // update timer
}
}
}