fix skateboard

This commit is contained in:
sfja 2026-03-28 23:45:25 +01:00
parent da33911aa3
commit 77a21035c3
8 changed files with 253 additions and 46 deletions

View File

@ -1,2 +1,4 @@
listener 1883
allow_anonymous true
password_file mqtt_users password_file mqtt_users

View File

@ -1,5 +1,5 @@
idf_component_register( idf_component_register(
SRCS skateboard.c app_wifi.c app_mpu.c SRCS skateboard.c app_wifi.c app_mpu.c app_mqtt.c
PRIV_REQUIRES nvs_flash esp_wifi PRIV_REQUIRES nvs_flash esp_netif esp_wifi mqtt
INCLUDE_DIRS ".") INCLUDE_DIRS ".")

View File

@ -1,17 +1,31 @@
menu "Skateboard config" menu "Skateboard config"
config SKATEBOARD_WIFI_SSID config WIFI_SSID
string "WIFI SSID" string "WIFI SSID"
default "myssid" default "myssid"
config SKATEBOARD_WIFI_PASSWORD config WIFI_PASSWORD
string "WIFI password" string "WIFI password"
default "mypassword" default "mypassword"
config SKATEBOARD_WIFI_MAXIMUM_RETRIES config WIFI_MAXIMUM_RETRIES
int "WIFI maximum connection retries" int "WIFI maximum connection retries"
default 5 default 5
config MQTT_URL
string "MQTT URL"
default "mqtt://mqtt.eclipseprojects.io"
help
URL of the broker to connect to
config MQTT_USERNAME
string "MQTT Username"
default "test"
config MQTT_PASSWORD
string "MQTT Password"
default "1234"
choice MPU6050_I2C_ADDRESS choice MPU6050_I2C_ADDRESS
prompt "Select I2C address" prompt "Select I2C address"
default MPU6050_I2C_ADDRESS_LOW default MPU6050_I2C_ADDRESS_LOW

142
skateboard/main/app_mqtt.c Normal file
View File

@ -0,0 +1,142 @@
#include "app_mqtt.h"
#include "esp_event_base.h"
#include "esp_log.h"
#include "freertos/projdefs.h"
#include "mqtt_client.h"
#include "sdkconfig.h"
#include <string.h>
extern const char* TAG;
enum {
Ev_Connected = 1 << 0,
Ev_Failed = 1 << 1,
};
static void event_cb(void* arg, esp_event_base_t base, int32_t id, void* data)
{
AppMqtt* mqtt = arg;
esp_mqtt_event_handle_t event = data;
esp_mqtt_client_handle_t client = event->client;
(void)client;
if (id == MQTT_EVENT_CONNECTED) {
xEventGroupSetBits(mqtt->event_group, Ev_Connected);
return;
}
if (id == MQTT_EVENT_ERROR) {
ESP_LOGE(TAG, "MQTT error occured");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
if (event->error_handle->esp_tls_last_esp_err) {
ESP_LOGE(TAG,
"Error reported in esp-tls: 0x%x",
event->error_handle->esp_tls_last_esp_err);
} else if (event->error_handle->esp_tls_stack_err) {
ESP_LOGE(TAG,
"Error reported in tls stack: 0x%x",
event->error_handle->esp_tls_stack_err);
} else if (event->error_handle->esp_transport_sock_errno) {
ESP_LOGE(TAG,
"Error captured as transport's socket errno: 0x%x",
event->error_handle->esp_transport_sock_errno);
}
ESP_LOGI(TAG,
"Last errno string (%s)",
strerror(event->error_handle->esp_transport_sock_errno));
}
xEventGroupSetBits(mqtt->event_group, Ev_Failed);
return;
}
if (id == MQTT_EVENT_DATA) {
for (size_t i = 0; i < mqtt->subs_counts; ++i) {
size_t sub_topic_len = strlen(mqtt->subs[i].topic);
if (sub_topic_len == event->topic_len
&& strncmp(mqtt->subs[i].topic, event->topic, event->topic_len)
== 0) {
mqtt->subs[i].callback(event->topic,
event->topic_len,
event->data,
event->data_len,
mqtt->subs[i].arg);
break;
}
}
return;
}
}
void app_mqtt_init(AppMqtt* mqtt)
{
ESP_LOGI(TAG, "Initializing MQTT");
*mqtt = (AppMqtt) {
.event_group = xEventGroupCreate(),
.subs_counts = 0,
};
esp_mqtt_client_config_t mqtt_config = {
.broker.address.uri = CONFIG_MQTT_URL,
.credentials.username = CONFIG_MQTT_USERNAME,
.credentials.authentication.password = CONFIG_MQTT_PASSWORD,
};
mqtt->client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(
mqtt->client, ESP_EVENT_ANY_ID, event_cb, mqtt);
esp_mqtt_client_start(mqtt->client);
ESP_LOGI(TAG, "MQTT started");
EventBits_t event_bits = xEventGroupWaitBits(mqtt->event_group,
Ev_Connected | Ev_Failed,
pdFALSE,
pdFALSE,
pdMS_TO_TICKS(1000 * 60 * 2));
if (event_bits & Ev_Connected) {
ESP_LOGI(TAG, "Connected to MQTT broker at %s", CONFIG_MQTT_URL);
} else {
ESP_LOGE(
TAG, "Could not connect to MQTT broker at %s", CONFIG_MQTT_URL);
}
}
void app_mqtt_subscribe(
AppMqtt* mqtt, const char* topic, AppMqttSubCb callback, void* arg)
{
if (mqtt->subs_counts + 1 >= app_mqtt_subs_max_count) {
ESP_LOGE(TAG,
"Max MQTT subscriptions exceeded (%d)",
app_mqtt_subs_max_count);
return;
}
int status = esp_mqtt_client_subscribe_single(mqtt->client, topic, 0);
if (status < 0) {
ESP_LOGE(TAG, "Could not subscribe to MQTT topic '%s'", topic);
return;
}
mqtt->subs[mqtt->subs_counts++] = (AppMqttSub) { topic, callback, arg };
}
void app_mqtt_publish(
AppMqtt* mqtt, const char* topic, const void* data, size_t size)
{
int status
= esp_mqtt_client_publish(mqtt->client, topic, data, (int)size, 1, 0);
if (status < 0) {
ESP_LOGE(TAG, "Could not publish to MQTT topic '%s'", topic);
return;
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "mqtt_client.h"
#include <stddef.h>
typedef void (*AppMqttSubCb)(const char* topic,
size_t topic_size,
const void* data,
size_t data_size,
void* arg);
typedef struct {
const char* topic;
AppMqttSubCb callback;
void* arg;
} AppMqttSub;
#define app_mqtt_subs_max_count 4
typedef struct AppMqtt {
EventGroupHandle_t event_group;
esp_mqtt_client_handle_t client;
AppMqttSub subs[app_mqtt_subs_max_count];
size_t subs_counts;
} AppMqtt;
void app_mqtt_init(AppMqtt* mqtt);
void app_mqtt_subscribe(
AppMqtt* mqtt, const char* topic, AppMqttSubCb callback, void* arg);
void app_mqtt_publish(
AppMqtt* mqtt, const char* topic, const void* data, size_t size);

View File

@ -5,17 +5,12 @@
extern const char* TAG; extern const char* TAG;
#define WIFI_SSID CONFIG_SKATEBOARD_WIFI_SSID
#define WIFI_PASSWORD CONFIG_SKATEBOARD_WIFI_PASSWORD
#define WIFI_MAXIMUM_RETRIES CONFIG_SKATEBOARD_WIFI_MAXIMUM_RETRIES
enum { enum {
Ev_Connected = 1 << 0, Ev_Connected = 1 << 0,
Ev_Failed = 1 << 1, Ev_Failed = 1 << 1,
}; };
static void event_handler( static void event_cb(void* arg, esp_event_base_t base, int32_t id, void* data)
void* arg, esp_event_base_t base, int32_t id, void* data)
{ {
AppWifi* app = arg; AppWifi* app = arg;
@ -27,17 +22,17 @@ static void event_handler(
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) { if (base == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect(); esp_wifi_connect();
if (app->wifi_retries < WIFI_MAXIMUM_RETRIES) { if (app->wifi_retries < CONFIG_WIFI_MAXIMUM_RETRIES) {
esp_wifi_connect(); esp_wifi_connect();
app->wifi_retries += 1; app->wifi_retries += 1;
ESP_LOGE(TAG, ESP_LOGE(TAG,
"WIFI connection failed. Retrying (%d/%d)", "WIFI connection failed. Retrying (%d/%d)",
app->wifi_retries + 1, app->wifi_retries + 1,
WIFI_MAXIMUM_RETRIES); CONFIG_WIFI_MAXIMUM_RETRIES);
return; return;
} }
xEventGroupSetBits(app->wifi_event_group, Ev_Failed); xEventGroupSetBits(app->event_group, Ev_Failed);
return; return;
} }
@ -47,32 +42,32 @@ static void event_handler(
ESP_LOGI(TAG, ESP_LOGI(TAG,
"WIFI connected with IP " IPSTR, "WIFI connected with IP " IPSTR,
IP2STR(&ip_event->ip_info.ip)); IP2STR(&ip_event->ip_info.ip));
xEventGroupSetBits(app->wifi_event_group, Ev_Connected); xEventGroupSetBits(app->event_group, Ev_Connected);
return; return;
} }
} }
void app_wifi_init(AppWifi* wifi) void app_wifi_init(AppWifi* wifi)
{ {
wifi->wifi_event_group = xEventGroupCreate(); ESP_LOGI(TAG, "Initializing WIFI");
wifi->event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta(); esp_netif_create_default_wifi_sta();
wifi_init_config_t init_config = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&init_config)); ESP_ERROR_CHECK(esp_wifi_init(&init_config));
ESP_ERROR_CHECK(esp_event_handler_instance_register( ESP_ERROR_CHECK(esp_event_handler_instance_register(
WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, wifi, NULL)); WIFI_EVENT, ESP_EVENT_ANY_ID, &event_cb, wifi, NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register( ESP_ERROR_CHECK(esp_event_handler_instance_register(
IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, wifi, NULL)); IP_EVENT, IP_EVENT_STA_GOT_IP, &event_cb, wifi, NULL));
wifi_config_t config = { wifi_config_t config = {
.sta = { .sta = {
.ssid = WIFI_SSID, .ssid = CONFIG_WIFI_SSID,
.password = WIFI_PASSWORD, .password = CONFIG_WIFI_PASSWORD,
.threshold.authmode = WIFI_AUTH_WPA2_PSK, .threshold.authmode = WIFI_AUTH_WPA2_PSK,
}, },
}; };
@ -82,20 +77,15 @@ void app_wifi_init(AppWifi* wifi)
ESP_LOGI(TAG, "WIFI started"); ESP_LOGI(TAG, "WIFI started");
EventBits_t event_bits = xEventGroupWaitBits(wifi->wifi_event_group, EventBits_t event_bits = xEventGroupWaitBits(wifi->event_group,
Ev_Connected | Ev_Failed, Ev_Connected | Ev_Failed,
pdFALSE, pdFALSE,
pdFALSE, pdFALSE,
portMAX_DELAY); pdMS_TO_TICKS(1000 * 60 * 2));
if (event_bits & Ev_Connected) { if (event_bits & Ev_Connected) {
ESP_LOGI(TAG, "WIFI connected to %s / '%s'", WIFI_SSID, WIFI_PASSWORD); ESP_LOGI(TAG, "WIFI connected to %s", CONFIG_WIFI_SSID);
} else if (event_bits & Ev_Failed) {
ESP_LOGE(TAG,
"WIFI failed connecting to %s / '%s'",
WIFI_SSID,
WIFI_PASSWORD);
} else { } else {
ESP_LOGE(TAG, "Unexpected event"); ESP_LOGE(TAG, "WIFI failed connecting to %s", CONFIG_WIFI_SSID);
} }
} }

View File

@ -3,7 +3,7 @@
#include "freertos/idf_additions.h" #include "freertos/idf_additions.h"
typedef struct AppWifi { typedef struct AppWifi {
EventGroupHandle_t wifi_event_group; EventGroupHandle_t event_group;
int wifi_retries; int wifi_retries;
} AppWifi; } AppWifi;

View File

@ -1,41 +1,66 @@
#include "app_mpu.h" #include "app_mpu.h"
#include "app_mqtt.h"
#include "app_wifi.h" #include "app_wifi.h"
#include "esp_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_netif.h"
#include "freertos/idf_additions.h" #include "freertos/idf_additions.h"
#include "i2cdev.h"
#include "mpu6050.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
const char* TAG = "skateboard"; const char* TAG = "skateboard";
typedef struct App { typedef struct App {
AppWifi wifi; AppWifi wifi;
AppMpu mpu; AppMpu mpu;
AppMqtt mqtt;
} App; } App;
#define msg_buffer_capacity 1024
char msg_buffer[msg_buffer_capacity];
static void configure_cb(const char* topic,
size_t topic_size,
const void* data,
size_t data_size,
void* arg)
{
App* app = arg;
(void)app;
ESP_LOGI(TAG, "Received configure event (%.*s)", (int)topic_size, topic);
ESP_LOGI(TAG, "Data: %.*s", (int)data_size, (const char*)data);
}
void app_main(void) void app_main(void)
{ {
ESP_LOGI(TAG, "Initializing"); ESP_LOGI(TAG, "Initializing");
ESP_LOGI(TAG, "IDF version: %s", esp_get_idf_version()); ESP_LOGI(TAG, "IDF version: %s", esp_get_idf_version());
esp_err_t status = nvs_flash_init(); esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
if (status == ESP_ERR_NVS_NO_FREE_PAGES esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
|| status == ESP_ERR_NVS_NEW_VERSION_FOUND) { esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_erase()); esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
status = nvs_flash_init(); esp_log_level_set("transport", ESP_LOG_VERBOSE);
} esp_log_level_set("outbox", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(status);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
App app = { App app = {
.wifi = { .wifi = {
.wifi_event_group = 0, .event_group = 0,
.wifi_retries = 0, .wifi_retries = 0,
}, },
}; };
app_wifi_init(&app.wifi); app_wifi_init(&app.wifi);
app_mpu_init(&app.mpu); app_mpu_init(&app.mpu);
app_mqtt_init(&app.mqtt);
app_mqtt_subscribe(&app.mqtt, "/skateboard/configure", configure_cb, &app);
ESP_LOGI(TAG, "Initialized"); ESP_LOGI(TAG, "Initialized");
ESP_LOGI(TAG, "Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
@ -54,10 +79,11 @@ void app_main(void)
float temp; float temp;
app_mpu_read_temperature(&app.mpu, &temp); app_mpu_read_temperature(&app.mpu, &temp);
ESP_LOGI(TAG, int msg_size = snprintf(msg_buffer,
"Acceleration: x=% 7.2f y=% 7.2f z=% 7.2f " msg_buffer_capacity - 1,
"Rotation: x=% 7.1f y=% 7.1f z=% 7.1f " "{ \"acceleration\": [%.4f, %.4f, %.4f], "
"Temperature: % 2.1f", "\"rotation\": [%.4f, %.4f, %.4f], "
"\"temperature\": %.2f }",
accel_x, accel_x,
accel_y, accel_y,
accel_z, accel_z,
@ -66,6 +92,8 @@ void app_main(void)
rotation_z, rotation_z,
temp); temp);
app_mqtt_publish(&app.mqtt, "/skateboard/update", msg_buffer, msg_size);
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(200));
} }
} }