mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-18 16:56:34 +00:00
Add Windows client
This commit is contained in:
parent
027ffa983f
commit
a70eb1fd5f
75
hal/sdl2/app_hal.c
Normal file
75
hal/sdl2/app_hal.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <unistd.h>
|
||||
#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/
|
||||
#include <SDL2/SDL.h>
|
||||
#include "display/monitor.h"
|
||||
#include "indev/mouse.h"
|
||||
#include "indev/mousewheel.h"
|
||||
#include "indev/keyboard.h"
|
||||
|
||||
|
||||
/**
|
||||
* A task to measure the elapsed time for LittlevGL
|
||||
* @param data unused
|
||||
* @return never return
|
||||
*/
|
||||
static int tick_thread(void * data)
|
||||
{
|
||||
(void)data;
|
||||
|
||||
while(1) {
|
||||
SDL_Delay(5); /*Sleep for 5 millisecond*/
|
||||
lv_tick_inc(5); /*Tell LittelvGL that 5 milliseconds were elapsed*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hal_setup(void)
|
||||
{
|
||||
// Workaround for sdl2 `-m32` crash
|
||||
// https://bugs.launchpad.net/ubuntu/+source/libsdl2/+bug/1775067/comments/7
|
||||
#ifndef WIN32
|
||||
setenv("DBUS_FATAL_WARNINGS", "0", 1);
|
||||
#endif
|
||||
|
||||
/* Add a display
|
||||
* Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/
|
||||
monitor_init();
|
||||
/* Tick init.
|
||||
* You have to call 'lv_tick_inc()' in periodically to inform LittelvGL about how much time were elapsed
|
||||
* Create an SDL thread to do this*/
|
||||
SDL_CreateThread(tick_thread, "tick", NULL);
|
||||
|
||||
lv_init();
|
||||
static lv_disp_buf_t disp_buf;
|
||||
static lv_color_t buf[LV_HOR_RES_MAX * 10]; /*Declare a buffer for 10 lines*/
|
||||
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*/
|
||||
|
||||
lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
|
||||
disp_drv.flush_cb = monitor_flush; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
|
||||
disp_drv.buffer = &disp_buf;
|
||||
//disp_drv.disp_fill = monitor_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
|
||||
//disp_drv.disp_map = monitor_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
/* Add the mouse as input device
|
||||
* Use the 'mouse' driver which reads the PC's mouse*/
|
||||
mouse_init();
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = mouse_read; /*This function will be called periodically (by the library) to get the mouse position and state*/
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void hal_loop(void)
|
||||
{
|
||||
/*while(1)*/ {
|
||||
SDL_Delay(5);
|
||||
lv_task_handler();
|
||||
}
|
||||
}
|
17
hal/sdl2/app_hal.h
Normal file
17
hal/sdl2/app_hal.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void hal_setup(void);
|
||||
void hal_loop(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DRIVER_H*/
|
50
hal/stm32f407_btt/app_hal.c
Normal file
50
hal/stm32f407_btt/app_hal.c
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
//#include "stm32f429i_discovery.h"
|
||||
#include "tft.h"
|
||||
//#include "touchpad.h"
|
||||
|
||||
#ifdef USE_RTOS_SYSTICK
|
||||
#include <cmsis_os.h>
|
||||
#endif
|
||||
|
||||
void hal_setup(void)
|
||||
{
|
||||
pinMode(PD12, OUTPUT);
|
||||
digitalWrite(PD12, HIGH);
|
||||
|
||||
// HAL_Init();
|
||||
|
||||
// /* Configure the system clock to 180 MHz */
|
||||
// SystemClock_Config();
|
||||
|
||||
// /* Start up indication */
|
||||
// BSP_LED_Init(LED3);
|
||||
// for (uint8_t i = 0; i < 8; i++) { BSP_LED_Toggle(LED3); delay(50); }
|
||||
|
||||
tft_init();
|
||||
//touchpad_init();
|
||||
}
|
||||
|
||||
// void SysTick_Handler(void)
|
||||
// {
|
||||
// HAL_IncTick();
|
||||
// HAL_SYSTICK_IRQHandler();
|
||||
|
||||
// lv_tick_inc(1);
|
||||
|
||||
// #ifdef USE_RTOS_SYSTICK
|
||||
// osSystickHandler();
|
||||
// #endif
|
||||
// }
|
||||
|
||||
void hal_loop(void)
|
||||
{
|
||||
//while (1)
|
||||
{
|
||||
delay(5);
|
||||
lv_task_handler();
|
||||
}
|
||||
}
|
17
hal/stm32f407_btt/app_hal.h
Normal file
17
hal/stm32f407_btt/app_hal.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void hal_setup(void);
|
||||
void hal_loop(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DRIVER_H*/
|
65
hal/stm32f407_btt/tft.c
Normal file
65
hal/stm32f407_btt/tft.c
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file disp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <string.h>
|
||||
|
||||
#include "tft.h"
|
||||
#include "stm32f4xx.h"
|
||||
#include "fsmc_ssd1963.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_disp_drv_t disp_drv;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
/**
|
||||
* Initialize your display here
|
||||
*/
|
||||
void tft_init(void)
|
||||
{
|
||||
static lv_color_t disp_buf1[TFT_HOR_RES * 40];
|
||||
static lv_disp_buf_t buf;
|
||||
lv_disp_buf_init(&buf, disp_buf1, NULL, TFT_HOR_RES * 40);
|
||||
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
fsmc_ssd1963_init(0, false);
|
||||
|
||||
disp_drv.buffer = &buf;
|
||||
disp_drv.flush_cb = fsmc_ssd1963_flush;
|
||||
disp_drv.hor_res = TFT_HOR_RES;
|
||||
disp_drv.ver_res = TFT_VER_RES;
|
||||
#if TFT_USE_GPU != 0
|
||||
DMA2D_Config();
|
||||
disp_drv.gpu_blend_cb = gpu_mem_blend;
|
||||
disp_drv.gpu_fill_cb = gpu_mem_fill;
|
||||
#endif
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
37
hal/stm32f407_btt/tft.h
Normal file
37
hal/stm32f407_btt/tft.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file disp.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DISP_H
|
||||
#define DISP_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include "lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TFT_HOR_RES TFT_WIDTH
|
||||
#define TFT_VER_RES TFT_HEIGHT
|
||||
|
||||
#define TFT_EXT_FB 1 /*Frame buffer is located into an external SDRAM*/
|
||||
#define TFT_USE_GPU 0 /*Enable hardware accelerator*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void tft_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif
|
123
hal/stm32f429_disco/app_hal.c
Normal file
123
hal/stm32f429_disco/app_hal.c
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
#include "stm32f429i_discovery.h"
|
||||
#include "tft.h"
|
||||
#include "touchpad.h"
|
||||
|
||||
#ifdef USE_RTOS_SYSTICK
|
||||
#include <cmsis_os.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief System Clock Configuration
|
||||
* The system Clock is configured as follow :
|
||||
* System Clock source = PLL (HSE)
|
||||
* SYSCLK(Hz) = 180000000
|
||||
* HCLK(Hz) = 180000000
|
||||
* AHB Prescaler = 1
|
||||
* APB1 Prescaler = 4
|
||||
* APB2 Prescaler = 2
|
||||
* HSE Frequency(Hz) = 8000000
|
||||
* PLL_M = 8
|
||||
* PLL_N = 360
|
||||
* PLL_P = 2
|
||||
* PLL_Q = 7
|
||||
* VDD(V) = 3.3
|
||||
* Main regulator output voltage = Scale1 mode
|
||||
* Flash Latency(WS) = 5
|
||||
* The LTDC Clock is configured as follow :
|
||||
* PLLSAIN = 192
|
||||
* PLLSAIR = 4
|
||||
* PLLSAIDivR = 8
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void SystemClock_Config(void)
|
||||
{
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
|
||||
/* Enable Power Control clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
/* The voltage scaling allows optimizing the power consumption when the device is
|
||||
clocked below the maximum system frequency, to update the voltage scaling value
|
||||
regarding system frequency refer to product datasheet. */
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
|
||||
/*##-1- System Clock Configuration #########################################*/
|
||||
/* Enable HSE Oscillator and activate PLL with HSE as source */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 8;
|
||||
RCC_OscInitStruct.PLL.PLLN = 360;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||||
HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
|
||||
/* Activate the Over-Drive mode */
|
||||
HAL_PWREx_EnableOverDrive();
|
||||
|
||||
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
|
||||
clocks dividers */
|
||||
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
|
||||
|
||||
/*##-2- LTDC Clock Configuration ###########################################*/
|
||||
/* LCD clock configuration */
|
||||
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 MHz */
|
||||
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 MHz */
|
||||
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 MHz */
|
||||
/* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDIVR_8 = 48/8 = 6 MHz */
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
|
||||
PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
|
||||
PeriphClkInitStruct.PLLSAI.PLLSAIR = 4;
|
||||
PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;
|
||||
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
}
|
||||
|
||||
|
||||
void hal_setup(void)
|
||||
{
|
||||
HAL_Init();
|
||||
|
||||
/* Configure the system clock to 180 MHz */
|
||||
SystemClock_Config();
|
||||
|
||||
/* Start up indication */
|
||||
BSP_LED_Init(LED3);
|
||||
for (uint8_t i = 0; i < 8; i++) { BSP_LED_Toggle(LED3); HAL_Delay(50); }
|
||||
|
||||
tft_init();
|
||||
touchpad_init();
|
||||
}
|
||||
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
HAL_IncTick();
|
||||
HAL_SYSTICK_IRQHandler();
|
||||
|
||||
lv_tick_inc(1);
|
||||
|
||||
#ifdef USE_RTOS_SYSTICK
|
||||
osSystickHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void hal_loop(void)
|
||||
{
|
||||
while(1) {
|
||||
HAL_Delay(5);
|
||||
lv_task_handler();
|
||||
}
|
||||
}
|
17
hal/stm32f429_disco/app_hal.h
Normal file
17
hal/stm32f429_disco/app_hal.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void hal_setup(void);
|
||||
void hal_loop(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*DRIVER_H*/
|
236
hal/stm32f429_disco/tft.c
Normal file
236
hal/stm32f429_disco/tft.c
Normal file
@ -0,0 +1,236 @@
|
||||
/**
|
||||
* @file disp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <string.h>
|
||||
|
||||
#include "tft.h"
|
||||
#include "stm32f4xx.h"
|
||||
#include "stm32f429i_discovery_lcd.h"
|
||||
#include "ili9341.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define SDRAM_BANK_ADDR ((uint32_t)0xD0000000)
|
||||
|
||||
#define DMA_STREAM DMA2_Stream0
|
||||
#define DMA_CHANNEL DMA_CHANNEL_0
|
||||
#define DMA_STREAM_IRQ DMA2_Stream0_IRQn
|
||||
#define DMA_STREAM_IRQHANDLER DMA2_Stream0_IRQHandler
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void tft_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
extern LTDC_HandleTypeDef LtdcHandler;
|
||||
|
||||
#if TFT_USE_GPU != 0
|
||||
static DMA2D_HandleTypeDef Dma2dHandle;
|
||||
#endif
|
||||
|
||||
#if TFT_EXT_FB != 0
|
||||
static __IO uint16_t *my_fb = (__IO uint16_t *)(SDRAM_BANK_ADDR);
|
||||
#else
|
||||
static uint16_t my_fb[TFT_HOR_RES * TFT_VER_RES];
|
||||
#endif
|
||||
|
||||
/*DMA to flush to frame buffer*/
|
||||
static void DMA_Config(void);
|
||||
static void DMA_TransferComplete(DMA_HandleTypeDef *han);
|
||||
static void DMA_TransferError(DMA_HandleTypeDef *han);
|
||||
|
||||
DMA_HandleTypeDef DmaHandle;
|
||||
static lv_disp_drv_t disp_drv;
|
||||
static int32_t x1_flush;
|
||||
static int32_t y1_flush;
|
||||
static int32_t x2_flush;
|
||||
static int32_t y2_fill;
|
||||
static int32_t y_fill_act;
|
||||
static const lv_color_t *buf_to_flush;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
/**
|
||||
* Initialize your display here
|
||||
*/
|
||||
void tft_init(void)
|
||||
{
|
||||
static lv_color_t disp_buf1[TFT_HOR_RES * 40];
|
||||
static lv_disp_buf_t buf;
|
||||
lv_disp_buf_init(&buf, disp_buf1, NULL, TFT_HOR_RES * 40);
|
||||
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
|
||||
BSP_LCD_Init();
|
||||
BSP_LCD_LayerDefaultInit(0, (uint32_t)my_fb);
|
||||
HAL_LTDC_SetPixelFormat(&LtdcHandler, LTDC_PIXEL_FORMAT_RGB565, 0);
|
||||
DMA_Config();
|
||||
disp_drv.buffer = &buf;
|
||||
disp_drv.flush_cb = tft_flush;
|
||||
disp_drv.hor_res = TFT_HOR_RES;
|
||||
disp_drv.ver_res = TFT_VER_RES;
|
||||
#if TFT_USE_GPU != 0
|
||||
DMA2D_Config();
|
||||
disp_drv.gpu_blend_cb = gpu_mem_blend;
|
||||
disp_drv.gpu_fill_cb = gpu_mem_fill;
|
||||
#endif
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Flush a color buffer
|
||||
* @param x1 left coordinate of the rectangle
|
||||
* @param x2 right coordinate of the rectangle
|
||||
* @param y1 top coordinate of the rectangle
|
||||
* @param y2 bottom coordinate of the rectangle
|
||||
* @param color_p pointer to an array of colors
|
||||
*/
|
||||
static void tft_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p)
|
||||
{
|
||||
/*Return if the area is out the screen*/
|
||||
if (area->x2 < 0)
|
||||
return;
|
||||
if (area->y2 < 0)
|
||||
return;
|
||||
if (area->x1 > TFT_HOR_RES - 1)
|
||||
return;
|
||||
if (area->y1 > TFT_VER_RES - 1)
|
||||
return;
|
||||
|
||||
/*Truncate the area to the screen*/
|
||||
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
|
||||
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
|
||||
int32_t act_x2 = area->x2 > TFT_HOR_RES - 1 ? TFT_HOR_RES - 1 : area->x2;
|
||||
int32_t act_y2 = area->y2 > TFT_VER_RES - 1 ? TFT_VER_RES - 1 : area->y2;
|
||||
|
||||
x1_flush = act_x1;
|
||||
y1_flush = act_y1;
|
||||
x2_flush = act_x2;
|
||||
y2_fill = act_y2;
|
||||
y_fill_act = act_y1;
|
||||
buf_to_flush = color_p;
|
||||
|
||||
/*##-7- Start the DMA transfer using the interrupt mode #*/
|
||||
/* Configure the source, destination and buffer size DMA fields and Start DMA Stream transfer */
|
||||
/* Enable All the DMA interrupts */
|
||||
HAL_StatusTypeDef err;
|
||||
err = HAL_DMA_Start_IT(&DmaHandle, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * TFT_HOR_RES + x1_flush],
|
||||
(x2_flush - x1_flush + 1));
|
||||
if (err != HAL_OK)
|
||||
{
|
||||
while (1)
|
||||
; /*Halt on error*/
|
||||
}
|
||||
}
|
||||
|
||||
static void DMA_Config(void)
|
||||
{
|
||||
/*## -1- Enable DMA2 clock #################################################*/
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
|
||||
/*##-2- Select the DMA functional Parameters ###############################*/
|
||||
DmaHandle.Init.Channel = DMA_CHANNEL; /* DMA_CHANNEL_0 */
|
||||
DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY; /* M2M transfer mode */
|
||||
DmaHandle.Init.PeriphInc = DMA_PINC_ENABLE; /* Peripheral increment mode Enable */
|
||||
DmaHandle.Init.MemInc = DMA_MINC_ENABLE; /* Memory increment mode Enable */
|
||||
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* Peripheral data alignment : 16bit */
|
||||
DmaHandle.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; /* memory data alignment : 16bit */
|
||||
DmaHandle.Init.Mode = DMA_NORMAL; /* Normal DMA mode */
|
||||
DmaHandle.Init.Priority = DMA_PRIORITY_HIGH; /* priority level : high */
|
||||
DmaHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE; /* FIFO mode enabled */
|
||||
DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* FIFO threshold: 1/4 full */
|
||||
DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE; /* Memory burst */
|
||||
DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Peripheral burst */
|
||||
|
||||
/*##-3- Select the DMA instance to be used for the transfer : DMA2_Stream0 #*/
|
||||
DmaHandle.Instance = DMA_STREAM;
|
||||
|
||||
/*##-4- Initialize the DMA stream ##########################################*/
|
||||
if (HAL_DMA_Init(&DmaHandle) != HAL_OK)
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/*##-5- Select Callbacks functions called after Transfer complete and Transfer error */
|
||||
HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, DMA_TransferComplete);
|
||||
HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_ERROR_CB_ID, DMA_TransferError);
|
||||
|
||||
/*##-6- Configure NVIC for DMA transfer complete/error interrupts ##########*/
|
||||
HAL_NVIC_SetPriority(DMA_STREAM_IRQ, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA_STREAM_IRQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA conversion complete callback
|
||||
* @note This function is executed when the transfer complete interrupt
|
||||
* is generated
|
||||
* @retval None
|
||||
*/
|
||||
static void DMA_TransferComplete(DMA_HandleTypeDef *han)
|
||||
{
|
||||
y_fill_act++;
|
||||
|
||||
if (y_fill_act > y2_fill)
|
||||
{
|
||||
lv_disp_flush_ready(&disp_drv);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_to_flush += x2_flush - x1_flush + 1;
|
||||
/*##-7- Start the DMA transfer using the interrupt mode ####################*/
|
||||
/* Configure the source, destination and buffer size DMA fields and Start DMA Stream transfer */
|
||||
/* Enable All the DMA interrupts */
|
||||
if (HAL_DMA_Start_IT(han, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * TFT_HOR_RES + x1_flush],
|
||||
(x2_flush - x1_flush + 1)) != HAL_OK)
|
||||
{
|
||||
while (1)
|
||||
; /*Halt on error*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA conversion error callback
|
||||
* @note This function is executed when the transfer error interrupt
|
||||
* is generated during DMA transfer
|
||||
* @retval None
|
||||
*/
|
||||
static void DMA_TransferError(DMA_HandleTypeDef *han)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA Stream interrupt request.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void DMA_STREAM_IRQHANDLER(void)
|
||||
{
|
||||
/* Check the interrupt and clear flag */
|
||||
HAL_DMA_IRQHandler(&DmaHandle);
|
||||
}
|
37
hal/stm32f429_disco/tft.h
Normal file
37
hal/stm32f429_disco/tft.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file disp.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DISP_H
|
||||
#define DISP_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include "lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define TFT_HOR_RES 240
|
||||
#define TFT_VER_RES 320
|
||||
|
||||
#define TFT_EXT_FB 1 /*Frame buffer is located into an external SDRAM*/
|
||||
#define TFT_USE_GPU 0 /*Enable hardware accelerator*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void tft_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif
|
144
hal/stm32f429_disco/touchpad.c
Normal file
144
hal/stm32f429_disco/touchpad.c
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @file indev.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "tft.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
#include "stm32f429i_discovery.h"
|
||||
#include "stmpe811.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool touchpad_read(lv_indev_drv_t * drv, lv_indev_data_t *data);
|
||||
static bool touchpad_get_xy(int16_t *x, int16_t *y);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize your input devices here
|
||||
*/
|
||||
void touchpad_init(void)
|
||||
{
|
||||
stmpe811_Init(TS_I2C_ADDRESS);
|
||||
stmpe811_TS_Start(TS_I2C_ADDRESS);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.read_cb = touchpad_read;
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Read an input device
|
||||
* @param indev_id id of the input device to read
|
||||
* @param x put the x coordinate here
|
||||
* @param y put the y coordinate here
|
||||
* @return true: the device is pressed, false: released
|
||||
*/
|
||||
static bool touchpad_read(lv_indev_drv_t * drv, lv_indev_data_t *data)
|
||||
{
|
||||
static int16_t last_x = 0;
|
||||
static int16_t last_y = 0;
|
||||
|
||||
bool detected;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
detected = touchpad_get_xy(&x, &y);
|
||||
if(detected) {
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
last_x = data->point.x;
|
||||
last_y = data->point.y;
|
||||
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
} else {
|
||||
data->point.x = last_x;
|
||||
data->point.y = last_y;
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool touchpad_get_xy(int16_t *x, int16_t *y)
|
||||
{
|
||||
static int32_t _x = 0, _y = 0;
|
||||
int16_t xDiff, yDiff, xr, yr, x_raw, y_raw;;
|
||||
|
||||
bool detected;
|
||||
detected = stmpe811_TS_DetectTouch(TS_I2C_ADDRESS);
|
||||
|
||||
if(!detected) return false;
|
||||
|
||||
|
||||
stmpe811_TS_GetXY(TS_I2C_ADDRESS, &x_raw, &y_raw);
|
||||
|
||||
/* Y value first correction */
|
||||
y_raw -= 360;
|
||||
|
||||
/* Y value second correction */
|
||||
yr = y_raw / 11;
|
||||
|
||||
/* Return y_raw position value */
|
||||
if(yr <= 0) yr = 0;
|
||||
else if (yr > TFT_VER_RES) yr = TFT_VER_RES - 1;
|
||||
|
||||
y_raw = yr;
|
||||
|
||||
/* X value first correction */
|
||||
if(x_raw <= 3000) x_raw = 3870 - x_raw;
|
||||
else x_raw = 3800 - x_raw;
|
||||
|
||||
/* X value second correction */
|
||||
xr = x_raw / 15;
|
||||
|
||||
/* Return X position value */
|
||||
if(xr <= 0) xr = 0;
|
||||
else if (xr > TFT_HOR_RES) xr = TFT_HOR_RES - 1;
|
||||
|
||||
x_raw = xr;
|
||||
xDiff = x_raw > _x? (x_raw - _x): (_x - x_raw);
|
||||
yDiff = y_raw > _y? (y_raw - _y): (_y - y_raw);
|
||||
|
||||
if (xDiff + yDiff > 5) {
|
||||
_x = x_raw;
|
||||
_y = y_raw;
|
||||
}
|
||||
|
||||
/* Update the X and Y position */
|
||||
*x = _x;
|
||||
*y = _y;
|
||||
|
||||
return true;
|
||||
}
|
32
hal/stm32f429_disco/touchpad.h
Normal file
32
hal/stm32f429_disco/touchpad.h
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file indev.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INDEV_H
|
||||
#define INDEV_H
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void touchpad_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif
|
7
include/VersionInfo.h
Normal file
7
include/VersionInfo.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef VERSIONINFO_H
|
||||
#define VERSIONINFO_H
|
||||
|
||||
#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@"
|
||||
#define CLIENT_VERSION "@CLIENT_VERSION@"
|
||||
|
||||
#endif /* VERSIONINFO_H */
|
@ -1,6 +1,9 @@
|
||||
#ifndef HASP_CONF_H
|
||||
#define HASP_CONF_H
|
||||
|
||||
// language specific defines
|
||||
#include "lang/lang.h"
|
||||
|
||||
#define HASP_USE_APP 1
|
||||
|
||||
#ifndef HASP_USE_DEBUG
|
||||
@ -101,7 +104,12 @@
|
||||
#define HASP_OBJECT_NOTATION "p%ub%u"
|
||||
|
||||
/* Includes */
|
||||
#include <Arduino.h>
|
||||
#ifdef WINDOWS
|
||||
#include "winsock2.h"
|
||||
#include "Windows.h"
|
||||
#else
|
||||
#include "Arduino.h"
|
||||
#endif
|
||||
|
||||
#if HASP_USE_SPIFFS > 0
|
||||
// #if defined(ARDUINO_ARCH_ESP32)
|
||||
@ -132,7 +140,7 @@
|
||||
#endif
|
||||
|
||||
#if HASP_USE_WIFI > 0
|
||||
#include "net/hasp_wifi.h"
|
||||
#include "sys/net/hasp_wifi.h"
|
||||
|
||||
#if defined(STM32F4xx)
|
||||
#include "WiFiSpi.h"
|
||||
@ -173,11 +181,18 @@ static WiFiSpiClass WiFi;
|
||||
#endif
|
||||
|
||||
#if HASP_USE_MQTT > 0
|
||||
#include "svc/hasp_mqtt.h"
|
||||
#include "mqtt/hasp_mqtt.h"
|
||||
|
||||
#ifdef WINDOWS
|
||||
#define USE_PAHO
|
||||
#else
|
||||
#define USE_PUBSUBCLIENT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if HASP_USE_GPIO > 0
|
||||
#include "hasp_gpio.h"
|
||||
#include "sys/gpio/hasp_gpio.h"
|
||||
#endif
|
||||
|
||||
#if HASP_USE_HTTP > 0
|
||||
@ -215,4 +230,54 @@ static WiFiSpiClass WiFi;
|
||||
#define PGM_P const char *
|
||||
#endif
|
||||
|
||||
#ifndef __FlashStringHelper
|
||||
#define __FlashStringHelper char
|
||||
#endif
|
||||
|
||||
#ifndef FPSTR
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#endif
|
||||
|
||||
#ifndef PGM_P
|
||||
#define PGM_P const char *
|
||||
#endif
|
||||
|
||||
#ifndef F
|
||||
#define F(x) (x)
|
||||
#endif
|
||||
|
||||
#ifndef PSTR
|
||||
#define PSTR(x) x
|
||||
#endif
|
||||
|
||||
#ifndef PROGMEM
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <Windows.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#define snprintf_P snprintf
|
||||
#define memcpy_P memcpy
|
||||
#define strcasecmp_P strcmp // TODO: should be strcasecmp
|
||||
#define strcmp_P strcmp
|
||||
#define strstr_P strstr
|
||||
#define halRestartMcu()
|
||||
#define delay Sleep
|
||||
#define millis SDL_GetTicks
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define BIN 2
|
||||
|
||||
#define guiGetDim() 255
|
||||
#define guiSetDim(x)
|
||||
#define guiGetBacklight() 1
|
||||
#define guiSetBacklight(x)
|
||||
#define guiCalibrate()
|
||||
#endif
|
||||
|
||||
#endif // HASP_CONF_H
|
@ -1,65 +1,72 @@
|
||||
#ifndef HASP_MACRO_H
|
||||
#define HASP_MACRO_H
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_FATAL
|
||||
#define LOG_FATAL(...) \
|
||||
Log.fatal(__VA_ARGS__); \
|
||||
while(true) { \
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
#define LOG_OUTPUT(x, ...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_FATAL(...) \
|
||||
do { \
|
||||
} while(0)
|
||||
#define LOG_OUTPUT(...) Log.output(...)
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_FATAL
|
||||
#define LOG_FATAL(...) \
|
||||
Log.fatal(__VA_ARGS__); \
|
||||
while (true) \
|
||||
{ \
|
||||
}
|
||||
#else
|
||||
#define LOG_FATAL(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_ALERT
|
||||
#define LOG_ALERT(...) Log.alert(__VA_ARGS__)
|
||||
#define LOG_ALERT(...) Log.alert(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_ALERT(...)
|
||||
#define LOG_ALERT(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_CRITICAL
|
||||
#define LOG_CRITICAL(...) Log.critical(__VA_ARGS__)
|
||||
#define LOG_CRITICAL(...) Log.critical(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_CRITICAL(...)
|
||||
#define LOG_CRITICAL(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_ERROR
|
||||
#define LOG_ERROR(...) Log.error(__VA_ARGS__)
|
||||
#define LOG_ERROR(...) Log.error(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_ERROR(...)
|
||||
#define LOG_ERROR(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_WARNING
|
||||
#define LOG_WARNING(...) Log.warning(__VA_ARGS__)
|
||||
#define LOG_WARNING(...) Log.warning(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_WARNING(...)
|
||||
#define LOG_WARNING(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_INFO
|
||||
#define LOG_INFO(...) Log.notice(__VA_ARGS__)
|
||||
#define LOG_INFO(...) Log.notice(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_INFO(...)
|
||||
#define LOG_INFO(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_TRACE
|
||||
#define LOG_TRACE(...) Log.trace(__VA_ARGS__)
|
||||
#define LOG_TRACE(...) Log.trace(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_TRACE(...)
|
||||
#define LOG_TRACE(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_VERBOSE
|
||||
#define LOG_VERBOSE(...) Log.verbose(__VA_ARGS__)
|
||||
#define LOG_VERBOSE(...) Log.verbose(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_VERBOSE(...)
|
||||
#define LOG_VERBOSE(...)
|
||||
#endif
|
||||
|
||||
#if HASP_LOG_LEVEL > LOG_LEVEL_DEBUG
|
||||
#define LOG_DEBUG(...) Log.debug(__VA_ARGS__)
|
||||
#define LOG_DEBUG(...) Log.debug(__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_DEBUG(...)
|
||||
#define LOG_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#define LOG_OUTPUT(...) Log.output(...)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -26,6 +26,8 @@
|
||||
/* Maximal horizontal and vertical resolution to support by the library.*/
|
||||
#define LV_HOR_RES_MAX (TFT_WIDTH)
|
||||
#define LV_VER_RES_MAX (TFT_HEIGHT)
|
||||
#define LV_HOR_RES (TFT_WIDTH)
|
||||
#define LV_VER_RES (TFT_HEIGHT)
|
||||
|
||||
/* Color depth:
|
||||
* - 1: 1 byte per pixel
|
||||
@ -181,7 +183,7 @@ typedef void* lv_group_user_data_t;
|
||||
typedef void* lv_fs_drv_user_data_t;
|
||||
|
||||
/*File system interface*/
|
||||
#define LV_USE_FS_IF 1
|
||||
#define LV_USE_FS_IF 0
|
||||
#if LV_USE_FS_IF
|
||||
# define LV_FS_IF_FATFS '\0'
|
||||
#if defined(ARDUINO_ARCH_ESP32) // || defined(ARDUINO_ARCH_ESP8266)
|
||||
@ -251,12 +253,18 @@ typedef void* lv_img_decoder_user_data_t;
|
||||
|
||||
/* 1: use a custom tick source.
|
||||
* It removes the need to manually update the tick with `lv_tick_inc`) */
|
||||
#ifdef ARDUINO
|
||||
|
||||
#define LV_TICK_CUSTOM 1
|
||||
#if LV_TICK_CUSTOM == 1
|
||||
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the sys time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current systime in ms*/
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
#else
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#endif
|
||||
|
||||
typedef void* lv_disp_drv_user_data_t; /*Type of user data in the display driver*/
|
||||
typedef void* lv_indev_drv_user_data_t; /*Type of user data in the input device driver*/
|
||||
|
||||
@ -280,7 +288,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
|
||||
|
||||
/* 1: Print the log with 'printf';
|
||||
* 0: user need to register a callback with `lv_log_register_print_cb`*/
|
||||
# define LV_LOG_PRINTF 0
|
||||
# define LV_LOG_PRINTF 1
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*=================
|
||||
@ -431,7 +439,7 @@ typedef void* lv_font_user_data_t;
|
||||
/*Always enable at least on theme*/
|
||||
#define LV_USE_THEME_MATERIAL 1 /*A fast and impressive theme*/
|
||||
|
||||
#define LV_THEME_DEFAULT_INIT lv_theme_hasp_init // We init the theme ourselves
|
||||
#define LV_THEME_DEFAULT_INIT lv_theme_material_init // lv_theme_hasp_init // We init the theme ourselves
|
||||
#define LV_THEME_DEFAULT_COLOR_PRIMARY LV_COLOR_RED
|
||||
#define LV_THEME_DEFAULT_COLOR_SECONDARY LV_COLOR_BLUE
|
||||
#define LV_THEME_DEFAULT_FLAG 0 //LV_THEME_MATERIAL_FLAG_NONE
|
||||
|
135
platformio.ini
135
platformio.ini
@ -34,7 +34,6 @@ extra_default_envs =
|
||||
; Common environment settings
|
||||
;***************************************************
|
||||
[env]
|
||||
framework = arduino
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
|
||||
@ -49,21 +48,20 @@ build_flags =
|
||||
-D LV_CONF_INCLUDE_SIMPLE ; for lvgl
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE ; for lv_drivers
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE ; for components
|
||||
; -- littlevgl build options ------------------------------
|
||||
; -- ESP build options ------------------------------------
|
||||
-D SPIFFS_TEMPORAL_FD_CACHE ; speedup opening recent files
|
||||
; -- ArduinoJson build options ----------------------------
|
||||
-D ARDUINOJSON_DECODE_UNICODE=1 ; for utf-8 symbols
|
||||
-D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments
|
||||
;-D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments
|
||||
|
||||
; -- StreamUtils build options ----------------------------
|
||||
-D STREAMUTILS_ENABLE_EEPROM=1 ; for STM32, it also supports EEPROM
|
||||
|
||||
; -- Hasp build options ----------------------------
|
||||
-D HASP_VER_MAJ=0
|
||||
-D HASP_VER_MIN=3
|
||||
-D HASP_VER_REV=3
|
||||
-D HASP_VER_MIN=4
|
||||
-D HASP_VER_REV=0
|
||||
-D HASP_LOG_LEVEL=9
|
||||
-D HASP_USE_CONFIG=1 ; Native application, not library
|
||||
${override.build_flags}
|
||||
|
||||
; -- Shared library dependencies in all environments
|
||||
@ -93,6 +91,7 @@ extra_scripts = tools/copy_fw.py ; tools/pre:extra_script.py
|
||||
|
||||
; -- Platform specific build flags
|
||||
[esp32]
|
||||
framework = arduino
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D HTTP_UPLOAD_BUFLEN=1024 ; lower http upload buffer
|
||||
@ -108,6 +107,7 @@ build_flags =
|
||||
;-D HASP_USE_SPIFFS=1
|
||||
-D HASP_USE_LITTLEFS=1
|
||||
;-D HASP_USE_EEPROM=1
|
||||
-D HASP_USE_CONFIG=1 ; Native application, not library
|
||||
; -- LittleFS build options ------------------------
|
||||
-D CONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
|
||||
@ -146,6 +146,7 @@ hspi =
|
||||
-D TFT_SCLK=14
|
||||
|
||||
[esp8266]
|
||||
framework = arduino
|
||||
build_flags=
|
||||
-D HTTP_UPLOAD_BUFLEN=512 ; lower http upload buffer
|
||||
-D MQTT_MAX_PACKET_SIZE=1024 ; longer PubSubClient messages
|
||||
@ -163,6 +164,7 @@ build_flags=
|
||||
-D HASP_USE_LITTLEFS=1
|
||||
-D HASP_USE_EEPROM=1
|
||||
-D HASP_USE_ETHERNET=0
|
||||
-D HASP_USE_CONFIG=1 ; Native application, not library
|
||||
|
||||
lib_ignore =
|
||||
ESP32 BLE Arduino
|
||||
@ -174,6 +176,7 @@ lib_ignore =
|
||||
lib_deps =
|
||||
|
||||
[stm32f4]
|
||||
framework = arduino
|
||||
build_flags=
|
||||
-I include/stm32f4
|
||||
-D MQTT_MAX_PACKET_SIZE=2048 ; longer PubSubClient messages
|
||||
@ -187,6 +190,7 @@ build_flags=
|
||||
-D HASP_USE_SYSLOG=0 ; Needs UDP
|
||||
-D HASP_USE_SPIFFS=0
|
||||
-D HASP_USE_LITTLEFS=0
|
||||
-D HASP_USE_CONFIG=1 ; Native application, not library
|
||||
|
||||
lib_deps =
|
||||
; sstaub/Ticker @ ^3.2.0
|
||||
@ -219,3 +223,122 @@ lib_deps =
|
||||
; ;lv_drivers=https://github.com/littlevgl/lv_drivers/archive/master.zip
|
||||
; lv_drivers@^6.0.2
|
||||
;src_filter = +<*> +<../drivers/sdl2>
|
||||
|
||||
[env:emulator_64bits]
|
||||
platform = native@^1.1.3
|
||||
extra_scripts = tools/sdl2_build_extra.py
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
; ----- Monitor
|
||||
-D TFT_WIDTH=800
|
||||
-D TFT_HEIGHT=480
|
||||
; SDL drivers options
|
||||
;-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
;-D LV_DRV_NO_CONF
|
||||
-D USE_MONITOR
|
||||
-D MONITOR_ZOOM=1 ; 2
|
||||
-D USE_MOUSE
|
||||
-D USE_MOUSEWHEEL
|
||||
-D USE_KEYBOARD
|
||||
; ----- ArduinoJson
|
||||
-D ARDUINOJSON_DECODE_UNICODE=1
|
||||
-D HASP_NUM_PAGES=4
|
||||
-D HASP_USE_SPIFFS=0
|
||||
-D HASP_USE_LITTLEFS=0
|
||||
-D HASP_USE_EEPROM=0
|
||||
-D HASP_USE_GPIO=0
|
||||
-D HASP_USE_CONFIG=0 ; Standalone application, as library
|
||||
-D HASP_USE_DEBUG=1
|
||||
-D HASP_USE_MQTT=1
|
||||
-D MQTT_MAX_PACKET_SIZE=2048
|
||||
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_INFO
|
||||
;-D LV_LOG_PRINTF=1
|
||||
; Add recursive dirs for hal headers search
|
||||
!python -c "import os; print(' '.join(['-I {}'.format(i[0].replace('\x5C','/')) for i in os.walk('hal/sdl2')]))"
|
||||
-mconsole
|
||||
-lSDL2
|
||||
-D PAHO_MQTT_STATIC
|
||||
-D _WIN64
|
||||
-D WINDOWS ; We add this for code branching in hasp
|
||||
-D WIN32_LEAN_AND_MEAN
|
||||
-DPAHO_WITH_SSL=FALSE
|
||||
-DPAHO_BUILD_DOCUMENTATION=FALSE
|
||||
-DPAHO_BUILD_SAMPLES=FALSE
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_VERBOSE_MAKEFILE=TRUE
|
||||
;-D NO_PERSISTENCE
|
||||
-I.pio/libdeps/emulator_64bits/paho/src
|
||||
-I.pio/libdeps/emulator_64bits/ArduinoJson/src
|
||||
-I lib/ArduinoJson/src
|
||||
-I lib/lv_fs_if
|
||||
-l"ws2_32"
|
||||
-lrpcrt4
|
||||
-lcrypt32
|
||||
-lmingw32
|
||||
-lSDL2main
|
||||
-lSDL2
|
||||
-mwindows
|
||||
-lm
|
||||
-ldinput8
|
||||
-ldxguid
|
||||
-ldxerr8
|
||||
-luser32
|
||||
-lgdi32
|
||||
-lwinmm
|
||||
-limm32
|
||||
-lole32
|
||||
-loleaut32
|
||||
-lshell32
|
||||
-lversion
|
||||
-luuid
|
||||
-lsetupapi
|
||||
-lhid
|
||||
;-v
|
||||
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
lv_drivers@~7.9.0
|
||||
;lv_drivers=https://github.com/littlevgl/lv_drivers/archive/7d71907c1d6b02797d066f50984b866e080ebeed.zip
|
||||
https://github.com/eclipse/paho.mqtt.c.git
|
||||
bblanchon/ArduinoJson@^6.17.2 ; Json(l) parser
|
||||
|
||||
lib_ignore = paho
|
||||
|
||||
src_filter =
|
||||
+<*>
|
||||
-<*.h>
|
||||
+<../hal/sdl2>
|
||||
+<../.pio/libdeps/emulator_64bits/paho/src/*.c>
|
||||
-<../.pio/libdeps/emulator_64bits/paho/src/MQTTClient.c>
|
||||
-<../.pio/libdeps/emulator_64bits/paho/src/MQTTVersion.c>
|
||||
-<../.pio/libdeps/emulator_64bits/paho/src/SSLSocket.c>
|
||||
-<MQTTClient.c>
|
||||
-<MQTTVersion.c>
|
||||
-<SSLSocket.c>
|
||||
-<../.pio/libdeps/emulator_64bits/lv_fs_if/lv_fs_pc.c>
|
||||
-<../.pio/libdeps/emulator_64bits/ArduinoLog/ArduinoLog.cpp>
|
||||
-<sys>
|
||||
-<hal>
|
||||
-<drv>
|
||||
-<drv/touch>
|
||||
-<drv/tft>
|
||||
-<dev>
|
||||
-<hal>
|
||||
-<svc>
|
||||
-<hasp_filesystem.cpp>
|
||||
-<hasp_gui.cpp>
|
||||
-<hasp_gui.h>
|
||||
+<font>
|
||||
+<hasp>
|
||||
+<lang>
|
||||
-<log>
|
||||
+<mqtt>
|
||||
-<lib/ArduinoLog>
|
||||
-<lib/lv_fs_if>
|
||||
-<../lib/lv_fs_if>
|
||||
-<../lib/lv_fs_if/lv_fs_if.cpp>
|
||||
-<../lib/lv_fs_if/lv_fs_if.h>
|
||||
-<../lib/lv_fs_if/lv_fs_spiffs.cpp>
|
||||
-<../lib/lv_fs_if/lv_fs_spiffs.h>
|
||||
+<../.pio/libdeps/emulator_64bits/ArduinoJson/src/ArduinoJson.h>
|
||||
|
@ -1,18 +1,26 @@
|
||||
/* MIT License - Copyright (c) 2020 Francis Van Roie
|
||||
For full license information read the LICENSE file in the project folder */
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "hasp_conf.h" // load first
|
||||
|
||||
#include "hasp_debug.h"
|
||||
#include "hasp_config.h"
|
||||
#include "hasp_gui.h"
|
||||
#if HASP_USE_CONFIG > 0
|
||||
#include "hasp_debug.h"
|
||||
#endif
|
||||
|
||||
#if HASP_USE_CONFIG > 0
|
||||
#include "hasp_config.h"
|
||||
#include "hasp_gui.h"
|
||||
#endif
|
||||
|
||||
#include "hasp_oobe.h"
|
||||
|
||||
#include "hasp/hasp_dispatch.h"
|
||||
#include "hasp/hasp.h"
|
||||
|
||||
#include "net/hasp_network.h"
|
||||
#include "sys/net/hasp_network.h"
|
||||
|
||||
#include "dev/device.h"
|
||||
|
||||
@ -49,6 +57,7 @@ void setup()
|
||||
dispatchSetup();
|
||||
guiSetup();
|
||||
debugSetup(); // Init the console
|
||||
|
||||
#if HASP_USE_GPIO > 0
|
||||
gpioSetup();
|
||||
#endif
|
||||
@ -137,7 +146,7 @@ void loop()
|
||||
/* Timer Loop */
|
||||
if(millis() - mainLastLoopTime >= 1000) {
|
||||
/* Runs Every Second */
|
||||
haspEverySecond();
|
||||
haspEverySecond(); // sleep timer
|
||||
debugEverySecond(); // statusupdate
|
||||
|
||||
#if HASP_USE_OTA > 0
|
||||
@ -177,4 +186,6 @@ void loop()
|
||||
#else
|
||||
delay(6);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
120
src/main_windows.cpp
Normal file
120
src/main_windows.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/* MIT License - Copyright (c) 2020 Francis Van Roie
|
||||
For full license information read the LICENSE file in the project folder */
|
||||
|
||||
#ifdef WINDOWS
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "app_hal.h"
|
||||
|
||||
#include "hasp_conf.h"
|
||||
#include "hasp_debug.h"
|
||||
|
||||
#include "hasp/hasp_dispatch.h"
|
||||
#include "hasp/hasp.h"
|
||||
|
||||
#include "dev/device.h"
|
||||
#include "app_hal.h"
|
||||
|
||||
bool isConnected;
|
||||
uint8_t mainLoopCounter = 0;
|
||||
unsigned long mainLastLoopTime = 0;
|
||||
|
||||
void debugLvglLogEvent(lv_log_level_t level, const char * file, uint32_t line, const char * funcname,
|
||||
const char * descr)
|
||||
{
|
||||
printf("%s %d\n", file, line);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
fflush(stdout);
|
||||
lv_init();
|
||||
lv_log_register_print_cb(debugLvglLogEvent);
|
||||
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
fflush(stdout);
|
||||
hal_setup();
|
||||
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
haspDevice.pre_setup();
|
||||
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
dispatchSetup();
|
||||
// debugSetup(); // Init the console
|
||||
|
||||
#if HASP_USE_MQTT > 0
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
mqttSetup(); // Load Hostname before starting WiFi
|
||||
#endif
|
||||
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
haspSetup();
|
||||
mainLastLoopTime = millis() - 1000; // reset loop counter
|
||||
delay(250);
|
||||
|
||||
mqttStart();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
haspLoop();
|
||||
|
||||
// debugLoop(); // Console
|
||||
haspDevice.loop();
|
||||
|
||||
/* Timer Loop */
|
||||
if(millis() - mainLastLoopTime >= 1000) {
|
||||
/* Runs Every Second */
|
||||
haspEverySecond(); // sleep timer
|
||||
|
||||
#if HASP_USE_OTA > 0
|
||||
otaEverySecond(); // progressbar
|
||||
#endif
|
||||
|
||||
/* Runs Every 5 Seconds */
|
||||
if(mainLoopCounter == 0 || mainLoopCounter == 5) {
|
||||
|
||||
haspDevice.loop_5s();
|
||||
}
|
||||
|
||||
/* Reset loop counter every 10 seconds */
|
||||
if(mainLoopCounter >= 9) {
|
||||
mainLoopCounter = 0;
|
||||
} else {
|
||||
mainLoopCounter++;
|
||||
}
|
||||
mainLastLoopTime += 1000;
|
||||
}
|
||||
|
||||
delay(6);
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
int main(int argv, char ** args)
|
||||
{
|
||||
printf("%s %d\n", __FILE__, __LINE__);
|
||||
fflush(stdout);
|
||||
setup();
|
||||
std::cout << "HSetup OK\n";
|
||||
|
||||
while(1) {
|
||||
SDL_Delay(5);
|
||||
lv_task_handler();
|
||||
fflush(stdout);
|
||||
}
|
||||
std::cout << "Hloop OK\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
void loop()
|
||||
{
|
||||
delay(5);
|
||||
lv_task_handler();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -4,7 +4,11 @@
|
||||
#ifndef HASP_MQTT_H
|
||||
#define HASP_MQTT_H
|
||||
|
||||
#include "ArduinoJson.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hasp_conf.h"
|
||||
|
||||
#define __FlashStringHelper char
|
||||
|
||||
void mqttSetup();
|
||||
void mqttLoop();
|
||||
@ -22,6 +26,6 @@ bool mqttGetConfig(const JsonObject & settings);
|
||||
bool mqttSetConfig(const JsonObject & settings);
|
||||
#endif
|
||||
|
||||
String mqttGetNodename(void);
|
||||
//String mqttGetNodename(void);
|
||||
|
||||
#endif
|
@ -35,7 +35,7 @@ EthernetClient mqttNetworkClient;
|
||||
#endif
|
||||
|
||||
#include "hasp_hal.h"
|
||||
#include "hasp_debug.h"
|
||||
#include "log/hasp_debug.h"
|
||||
#include "hasp_config.h"
|
||||
|
||||
#include "../hasp/hasp_dispatch.h"
|
@ -3,7 +3,8 @@
|
||||
|
||||
#include "ArduinoJson.h"
|
||||
#include "hasp_conf.h"
|
||||
#if HASP_USE_MQTT > 0
|
||||
|
||||
#if 0 && HASP_USE_MQTT > 0
|
||||
|
||||
#include "PubSubClient.h"
|
||||
|
423
src/mqtt/hasp_mqtt_paho.cpp
Normal file
423
src/mqtt/hasp_mqtt_paho.cpp
Normal file
@ -0,0 +1,423 @@
|
||||
/* MIT License - Copyright (c) 2020 Francis Van Roie
|
||||
For full license information read the LICENSE file in the project folder */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hasp_conf.h"
|
||||
|
||||
#if HASP_USE_MQTT > 0
|
||||
#ifdef USE_PAHO
|
||||
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2020 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial contribution
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "MQTTAsync.h"
|
||||
|
||||
#include "hasp_mqtt.h" // functions to implement here
|
||||
|
||||
#include "hasp/hasp_dispatch.h" // for dispatch_topic_payload
|
||||
#include "hasp_debug.h" // for logging
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WRS_KERNEL)
|
||||
#include <OsWrapper.h>
|
||||
#endif
|
||||
|
||||
#define ADDRESS "10.4.0.5:1883"
|
||||
#define CLIENTID "ExampleClientSub"
|
||||
#define TOPIC "hasp/plate35/"
|
||||
#define QOS 1
|
||||
#define TIMEOUT 10000L
|
||||
|
||||
const char * mqttNodeTopic = TOPIC;
|
||||
const char * mqttGroupTopic = TOPIC;
|
||||
// char mqttNodeTopic[24];
|
||||
// char mqttGroupTopic[24];
|
||||
bool mqttEnabled = false;
|
||||
bool mqttHAautodiscover = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// These defaults may be overwritten with values saved by the web interface
|
||||
#ifndef MQTT_HOST
|
||||
#define MQTT_HOST "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PORT
|
||||
#define MQTT_PORT 1883;
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_USER
|
||||
#define MQTT_USER "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PASSW
|
||||
#define MQTT_PASSW "";
|
||||
#endif
|
||||
#ifndef MQTT_NODENAME
|
||||
#define MQTT_NODENAME "";
|
||||
#endif
|
||||
#ifndef MQTT_GROUPNAME
|
||||
#define MQTT_GROUPNAME "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PREFIX
|
||||
#define MQTT_PREFIX "hasp"
|
||||
#endif
|
||||
|
||||
#define LWT_TOPIC "LWT"
|
||||
|
||||
char mqttServer[16] = MQTT_HOST;
|
||||
char mqttUser[23] = MQTT_USER;
|
||||
char mqttPassword[32] = MQTT_PASSW;
|
||||
char mqttNodeName[16] = MQTT_NODENAME;
|
||||
char mqttGroupName[16] = MQTT_GROUPNAME;
|
||||
uint16_t mqttPort = MQTT_PORT;
|
||||
|
||||
MQTTAsync mqtt_client;
|
||||
|
||||
int disc_finished = 0;
|
||||
int subscribed = 0;
|
||||
int connected = 0;
|
||||
|
||||
static bool mqttPublish(const char * topic, const char * payload, size_t len, bool retain = false);
|
||||
|
||||
/* ===== Paho event callbacks ===== */
|
||||
|
||||
void connlost(void * context, char * cause)
|
||||
{
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||
int rc;
|
||||
connected = 0;
|
||||
|
||||
printf("\nConnection lost\n");
|
||||
if(cause) printf(" cause: %s\n", cause);
|
||||
|
||||
printf("Reconnecting\n");
|
||||
conn_opts.keepAliveInterval = 20;
|
||||
conn_opts.cleansession = 1;
|
||||
if((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to start connect, return code %d\n", rc);
|
||||
}
|
||||
}
|
||||
|
||||
// Receive incoming messages
|
||||
static void mqtt_message_cb(char * topic, char * payload, unsigned int length)
|
||||
{ // Handle incoming commands from MQTT
|
||||
if(length + 1 >= MQTT_MAX_PACKET_SIZE) {
|
||||
LOG_ERROR(TAG_MQTT_RCV, F("Payload too long (%d bytes)"), length);
|
||||
return;
|
||||
} else {
|
||||
payload[length] = '\0';
|
||||
}
|
||||
|
||||
LOG_TRACE(TAG_MQTT_RCV, F("%s = %s"), topic, (char *)payload);
|
||||
|
||||
if(topic == strstr(topic, mqttNodeTopic)) { // startsWith mqttNodeTopic
|
||||
|
||||
// Node topic
|
||||
topic += strlen(mqttNodeTopic); // shorten topic
|
||||
|
||||
} else if(topic == strstr(topic, mqttGroupTopic)) { // startsWith mqttGroupTopic
|
||||
|
||||
// Group topic
|
||||
topic += strlen(mqttGroupTopic); // shorten topic
|
||||
dispatch_topic_payload(topic, (const char *)payload);
|
||||
return;
|
||||
|
||||
} else if(topic == strstr_P(topic, PSTR("homeassistant/status"))) { // HA discovery topic
|
||||
if(mqttHAautodiscover && !strcasecmp_P((char *)payload, PSTR("online"))) {
|
||||
// dispatch_current_state();
|
||||
// mqtt_ha_register_auto_discovery();
|
||||
}
|
||||
return;
|
||||
|
||||
} else {
|
||||
// Other topic
|
||||
LOG_ERROR(TAG_MQTT, F(D_MQTT_INVALID_TOPIC));
|
||||
return;
|
||||
}
|
||||
|
||||
// catch a dangling LWT from a previous connection if it appears
|
||||
if(!strcmp_P(topic, PSTR(LWT_TOPIC))) { // endsWith LWT
|
||||
if(!strcasecmp_P((char *)payload, PSTR("offline"))) {
|
||||
{
|
||||
char msg[8];
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 8];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" LWT_TOPIC), mqttNodeTopic);
|
||||
snprintf_P(msg, sizeof(msg), PSTR("online"));
|
||||
|
||||
// /*bool res =*/mqttClient.publish(tmp_topic, msg, true);
|
||||
mqttPublish(tmp_topic, msg, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
// LOG_TRACE(TAG_MQTT, F("ignoring LWT = online"));
|
||||
}
|
||||
} else {
|
||||
dispatch_topic_payload(topic, (const char *)payload);
|
||||
}
|
||||
}
|
||||
|
||||
int msgarrvd(void * context, char * topicName, int topicLen, MQTTAsync_message * message)
|
||||
{
|
||||
printf("MQT RCV >> ");
|
||||
printf("%s => %.*s (%d)\n", topicName, message->payloadlen, (char *)message->payload, message->payloadlen);
|
||||
|
||||
char msg[message->payloadlen + 1];
|
||||
memcpy(msg, (char *)message->payload, message->payloadlen);
|
||||
msg[message->payloadlen] = '\0';
|
||||
|
||||
mqtt_message_cb(topicName, (char *)message->payload, message->payloadlen);
|
||||
|
||||
MQTTAsync_freeMessage(&message);
|
||||
MQTTAsync_free(topicName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void onDisconnectFailure(void * context, MQTTAsync_failureData * response)
|
||||
{
|
||||
printf("Disconnect failed, rc %d\n", response->code);
|
||||
disc_finished = 1;
|
||||
}
|
||||
|
||||
void onDisconnect(void * context, MQTTAsync_successData * response)
|
||||
{
|
||||
printf("Successful disconnection\n");
|
||||
disc_finished = 1;
|
||||
connected = 0;
|
||||
}
|
||||
|
||||
void onSubscribe(void * context, MQTTAsync_successData * response)
|
||||
{
|
||||
printf("Subscribe succeeded %d\n", response->token);
|
||||
subscribed = 1;
|
||||
}
|
||||
|
||||
void onSubscribeFailure(void * context, MQTTAsync_failureData * response)
|
||||
{
|
||||
printf("Subscribe failed, rc %d\n", response->code);
|
||||
}
|
||||
|
||||
void onConnectFailure(void * context, MQTTAsync_failureData * response)
|
||||
{
|
||||
connected = 0;
|
||||
printf("Connect failed, rc %d\n", response->code);
|
||||
}
|
||||
|
||||
void mqtt_subscribe(void * context, const char * topic)
|
||||
{
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||
int rc;
|
||||
|
||||
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n", topic, CLIENTID, QOS);
|
||||
opts.onSuccess = onSubscribe;
|
||||
opts.onFailure = onSubscribeFailure;
|
||||
opts.context = client;
|
||||
if((rc = MQTTAsync_subscribe(client, topic, QOS, &opts)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to start subscribe, return code %d\n", rc);
|
||||
}
|
||||
}
|
||||
|
||||
void onConnect(void * context, MQTTAsync_successData * response)
|
||||
{
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
connected = 1;
|
||||
|
||||
printf("Successful connection\n");
|
||||
|
||||
mqtt_subscribe(context, TOPIC "command/#");
|
||||
mqtt_subscribe(context, TOPIC "command");
|
||||
mqtt_subscribe(context, TOPIC "light");
|
||||
mqtt_subscribe(context, TOPIC "dim");
|
||||
|
||||
mqtt_send_object_state(0, 0, "connected");
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void onSendFailure(void * context, MQTTAsync_failureData * response)
|
||||
{
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
|
||||
int rc;
|
||||
|
||||
printf("Message send failed token %d error code %d\n", response->token, response->code);
|
||||
opts.onSuccess = onDisconnect;
|
||||
opts.onFailure = onDisconnectFailure;
|
||||
opts.context = client;
|
||||
if((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to start disconnect, return code %d\n", rc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void onSend(void * context, MQTTAsync_successData * response)
|
||||
{
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
|
||||
int rc;
|
||||
|
||||
printf("Message with token value %d delivery confirmed\n", response->token);
|
||||
// opts.onSuccess = onDisconnect;
|
||||
// opts.onFailure = onDisconnectFailure;
|
||||
// opts.context = client;
|
||||
// if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
|
||||
// {
|
||||
// printf("Failed to start disconnect, return code %d\n", rc);
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
}
|
||||
|
||||
/* ===== Local HASP MQTT functions ===== */
|
||||
|
||||
static bool mqttPublish(const char * topic, const char * payload, size_t len, bool retain)
|
||||
{
|
||||
if(mqttIsConnected()) {
|
||||
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||
int rc;
|
||||
|
||||
opts.onSuccess = onSend;
|
||||
opts.onFailure = onSendFailure;
|
||||
opts.context = mqtt_client;
|
||||
pubmsg.payload = (char *)payload;
|
||||
pubmsg.payloadlen = (int)strlen(payload);
|
||||
pubmsg.qos = QOS;
|
||||
pubmsg.retained = 0;
|
||||
if((rc = MQTTAsync_sendMessage(mqtt_client, topic, &pubmsg, &opts)) != MQTTASYNC_SUCCESS) {
|
||||
LOG_ERROR(TAG_MQTT_PUB, F(D_MQTT_FAILED " %s => %s"), topic, payload);
|
||||
} else {
|
||||
LOG_TRACE(TAG_MQTT_PUB, F("%s => %s"), topic, payload);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(TAG_MQTT, F(D_MQTT_NOT_CONNECTED));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ===== Public HASP MQTT functions ===== */
|
||||
|
||||
bool mqttIsConnected()
|
||||
{
|
||||
return connected == 1;
|
||||
}
|
||||
|
||||
void mqtt_send_state(const __FlashStringHelper * subtopic, const char * payload)
|
||||
{
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 20];
|
||||
printf(("%sstate/%s\n"), mqttNodeTopic, subtopic);
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), ("%sstate/%s"), mqttNodeTopic, subtopic);
|
||||
mqttPublish(tmp_topic, payload, false);
|
||||
}
|
||||
|
||||
void mqtt_send_object_state(uint8_t pageid, uint8_t btnid, char * payload)
|
||||
{
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 20];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%sstate/p%ub%u"), mqttNodeTopic, pageid, btnid);
|
||||
mqttPublish(tmp_topic, payload, false);
|
||||
}
|
||||
|
||||
void mqttStart()
|
||||
{
|
||||
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||
int rc;
|
||||
int ch;
|
||||
|
||||
if((rc = MQTTAsync_create(&mqtt_client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) !=
|
||||
MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to create client, return code %d\n", rc);
|
||||
rc = EXIT_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
if((rc = MQTTAsync_setCallbacks(mqtt_client, mqtt_client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to set callbacks, return code %d\n", rc);
|
||||
rc = EXIT_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
conn_opts.keepAliveInterval = 20;
|
||||
conn_opts.cleansession = 1;
|
||||
conn_opts.onSuccess = onConnect;
|
||||
conn_opts.onFailure = onConnectFailure;
|
||||
conn_opts.context = mqtt_client;
|
||||
if((rc = MQTTAsync_connect(mqtt_client, &conn_opts)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to start connect, return code %d\n", rc);
|
||||
rc = EXIT_FAILURE;
|
||||
// goto destroy_exit;
|
||||
} else {
|
||||
}
|
||||
|
||||
// while (!subscribed && !finished)
|
||||
// #if defined(_WIN32)
|
||||
// Sleep(100);
|
||||
// #else
|
||||
// usleep(10000L);
|
||||
// #endif
|
||||
|
||||
// if (finished)
|
||||
// goto exit;
|
||||
}
|
||||
|
||||
void mqttStop()
|
||||
{
|
||||
int rc;
|
||||
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
|
||||
disc_opts.onSuccess = onDisconnect;
|
||||
disc_opts.onFailure = onDisconnectFailure;
|
||||
if((rc = MQTTAsync_disconnect(mqtt_client, &disc_opts)) != MQTTASYNC_SUCCESS) {
|
||||
printf("Failed to start disconnect, return code %d\n", rc);
|
||||
rc = EXIT_FAILURE;
|
||||
// goto destroy_exit;
|
||||
}
|
||||
// while (!disc_finished)
|
||||
// {
|
||||
// #if defined(_WIN32)
|
||||
// Sleep(100);
|
||||
// #else
|
||||
// usleep(10000L);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// destroy_exit:
|
||||
// MQTTAsync_destroy(&client);
|
||||
// exit:
|
||||
// return rc;
|
||||
}
|
||||
|
||||
void mqttSetup(){};
|
||||
|
||||
void mqttLoop(){};
|
||||
|
||||
void mqttEvery5Seconds(bool wifiIsConnected){};
|
||||
|
||||
// String mqttGetNodename(void){return "palte35"};
|
||||
|
||||
#endif // USE_PAHO
|
||||
#endif // USE_MQTT
|
455
src/mqtt/hasp_mqtt_pubsubclient.cpp
Normal file
455
src/mqtt/hasp_mqtt_pubsubclient.cpp
Normal file
@ -0,0 +1,455 @@
|
||||
/* MIT License - Copyright (c) 2020 Francis Van Roie
|
||||
For full license information read the LICENSE file in the project folder */
|
||||
|
||||
#include "hasp_conf.h"
|
||||
|
||||
#if HASP_USE_MQTT > 0
|
||||
#ifdef USE_PUBSUBCLIENT
|
||||
|
||||
#include "PubSubClient.h"
|
||||
|
||||
#include "hasp/hasp.h"
|
||||
#include "hasp_mqtt.h"
|
||||
#include "hasp_mqtt_ha.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <WiFi.h>
|
||||
WiFiClient mqttNetworkClient;
|
||||
#elif defined(ARDUINO_ARCH_ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <EEPROM.h>
|
||||
#include <Esp.h>
|
||||
WiFiClient mqttNetworkClient;
|
||||
#else
|
||||
#if defined(STM32F4xx) && HASP_USE_WIFI > 0
|
||||
// #include <WiFi.h>
|
||||
WiFiSpiClient mqttNetworkClient;
|
||||
#else
|
||||
#if defined(W5500_MOSI) && defined(W5500_MISO) && defined(W5500_SCLK)
|
||||
#define W5500_LAN
|
||||
#include <Ethernet.h>
|
||||
#else
|
||||
#include <STM32Ethernet.h>
|
||||
#endif
|
||||
|
||||
EthernetClient mqttNetworkClient;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "hasp_hal.h"
|
||||
#include "log/hasp_debug.h"
|
||||
#include "hasp_config.h"
|
||||
|
||||
#include "../hasp/hasp_dispatch.h"
|
||||
|
||||
#ifdef USE_CONFIG_OVERRIDE
|
||||
#include "user_config_override.h"
|
||||
#endif
|
||||
|
||||
char mqttNodeTopic[24];
|
||||
char mqttGroupTopic[24];
|
||||
bool mqttEnabled = false;
|
||||
bool mqttHAautodiscover = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// These defaults may be overwritten with values saved by the web interface
|
||||
#ifndef MQTT_HOST
|
||||
#define MQTT_HOST "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PORT
|
||||
#define MQTT_PORT 1883;
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_USER
|
||||
#define MQTT_USER "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PASSW
|
||||
#define MQTT_PASSW "";
|
||||
#endif
|
||||
#ifndef MQTT_NODENAME
|
||||
#define MQTT_NODENAME "";
|
||||
#endif
|
||||
#ifndef MQTT_GROUPNAME
|
||||
#define MQTT_GROUPNAME "";
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_PREFIX
|
||||
#define MQTT_PREFIX "hasp"
|
||||
#endif
|
||||
|
||||
#define LWT_TOPIC "LWT"
|
||||
|
||||
char mqttServer[16] = MQTT_HOST;
|
||||
char mqttUser[23] = MQTT_USER;
|
||||
char mqttPassword[32] = MQTT_PASSW;
|
||||
char mqttNodeName[16] = MQTT_NODENAME;
|
||||
char mqttGroupName[16] = MQTT_GROUPNAME;
|
||||
uint16_t mqttPort = MQTT_PORT;
|
||||
PubSubClient mqttClient(mqttNetworkClient);
|
||||
|
||||
static bool mqttPublish(const char * topic, const char * payload, size_t len, bool retain = false)
|
||||
{
|
||||
if(mqttIsConnected()) {
|
||||
if(mqttClient.beginPublish(topic, len, retain)) {
|
||||
mqttClient.write((uint8_t *)payload, len);
|
||||
mqttClient.endPublish();
|
||||
|
||||
LOG_TRACE(TAG_MQTT_PUB, F("%s => %s"), topic, payload);
|
||||
return true;
|
||||
} else {
|
||||
LOG_ERROR(TAG_MQTT_PUB, F(D_MQTT_FAILED " %s => %s"), topic, payload);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(TAG_MQTT, F(D_MQTT_NOT_CONNECTED));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mqttPublish(const char * topic, const char * payload, bool retain = false)
|
||||
{
|
||||
return mqttPublish(topic, payload, strlen(payload), retain);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Send changed values OUT
|
||||
|
||||
bool mqttIsConnected()
|
||||
{
|
||||
return mqttEnabled && mqttClient.connected();
|
||||
}
|
||||
|
||||
void mqtt_send_lwt(bool online)
|
||||
{
|
||||
char tmp_payload[8];
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 4];
|
||||
strncpy(tmp_topic, mqttNodeTopic, sizeof(tmp_topic));
|
||||
strncat_P(tmp_topic, PSTR(LWT_TOPIC), sizeof(tmp_topic));
|
||||
// snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" LWT_TOPIC), mqttNodeTopic);
|
||||
|
||||
size_t len = snprintf_P(tmp_payload, sizeof(tmp_payload), online ? PSTR("online") : PSTR("offline"));
|
||||
bool res = mqttPublish(tmp_topic, tmp_payload, len, true);
|
||||
}
|
||||
|
||||
void mqtt_send_object_state(uint8_t pageid, uint8_t btnid, char * payload)
|
||||
{
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 16];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%sstate/" HASP_OBJECT_NOTATION), mqttNodeTopic, pageid, btnid);
|
||||
mqttPublish(tmp_topic, payload);
|
||||
}
|
||||
|
||||
void mqtt_send_state(const __FlashStringHelper * subtopic, const char * payload)
|
||||
{
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 20];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%sstate/%s"), mqttNodeTopic, subtopic);
|
||||
mqttPublish(tmp_topic, payload);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Receive incoming messages
|
||||
static void mqtt_message_cb(char * topic, byte * payload, unsigned int length)
|
||||
{ // Handle incoming commands from MQTT
|
||||
if(length + 1 >= mqttClient.getBufferSize()) {
|
||||
LOG_ERROR(TAG_MQTT_RCV, F("Payload too long (%d bytes)"), length);
|
||||
return;
|
||||
} else {
|
||||
payload[length] = '\0';
|
||||
}
|
||||
|
||||
LOG_TRACE(TAG_MQTT_RCV, F("%s = %s"), topic, (char *)payload);
|
||||
|
||||
if(topic == strstr(topic, mqttNodeTopic)) { // startsWith mqttNodeTopic
|
||||
|
||||
// Node topic
|
||||
topic += strlen(mqttNodeTopic); // shorten topic
|
||||
|
||||
} else if(topic == strstr(topic, mqttGroupTopic)) { // startsWith mqttGroupTopic
|
||||
|
||||
// Group topic
|
||||
topic += strlen(mqttGroupTopic); // shorten topic
|
||||
dispatch_topic_payload(topic, (const char *)payload);
|
||||
return;
|
||||
|
||||
} else if(topic == strstr_P(topic, PSTR("homeassistant/status"))) { // HA discovery topic
|
||||
if(mqttHAautodiscover && !strcasecmp_P((char *)payload, PSTR("online"))) {
|
||||
dispatch_current_state();
|
||||
mqtt_ha_register_auto_discovery();
|
||||
}
|
||||
return;
|
||||
|
||||
} else {
|
||||
// Other topic
|
||||
LOG_ERROR(TAG_MQTT, F(D_MQTT_INVALID_TOPIC));
|
||||
return;
|
||||
}
|
||||
|
||||
// catch a dangling LWT from a previous connection if it appears
|
||||
if(!strcmp_P(topic, PSTR(LWT_TOPIC))) { // endsWith LWT
|
||||
if(!strcasecmp_P((char *)payload, PSTR("offline"))) {
|
||||
{
|
||||
char msg[8];
|
||||
char tmp_topic[strlen(mqttNodeTopic) + 8];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" LWT_TOPIC), mqttNodeTopic);
|
||||
snprintf_P(msg, sizeof(msg), PSTR("online"));
|
||||
|
||||
// /*bool res =*/mqttClient.publish(tmp_topic, msg, true);
|
||||
mqttPublish(tmp_topic, msg, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
// LOG_TRACE(TAG_MQTT, F("ignoring LWT = online"));
|
||||
}
|
||||
} else {
|
||||
dispatch_topic_payload(topic, (const char *)payload);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqttSubscribeTo(const __FlashStringHelper * format, const char * data)
|
||||
{
|
||||
char tmp_topic[strlen_P((PGM_P)format) + 2 + strlen(data)];
|
||||
snprintf_P(tmp_topic, sizeof(tmp_topic), (PGM_P)format, data);
|
||||
if(mqttClient.subscribe(tmp_topic)) {
|
||||
LOG_VERBOSE(TAG_MQTT, F(D_BULLET D_MQTT_SUBSCRIBED), tmp_topic);
|
||||
} else {
|
||||
LOG_ERROR(TAG_MQTT, F(D_MQTT_NOT_SUBSCRIBED), tmp_topic);
|
||||
}
|
||||
}
|
||||
|
||||
void mqttStart()
|
||||
{
|
||||
char buffer[64];
|
||||
char mqttClientId[64];
|
||||
char lastWillPayload[8];
|
||||
static uint8_t mqttReconnectCount = 0;
|
||||
// bool mqttFirstConnect = true;
|
||||
|
||||
mqttClient.setServer(mqttServer, 1883);
|
||||
// mqttClient.setSocketTimeout(10); //in seconds
|
||||
|
||||
/* Construct unique Client ID*/
|
||||
{
|
||||
String mac = halGetMacAddress(3, "");
|
||||
mac.toLowerCase();
|
||||
memset(mqttClientId, 0, sizeof(mqttClientId));
|
||||
snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR(D_MQTT_DEFAULT_NAME), mac.c_str());
|
||||
LOG_INFO(TAG_MQTT, mqttClientId);
|
||||
}
|
||||
|
||||
// Attempt to connect and set LWT and Clean Session
|
||||
snprintf_P(buffer, sizeof(buffer), PSTR("%s" LWT_TOPIC), mqttNodeTopic); // lastWillTopic
|
||||
snprintf_P(lastWillPayload, sizeof(lastWillPayload), PSTR("offline")); // lastWillPayload
|
||||
|
||||
haspProgressMsg(F(D_MQTT_CONNECTING));
|
||||
haspProgressVal(mqttReconnectCount * 5);
|
||||
if(!mqttClient.connect(mqttClientId, mqttUser, mqttPassword, buffer, 0, true, lastWillPayload, true)) {
|
||||
// Retry until we give up and restart after connectTimeout seconds
|
||||
mqttReconnectCount++;
|
||||
|
||||
switch(mqttClient.state()) {
|
||||
case MQTT_CONNECTION_TIMEOUT:
|
||||
LOG_WARNING(TAG_MQTT, F("Connection timeout"));
|
||||
break;
|
||||
case MQTT_CONNECTION_LOST:
|
||||
LOG_WARNING(TAG_MQTT, F("Connection lost"));
|
||||
break;
|
||||
case MQTT_CONNECT_FAILED:
|
||||
LOG_WARNING(TAG_MQTT, F("Connection failed"));
|
||||
break;
|
||||
case MQTT_DISCONNECTED:
|
||||
snprintf_P(buffer, sizeof(buffer), PSTR(D_MQTT_DISCONNECTED));
|
||||
break;
|
||||
case MQTT_CONNECTED:
|
||||
break;
|
||||
case MQTT_CONNECT_BAD_PROTOCOL:
|
||||
LOG_WARNING(TAG_MQTT, F("MQTT version not suported"));
|
||||
break;
|
||||
case MQTT_CONNECT_BAD_CLIENT_ID:
|
||||
LOG_WARNING(TAG_MQTT, F("Client ID rejected"));
|
||||
break;
|
||||
case MQTT_CONNECT_UNAVAILABLE:
|
||||
LOG_WARNING(TAG_MQTT, F("Server unavailable"));
|
||||
break;
|
||||
case MQTT_CONNECT_BAD_CREDENTIALS:
|
||||
LOG_WARNING(TAG_MQTT, F("Bad credentials"));
|
||||
break;
|
||||
case MQTT_CONNECT_UNAUTHORIZED:
|
||||
LOG_WARNING(TAG_MQTT, F("Unauthorized"));
|
||||
break;
|
||||
default:
|
||||
LOG_WARNING(TAG_MQTT, F("Unknown failure"));
|
||||
}
|
||||
|
||||
if(mqttReconnectCount > 20) {
|
||||
LOG_ERROR(TAG_MQTT, F("Retry count exceeded, rebooting..."));
|
||||
dispatch_reboot(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(TAG_MQTT, F(D_MQTT_CONNECTED), mqttServer, mqttClientId);
|
||||
|
||||
// Subscribe to our incoming topics
|
||||
const __FlashStringHelper * F_topic;
|
||||
F_topic = F("%scommand/#");
|
||||
mqttSubscribeTo(F_topic, mqttGroupTopic);
|
||||
mqttSubscribeTo(F_topic, mqttNodeTopic);
|
||||
F_topic = F("%sconfig/#");
|
||||
mqttSubscribeTo(F_topic, mqttGroupTopic);
|
||||
mqttSubscribeTo(F_topic, mqttNodeTopic);
|
||||
mqttSubscribeTo(F("%slight/#"), mqttNodeTopic);
|
||||
mqttSubscribeTo(F("%sbrightness/#"), mqttNodeTopic);
|
||||
// mqttSubscribeTo(F("%s"LWT_TOPIC), mqttNodeTopic);
|
||||
mqttSubscribeTo(F("hass/status"), mqttClientId);
|
||||
|
||||
/* Home Assistant auto-configuration */
|
||||
if(mqttHAautodiscover) mqttSubscribeTo(F("homeassistant/status"), mqttClientId);
|
||||
|
||||
// Force any subscribed clients to toggle offline/online when we first connect to
|
||||
// make sure we get a full panel refresh at power on. Sending offline,
|
||||
// "online" will be sent by the mqttStatusTopic subscription action.
|
||||
mqtt_send_lwt(true);
|
||||
|
||||
// mqttFirstConnect = false;
|
||||
mqttReconnectCount = 0;
|
||||
|
||||
haspReconnect();
|
||||
haspProgressVal(255);
|
||||
|
||||
dispatch_current_state();
|
||||
}
|
||||
|
||||
void mqttSetup()
|
||||
{
|
||||
mqttEnabled = strlen(mqttServer) > 0 && mqttPort > 0;
|
||||
if(mqttEnabled) {
|
||||
mqttClient.setServer(mqttServer, mqttPort);
|
||||
mqttClient.setCallback(mqtt_message_cb);
|
||||
// if(!mqttClient.setBufferSize(1024)) {
|
||||
// LOG_ERROR(TAG_MQTT, F("Buffer allocation failed"));
|
||||
// } else {
|
||||
LOG_INFO(TAG_MQTT, F(D_MQTT_STARTED), mqttClient.getBufferSize());
|
||||
// }
|
||||
} else {
|
||||
LOG_WARNING(TAG_MQTT, F(D_MQTT_NOT_CONFIGURED));
|
||||
}
|
||||
}
|
||||
|
||||
void mqttLoop(void)
|
||||
{
|
||||
if(mqttEnabled) mqttClient.loop();
|
||||
}
|
||||
|
||||
void mqttEvery5Seconds(bool networkIsConnected)
|
||||
{
|
||||
if(mqttEnabled && networkIsConnected && !mqttClient.connected()) {
|
||||
LOG_TRACE(TAG_MQTT, F(D_MQTT_RECONNECTING));
|
||||
mqttStart();
|
||||
}
|
||||
}
|
||||
|
||||
String mqttGetNodename()
|
||||
{
|
||||
return mqttNodeName;
|
||||
}
|
||||
|
||||
void mqttStop()
|
||||
{
|
||||
if(mqttEnabled && mqttClient.connected()) {
|
||||
LOG_TRACE(TAG_MQTT, F(D_MQTT_DISCONNECTING));
|
||||
mqtt_send_lwt(false);
|
||||
mqttClient.disconnect();
|
||||
LOG_INFO(TAG_MQTT, F(D_MQTT_DISCONNECTED));
|
||||
}
|
||||
}
|
||||
|
||||
#if HASP_USE_CONFIG > 0
|
||||
bool mqttGetConfig(const JsonObject & settings)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if(strcmp(mqttNodeName, settings[FPSTR(FP_CONFIG_NAME)].as<String>().c_str()) != 0) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_NAME)] = mqttNodeName;
|
||||
|
||||
if(strcmp(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)].as<String>().c_str()) != 0) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_GROUP)] = mqttGroupName;
|
||||
|
||||
if(strcmp(mqttServer, settings[FPSTR(FP_CONFIG_HOST)].as<String>().c_str()) != 0) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_HOST)] = mqttServer;
|
||||
|
||||
if(mqttPort != settings[FPSTR(FP_CONFIG_PORT)].as<uint16_t>()) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_PORT)] = mqttPort;
|
||||
|
||||
if(strcmp(mqttUser, settings[FPSTR(FP_CONFIG_USER)].as<String>().c_str()) != 0) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_USER)] = mqttUser;
|
||||
|
||||
if(strcmp(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)].as<String>().c_str()) != 0) changed = true;
|
||||
settings[FPSTR(FP_CONFIG_PASS)] = mqttPassword;
|
||||
|
||||
if(changed) configOutput(settings, TAG_MQTT);
|
||||
return changed;
|
||||
}
|
||||
|
||||
/** Set MQTT Configuration.
|
||||
*
|
||||
* Read the settings from json and sets the application variables.
|
||||
*
|
||||
* @note: data pixel should be formated to uint32_t RGBA. Imagemagick requirements.
|
||||
*
|
||||
* @param[in] settings JsonObject with the config settings.
|
||||
**/
|
||||
bool mqttSetConfig(const JsonObject & settings)
|
||||
{
|
||||
configOutput(settings, TAG_MQTT);
|
||||
bool changed = false;
|
||||
|
||||
changed |= configSet(mqttPort, settings[FPSTR(FP_CONFIG_PORT)], F("mqttPort"));
|
||||
|
||||
if(!settings[FPSTR(FP_CONFIG_NAME)].isNull()) {
|
||||
changed |= strcmp(mqttNodeName, settings[FPSTR(FP_CONFIG_NAME)]) != 0;
|
||||
strncpy(mqttNodeName, settings[FPSTR(FP_CONFIG_NAME)], sizeof(mqttNodeName));
|
||||
}
|
||||
// Prefill node name
|
||||
if(strlen(mqttNodeName) == 0) {
|
||||
String mac = halGetMacAddress(3, "");
|
||||
mac.toLowerCase();
|
||||
snprintf_P(mqttNodeName, sizeof(mqttNodeName), PSTR(D_MQTT_DEFAULT_NAME), mac.c_str());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(!settings[FPSTR(FP_CONFIG_GROUP)].isNull()) {
|
||||
changed |= strcmp(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)]) != 0;
|
||||
strncpy(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)], sizeof(mqttGroupName));
|
||||
}
|
||||
|
||||
if(strlen(mqttGroupName) == 0) {
|
||||
strcpy_P(mqttGroupName, PSTR("plates"));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(!settings[FPSTR(FP_CONFIG_HOST)].isNull()) {
|
||||
changed |= strcmp(mqttServer, settings[FPSTR(FP_CONFIG_HOST)]) != 0;
|
||||
strncpy(mqttServer, settings[FPSTR(FP_CONFIG_HOST)], sizeof(mqttServer));
|
||||
}
|
||||
|
||||
if(!settings[FPSTR(FP_CONFIG_USER)].isNull()) {
|
||||
changed |= strcmp(mqttUser, settings[FPSTR(FP_CONFIG_USER)]) != 0;
|
||||
strncpy(mqttUser, settings[FPSTR(FP_CONFIG_USER)], sizeof(mqttUser));
|
||||
}
|
||||
|
||||
if(!settings[FPSTR(FP_CONFIG_PASS)].isNull() &&
|
||||
settings[FPSTR(FP_CONFIG_PASS)].as<String>() != String(FPSTR(D_PASSWORD_MASK))) {
|
||||
changed |= strcmp(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)]) != 0;
|
||||
strncpy(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)], sizeof(mqttPassword));
|
||||
}
|
||||
|
||||
snprintf_P(mqttNodeTopic, sizeof(mqttNodeTopic), PSTR(MQTT_PREFIX "/%s/"), mqttNodeName);
|
||||
snprintf_P(mqttGroupTopic, sizeof(mqttGroupTopic), PSTR(MQTT_PREFIX "/%s/"), mqttGroupName);
|
||||
|
||||
return changed;
|
||||
}
|
||||
#endif // HASP_USE_CONFIG
|
||||
|
||||
#endif // PUBSUBCLIENT
|
||||
|
||||
#endif // HASP_USE_MQTT
|
33
tools/sdl2_build_extra.py
Normal file
33
tools/sdl2_build_extra.py
Normal file
@ -0,0 +1,33 @@
|
||||
Import("env", "projenv")
|
||||
|
||||
for e in [ env, projenv ]:
|
||||
# If compiler uses `-m32`, propagate it to linker.
|
||||
# Add via script, because `-Wl,-m32` does not work.
|
||||
if "-m32" in e['CCFLAGS']:
|
||||
e.Append(LINKFLAGS = ["-m32"])
|
||||
|
||||
env.Append(
|
||||
LINKFLAGS=[
|
||||
"-static",
|
||||
"-static-libgcc",
|
||||
"-static-libstdc++"
|
||||
]
|
||||
)
|
||||
|
||||
# Override unused "upload" to execute compiled binary
|
||||
from SCons.Script import AlwaysBuild
|
||||
AlwaysBuild(env.Alias("build", "$BUILD_DIR/${PROGNAME}", "$BUILD_DIR/${PROGNAME}"))
|
||||
|
||||
# Add custom target to explorer
|
||||
env.AddTarget(
|
||||
name = "execute",
|
||||
dependencies = "$BUILD_DIR\${PROGNAME}.exe",
|
||||
actions = "$BUILD_DIR\${PROGNAME}.exe",
|
||||
# actions = 'cmd.exe /C "start cmd.exe /C $BUILD_DIR\${PROGNAME}.exe"',
|
||||
title = "Execute",
|
||||
description = "Build and execute",
|
||||
group="General"
|
||||
)
|
||||
|
||||
#print('=====================================')
|
||||
#print(env.Dump())
|
Loading…
x
Reference in New Issue
Block a user