From 5595d47e3f60b139b9743eed4e0ce6d54f2be80b Mon Sep 17 00:00:00 2001 From: SylvanArnold <89144178+SylvanArnold@users.noreply.github.com> Date: Tue, 20 May 2025 09:52:21 +0200 Subject: [PATCH 1/6] feat(pico-sensor): added callback in mqtt client to process incomming messages in application --- pico-sensor/src/application.c | 5 +++++ pico-sensor/src/mqtt_client.c | 35 ++++++++++++++++++----------------- pico-sensor/src/mqtt_client.h | 26 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/pico-sensor/src/application.c b/pico-sensor/src/application.c index 16268fe..d118256 100644 --- a/pico-sensor/src/application.c +++ b/pico-sensor/src/application.c @@ -136,6 +136,10 @@ static void MqttTask(void *pv) { } /* for */ } +static void MyMqttMessageCallback(topic_ID_e topic, const unsigned char *payload, size_t len) { + McuLog_info("MQTT message received, topic: %d, payload: %.*s", topic, (int)len, payload); +} + #endif void App_Init(void) { @@ -154,6 +158,7 @@ void App_Init(void) { } #endif #if PL_CONFIG_USE_MQTT_CLIENT + MqttClient_RegisterMessageCallback(MyMqttMessageCallback); // register the callback for incoming messages if (xTaskCreate( MqttTask, /* pointer to the task */ "mqtt", /* task name for kernel awareness debugging */ diff --git a/pico-sensor/src/mqtt_client.c b/pico-sensor/src/mqtt_client.c index 32fd1f3..c9856e4 100644 --- a/pico-sensor/src/mqtt_client.c +++ b/pico-sensor/src/mqtt_client.c @@ -39,20 +39,6 @@ #define TOPIC_NAME_CHARGER_CHARGING_POWER "home/charger/power" #endif -typedef enum topic_ID_e { - Topic_ID_None, -#if MQTT_CLIENT_IS_EV_CHARGER - Topic_ID_Solar_Power, /* power from PV panels */ - Topic_ID_Site_Power, /* power to the house/site */ - Topic_ID_Grid_Power, /* power from/to grid */ - Topic_ID_Battery_Power, /* power from/to battery */ - Topic_ID_Battery_Percentage,/* battery level percentage */ - Topic_ID_Charging_Power, /* actual charging power */ -#elif MQTT_CLIENT_IS_SENSOR - Topic_ID_Sensor_Update, -#endif -} topic_ID_e; - /* default entries for the MQTT broker connection */ #define MQTT_DEFAULT_BROKER "homeassistant" #define MQTT_DEFAULT_CLIENT "client" @@ -91,6 +77,13 @@ static const struct mqtt_connect_client_info_t mqtt_client_info = { #endif }; +// Static variable to hold the callback pointer +static MqttClient_MessageCallback_t app_message_callback = NULL; + +void MqttClient_RegisterMessageCallback(MqttClient_MessageCallback_t cb) { + app_message_callback = cb; +} + static void mqtt_publish_request_cb(void *arg, err_t err) { #if 0 && MQTT_EXTRA_LOGS const struct mqtt_connect_client_info_t *client_info = (const struct mqtt_connect_client_info_t*)arg; @@ -275,8 +268,8 @@ static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t f McuLog_trace("bat%%: %s%%", buf); } #elif MQTT_CLIENT_IS_SENSOR - if (mqtt.in_pub_ID == Topic_ID_Sensor_Update) { - McuLog_trace("Sensor update"); + if (app_message_callback != NULL) { + app_message_callback(mqtt.in_pub_ID, data, len); #endif } else { McuLog_trace("mqtt_incoming_data_cb: Ignoring payload..."); @@ -381,7 +374,15 @@ static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection McuLog_error("failed subscribing, err %d", err); } #elif MQTT_CLIENT_IS_SENSOR - /* no subscriptions */ + err = mqtt_sub_unsub(client, + "///command/new_measure", + 1, /* quality of service */ + mqtt_request_cb, // Callback to call when subscribe/unsubscribe response is received + LWIP_CONST_CAST(void*, client_info), + 1); // 1 for subscribe, 0 for unsubscribe + if (err!=ERR_OK) { + McuLog_error("failed subscribing, err %d", err); + } #endif } else if (status==MQTT_CONNECT_DISCONNECTED) { McuLog_trace("MQTT connect disconnect"); diff --git a/pico-sensor/src/mqtt_client.h b/pico-sensor/src/mqtt_client.h index 4215f7c..b1bf130 100644 --- a/pico-sensor/src/mqtt_client.h +++ b/pico-sensor/src/mqtt_client.h @@ -70,6 +70,32 @@ void MqttClient_Deinit(void); */ void MqttClient_Init(void); +typedef enum topic_ID_e { + Topic_ID_None, +#if MQTT_CLIENT_IS_EV_CHARGER + Topic_ID_Solar_Power, /* power from PV panels */ + Topic_ID_Site_Power, /* power to the house/site */ + Topic_ID_Grid_Power, /* power from/to grid */ + Topic_ID_Battery_Power, /* power from/to battery */ + Topic_ID_Battery_Percentage,/* battery level percentage */ + Topic_ID_Charging_Power, /* actual charging power */ +#elif MQTT_CLIENT_IS_SENSOR + Topic_ID_Sensor_Update, +#endif +} topic_ID_e; + +/*! + * \brief Callback function for incoming messages + */ +typedef void (*MqttClient_MessageCallback_t)(topic_ID_e topic, const unsigned char *payload, size_t len); + +/*! + * \brief Register a callback function for incoming messages + * \param cb Callback function to be registered + */ +void MqttClient_RegisterMessageCallback(MqttClient_MessageCallback_t cb); + + #ifdef __cplusplus } /* extern "C" */ #endif From 4b40a1c142660486c0cc8709666b946cef8d4b23 Mon Sep 17 00:00:00 2001 From: SylvanArnold <89144178+SylvanArnold@users.noreply.github.com> Date: Tue, 20 May 2025 10:31:54 +0200 Subject: [PATCH 2/6] feat(pico-sensor): topic_send_measurement can be configured via serial commands and is saved in flash --- pico-sensor/src/MinIniKeys.h | 1 + pico-sensor/src/mqtt_client.c | 7 +++++-- pico-sensor/src/mqtt_client.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pico-sensor/src/MinIniKeys.h b/pico-sensor/src/MinIniKeys.h index 7f1ae88..27d5824 100644 --- a/pico-sensor/src/MinIniKeys.h +++ b/pico-sensor/src/MinIniKeys.h @@ -35,6 +35,7 @@ #define NVMC_MININI_KEY_MQTT_PASS "pass" /* string, password */ #define NVMC_MININI_KEY_MQTT_PUBLISH "publish" /* bool, if publishing */ #define NVMC_TOPIC_NAME_SENSORS_UPDATE "topic_sensor_update" /*///update*/ + #define NVMC_TOPIC_NAME_SEND_MEASUREMENT "topic_send_measurement" /*///cmd/measure*/ #endif #if PL_CONFIG_USE_NTP_CLIENT diff --git a/pico-sensor/src/mqtt_client.c b/pico-sensor/src/mqtt_client.c index c9856e4..caab7ef 100644 --- a/pico-sensor/src/mqtt_client.c +++ b/pico-sensor/src/mqtt_client.c @@ -45,7 +45,8 @@ #define MQTT_DEFAULT_USER "user" #define MQTT_DEFAULT_PASS "password" #define MQTT_DEFAULT_PUBLISH true -#define DEFAULT_TOPIC_NAME_SENSORS_UPDATE "user/room/device/update" /*///update*/ +#define DEFAULT_TOPIC_NAME_SENSORS_UPDATE "user/room/device/update" +#define DEFAULT_TOPIC_NAME_SEND_MEASUREMENT "user/room/device/command/new_measurement" typedef struct mqtt_t { mqtt_client_t *mqtt_client; /* lwIP MQTT client handle */ @@ -55,6 +56,7 @@ typedef struct mqtt_t { unsigned char client_user[32]; /* client user name used for connection */ unsigned char client_pass[96]; /* client user password */ unsigned char sensors_update_topic[64]; /* topic name for sensor updates */ + unsigned char send_measurement_topic[64]; /* topic name for sending measurement */ topic_ID_e in_pub_ID; /* incoming published ID, set in the incoming_publish_cb and used in the incoming_data_cb */ /* configuration settings */ bool doLogging; /* if it shall write log messages */ @@ -375,7 +377,7 @@ static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection } #elif MQTT_CLIENT_IS_SENSOR err = mqtt_sub_unsub(client, - "///command/new_measure", + mqtt.send_measurement_topic, /* topic: send measurement command */ 1, /* quality of service */ mqtt_request_cb, // Callback to call when subscribe/unsubscribe response is received LWIP_CONST_CAST(void*, client_info), @@ -407,6 +409,7 @@ uint8_t MqttClient_Connect(void) { McuMinINI_ini_gets(NVMC_MININI_SECTION_MQTT, NVMC_MININI_KEY_MQTT_USER, MQTT_DEFAULT_USER, mqtt.client_user, sizeof(mqtt.client_user), NVMC_MININI_FILE_NAME); McuMinINI_ini_gets(NVMC_MININI_SECTION_MQTT, NVMC_MININI_KEY_MQTT_PASS, MQTT_DEFAULT_PASS, mqtt.client_pass, sizeof(mqtt.client_pass), NVMC_MININI_FILE_NAME); McuMinINI_ini_gets(NVMC_MININI_SECTION_MQTT, NVMC_TOPIC_NAME_SENSORS_UPDATE, DEFAULT_TOPIC_NAME_SENSORS_UPDATE, mqtt.sensors_update_topic, sizeof(mqtt.sensors_update_topic), NVMC_MININI_FILE_NAME); + McuMinINI_ini_gets(NVMC_MININI_SECTION_MQTT, NVMC_TOPIC_NAME_SEND_MEASUREMENT, DEFAULT_TOPIC_NAME_SEND_MEASUREMENT, mqtt.send_measurement_topic, sizeof(mqtt.send_measurement_topic), NVMC_MININI_FILE_NAME); mqtt.doPublishing = McuMinINI_ini_getbool(NVMC_MININI_SECTION_MQTT, NVMC_MININI_KEY_MQTT_PASS, MQTT_DEFAULT_PUBLISH, NVMC_MININI_FILE_NAME); #else McuUtility_strcpy(mqtt.broker, sizeof(mqtt.broker), MQTT_DEFAULT_BROKER); diff --git a/pico-sensor/src/mqtt_client.h b/pico-sensor/src/mqtt_client.h index b1bf130..9386b3f 100644 --- a/pico-sensor/src/mqtt_client.h +++ b/pico-sensor/src/mqtt_client.h @@ -81,6 +81,7 @@ typedef enum topic_ID_e { Topic_ID_Charging_Power, /* actual charging power */ #elif MQTT_CLIENT_IS_SENSOR Topic_ID_Sensor_Update, + Topic_ID_Send_Measurement #endif } topic_ID_e; From f530efe9688f1b6f7ff524225066796093f731db Mon Sep 17 00:00:00 2001 From: SylvanArnold <89144178+SylvanArnold@users.noreply.github.com> Date: Tue, 20 May 2025 10:58:50 +0200 Subject: [PATCH 3/6] feat(pico-sensor): send sensor values on get-measurement mqtt messages --- pico-sensor/src/application.c | 7 ++++++- pico-sensor/src/mqtt_client.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pico-sensor/src/application.c b/pico-sensor/src/application.c index d118256..4e4a20e 100644 --- a/pico-sensor/src/application.c +++ b/pico-sensor/src/application.c @@ -132,12 +132,17 @@ static void MqttTask(void *pv) { McuLog_error("failed publishing sensor values"); } } - vTaskDelay(pdMS_TO_TICKS(1000)); + vTaskDelay(pdMS_TO_TICKS(10000)); } /* for */ } static void MyMqttMessageCallback(topic_ID_e topic, const unsigned char *payload, size_t len) { McuLog_info("MQTT message received, topic: %d, payload: %.*s", topic, (int)len, payload); + if (topic==Topic_ID_Send_Measurement) { + if (MqttClient_Publish_SensorValues(Sensor_GetTemperature(), Sensor_GetHumidity())!=ERR_OK) { + McuLog_error("failed publishing sensor values"); + } + } } #endif diff --git a/pico-sensor/src/mqtt_client.c b/pico-sensor/src/mqtt_client.c index caab7ef..ce035a8 100644 --- a/pico-sensor/src/mqtt_client.c +++ b/pico-sensor/src/mqtt_client.c @@ -301,6 +301,8 @@ static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len #elif MQTT_CLIENT_IS_SENSOR if (McuUtility_strcmp(topic, mqtt.sensors_update_topic)==0) { mqtt.in_pub_ID = Topic_ID_Sensor_Update; + } else if (McuUtility_strcmp(topic, mqtt.send_measurement_topic)==0) { + mqtt.in_pub_ID = Topic_ID_Send_Measurement; #endif } else { /* unknown */ McuLog_trace("MQTT client \"%s\" publish cb: topic %s, len %d", client_info->client_id, topic, (int)tot_len); From 177bcfec3104263020d6d5fc169ed1a3f04c5bfb Mon Sep 17 00:00:00 2001 From: SylvanArnold <89144178+SylvanArnold@users.noreply.github.com> Date: Tue, 20 May 2025 11:06:46 +0200 Subject: [PATCH 4/6] doc(pico-sensor): added new topic configuration instructions --- pico-sensor/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pico-sensor/README.md b/pico-sensor/README.md index 97d4770..4189716 100644 --- a/pico-sensor/README.md +++ b/pico-sensor/README.md @@ -21,9 +21,10 @@ McuMinINI write settings.ini MQTT user "USERNAME" McuMinINI write settings.ini MQTT pass "PASSWORD" ``` -Topic name: +Topic names: ```shell McuMinINI write settings.ini MQTT topic_sensor_update "///update" +McuMinINI write settings.ini MQTT topic_send_measurement "///cmd/measure" ``` ## Build From 82012604a07a4468d95b6107d0ed2fc53afa0a0d Mon Sep 17 00:00:00 2001 From: SylvanArnold <89144178+SylvanArnold@users.noreply.github.com> Date: Tue, 20 May 2025 12:18:23 +0200 Subject: [PATCH 5/6] fix(pico-sensor): changed default send measurement topic name --- pico-sensor/src/mqtt_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-sensor/src/mqtt_client.c b/pico-sensor/src/mqtt_client.c index ce035a8..6556e5a 100644 --- a/pico-sensor/src/mqtt_client.c +++ b/pico-sensor/src/mqtt_client.c @@ -46,7 +46,7 @@ #define MQTT_DEFAULT_PASS "password" #define MQTT_DEFAULT_PUBLISH true #define DEFAULT_TOPIC_NAME_SENSORS_UPDATE "user/room/device/update" -#define DEFAULT_TOPIC_NAME_SEND_MEASUREMENT "user/room/device/command/new_measurement" +#define DEFAULT_TOPIC_NAME_SEND_MEASUREMENT "user/room/device/cmd/measure" typedef struct mqtt_t { mqtt_client_t *mqtt_client; /* lwIP MQTT client handle */ From 764be2ced70d53191a01cba7b3dc8a8eb31602f3 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Thu, 22 May 2025 14:05:51 +0200 Subject: [PATCH 6/6] fix(gateway): update command topic path to use 'cmd' instead of 'command' Solve: #28 Signed-off-by: Klagarge --- gateway/src/PublishCommand.go | 4 ++-- gateway/src/docs/docs.go | 2 +- gateway/src/docs/swagger.json | 2 +- gateway/src/docs/swagger.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gateway/src/PublishCommand.go b/gateway/src/PublishCommand.go index 528ee20..f2d3d79 100644 --- a/gateway/src/PublishCommand.go +++ b/gateway/src/PublishCommand.go @@ -11,7 +11,7 @@ import ( // Command represents the structure of the command to be published // @Description Command structure for publishing type Command struct { - Command string `json:"command" example:"MEASURE_NEW" binding:"required"` + Command string `json:"command" example:"measure" binding:"required"` } // @Summary Publish command @@ -55,7 +55,7 @@ func (gh *Gateway) publishCommand(c *gin.Context) error { } // Publish the command to the MQTT broker - topic := user + "/" + room + "/" + device + "/command/" + json.Command + topic := user + "/" + room + "/" + device + "/cmd/" + json.Command token := gh.mqtt.Publish(topic, 1, false, "") if token.Wait() && token.Error() != nil { return token.Error() diff --git a/gateway/src/docs/docs.go b/gateway/src/docs/docs.go index 3b790f0..78f2084 100644 --- a/gateway/src/docs/docs.go +++ b/gateway/src/docs/docs.go @@ -184,7 +184,7 @@ const docTemplate = `{ "properties": { "command": { "type": "string", - "example": "MEASURE_NEW" + "example": "measure" } } } diff --git a/gateway/src/docs/swagger.json b/gateway/src/docs/swagger.json index 692c210..86a6c32 100644 --- a/gateway/src/docs/swagger.json +++ b/gateway/src/docs/swagger.json @@ -178,7 +178,7 @@ "properties": { "command": { "type": "string", - "example": "MEASURE_NEW" + "example": "measure" } } } diff --git a/gateway/src/docs/swagger.yaml b/gateway/src/docs/swagger.yaml index 8747a00..a703ded 100644 --- a/gateway/src/docs/swagger.yaml +++ b/gateway/src/docs/swagger.yaml @@ -7,7 +7,7 @@ definitions: description: Command structure for publishing properties: command: - example: MEASURE_NEW + example: measure type: string required: - command