Files
MSE-SoftwEng/pico-sensor/src/application.c

181 lines
4.4 KiB
C

/*
* Copyright (c) 2023-2024, Erich Styger
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "platform.h"
#if PL_CONFIG_USE_PICO_W
#include "pico/cyw43_arch.h"
#include "PicoWiFi.h"
#endif
#include "application.h"
#include "McuRTOS.h"
#include "McuLog.h"
#include "McuUtility.h"
#include "McuLED.h"
#include "leds.h"
#if PL_CONFIG_USE_BUTTONS && !PL_CONFIG_USE_BUTTONS_IRQ
#include "buttons.h"
#include "debounce.h"
#endif
#if PL_CONFIG_USE_OLED
#include "oled.h"
#endif
#if PL_CONFIG_USE_GCOV
#include "McuCoverage.h"
#endif
#if PL_CONFIG_USE_GPROF
#include "profile_test.h"
#endif
#include <stdio.h>
#if PL_CONFIG_USE_MQTT_CLIENT
#include "mqtt_client.h"
#include "sensor.h"
#endif
#if PL_CONFIG_USE_BUTTONS
void App_OnButtonEvent(BTN_Buttons_e button, McuDbnc_EventKinds kind) {
const char *p = NULL;
if (kind==MCUDBNC_EVENT_PRESSED) {
switch(button) {
case BTN_NAV_UP:
p = "up";
break;
case BTN_NAV_DOWN:
p = "down";
break;
case BTN_NAV_LEFT:
p = "left";
break;
case BTN_NAV_RIGHT:
p = "right";
break;
case BTN_NAV_CENTER:
p = "center";
break;
default:
p = NULL;
break;
}
if (p!=NULL) {
McuLog_info(p);
#if PL_CONFIG_USE_OLED
OLED_SendText(p);
#endif
}
}
}
#endif
static void AppTask(void *pv) {
uint32_t ms = 0;
volatile bool dumpCoverage = true;
#if PL_CONFIG_USE_PICO_W && PL_CONFIG_USE_LEDS
Leds_InitFromTask(); /* needed for the on-board Pico-W LED */
#endif
for(;;) {
#if PL_CONFIG_USE_BUTTONS && !PL_CONFIG_USE_BUTTONS_IRQ
/*! \TODO if enabled WiFi, it triggers GPIO button interrupts? Doing polling instead */
uint32_t buttons;
buttons = BTN_GetButtons();
if (buttons!=0) { /* poll buttons */
Debounce_StartDebounce(buttons);
}
vTaskDelay(pdMS_TO_TICKS(20));
ms += 20;
#else
vTaskDelay(pdMS_TO_TICKS(1000));
ms += 1000;
#endif
#if PL_CONFIG_USE_GCOV
if (dumpCoverage && ms>5*1000) {
vTaskEndScheduler(); /* exit scheduler to write coverage information */
}
#endif
#if PL_CONFIG_USE_GPROF
gprof_test();
if (ms>5*1000) {
vTaskEndScheduler();
}
#endif
}
}
#if PL_CONFIG_USE_MQTT_CLIENT
static TaskHandle_t mqttTaskHandle = NULL;
void App_MqttTaskResume(void) {
if (mqttTaskHandle!=NULL) {
vTaskResume(mqttTaskHandle);
}
}
void App_MqttTaskSuspend(void) {
if (mqttTaskHandle!=NULL) {
vTaskSuspend(mqttTaskHandle);
}
}
static void MqttTask(void *pv) {
for(;;) {
float t, h;
h = Sensor_GetHumidity();
t = Sensor_GetTemperature();
if (MqttClient_GetDoPublish()) {
if (MqttClient_Publish_SensorValues(t, h)!=ERR_OK) {
McuLog_error("failed publishing sensor values");
}
}
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
void App_Init(void) {
#if PL_CONFIG_USE_APP_TASK
if (xTaskCreate(
AppTask, /* pointer to the task */
"App", /* task name for kernel awareness debugging */
1500/sizeof(StackType_t), /* task stack size */
(void*)NULL, /* optional task startup argument */
tskIDLE_PRIORITY+2, /* initial priority */
(TaskHandle_t*)NULL /* optional task handle to create */
) != pdPASS)
{
McuLog_fatal("Failed creating task"); // GCOVR_EXCL_LINE
for(;;){} /* error! probably out of memory */ // GCOVR_EXCL_LINE
}
#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 */
1500/sizeof(StackType_t), /* task stack size */
(void*)NULL, /* optional task startup argument */
tskIDLE_PRIORITY+2, /* initial priority */
&mqttTaskHandle /* optional task handle to create */
) != pdPASS)
{
McuLog_fatal("Failed creating myqtt task");
for(;;){} /* error! probably out of memory */
}
#endif
}