第七天主要讲的内容是:项目完善与总结回顾。
要完善的业务逻辑:
1.MQTT连接服务器、订阅相关topic;
2.按键按下后发布topic;
3.处理订阅topic的消息,判断到是控制LED的则去控制LED亮灭;
实现功能分别有两种方案,分别是:
1.只有一个任务
2.有多个任务
两种方式的优缺点:
既然一个任务就可以实现所需要的功能,为何一定要使用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的完整的产品发布的一个流程
训练营导航:www.100ask.net