【百问网】7天物联网智能家居实战 Day7

第七天主要讲的内容是:项目完善与总结回顾。

要完善的业务逻辑:

1.MQTT连接服务器、订阅相关topic;

2.按键按下后发布topic;

3.处理订阅topic的消息,判断到是控制LED的则去控制LED亮灭;

实现功能分别有两种方案,分别是:

1.只有一个任务

【百问网】7天物联网智能家居实战 Day7_第1张图片

2.有多个任务

【百问网】7天物联网智能家居实战 Day7_第2张图片

两种方式的优缺点:

 【百问网】7天物联网智能家居实战 Day7_第3张图片

 既然一个任务就可以实现所需要的功能,为何一定要使用RTOS?

原因有以下三点:

1.因为业务逻辑过于简单,因而才可以一个任务就可以完成;

2. 物联网应用中通常涉及多种传感器、多条数据流,使用RTOS能够更好的应对这些复杂应用;

3.Paho MQTT已经为我们实现了基于FreeRTOS的C库,节约开发时间。

基于一些FreeRTOS的接口函数,可以更好的优化之前的代码,优化后的代码如下:

1.MQTT Read的超时:

int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
	TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
	TimeOut_t xTimeOut;
	int recvLen = 0;

	vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
	do
	{
        if(n->netdev->Read(n->netdev, (char*)buffer, len, timeout_ms) == 0) recvLen = len;
	} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);

	return recvLen;
}

int Driver_Net_RecvSocket(char *buf, int len, int timeout)
{
    int tmp = 0;
    while(timeout != 0)
    {
        tmp += Driver_Buffer_ReadBytes(&NetDataBuffer, (uint8_t*)&buf[tmp], len);
        if(tmp == len)  return 0;
        timeout--;
        HAL_Delay(1);
    }
    return -1;
}

 2.MQTT write的超时:

int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
	TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
	TimeOut_t xTimeOut;
	int sentLen = 0;

	vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
	do
	{
        if(n->netdev->Write(n->netdev, (char*)buffer, len, timeout_ms) == 0) sentLen = len;
	} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);

	return sentLen;
}

int Driver_Net_TransmitSocket(const char *socket, int len, int timeout)
{
    uint8_t i = 0;
    char buf[64] = {0};
    char cmd[16] = {0};
    sprintf(cmd, "AT+CIPSEND=%d\r\n", len);
    HAL_UART_Transmit(&huart2, (uint8_t *)cmd, strlen(cmd), 500);
    HAL_Delay(1);
    Driver_Buffer_Clean(&CmdRetBuffer);
    HAL_UART_Transmit(&huart2, (uint8_t *)socket, len, 500);
    while(timeout != 0)
    {
        if(Driver_Buffer_Read(&CmdRetBuffer, (uint8_t*)&buf[i]) == 0)
        {
            i = (i+1)%64;
            if(strstr(buf, "SEND OK") != 0)
            {
                return 0;
            }
        }
        else
        {
            timeout--;
            HAL_Delay(1);
        }
    }
    return -1;
}

3.底层驱动函数的返回值应用与调试输出:

int Driver_Buffer_Init(ptRingBuffer buffer, uint16_t size)
{
    if(buffer == NULL || size == 0) return -1;
    
    if(buffer->fifo == NULL)
    {
        buffer->fifo = (uint8_t*)malloc(size);
        if(buffer->fifo == NULL)    
        {
            printf("Malloc %d bytes failed.\r\n", size);
            return -1;
        }
    }
    buffer->pw = buffer->pr = 0;
    buffer->buf_size = size;
    
    return 0;
}  

int Driver_Net_Init(void)
{
    if(Driver_Net_UART_Init() != 0)
        return -1;
    
    if(Driver_Buffer_Init(&CmdRetBuffer, 128) != 0) return -1;
    if(Driver_Buffer_Init(&NetDataBuffer, 1024) != 0) return -1;;
    
    Driver_Net_TransmitCmd("AT+RST", "OK\r\n", 10000);
    HAL_Delay(500);
    Driver_Net_TransmitCmd("AT+CWMODE_CUR=1", "OK\r\n", 500);
    
    return 0;
}

int Driver_Key_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    Driver_Buffer_Init(&KeyBuffer, sizeof(KeyEvent)<<4);
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    GPIO_InitStruct.Pin = KEY_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    
    HAL_GPIO_Init(KEY_PORT, &GPIO_InitStruct);
    
    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
    
    return 0;
}

至此,实现并改进了MQTT的完整的产品发布的一个流程

【百问网】7天物联网智能家居实战 Day7_第4张图片

 训练营导航:www.100ask.net

你可能感兴趣的:(stm32,单片机,arm)