void ICACHE_FLASH_ATTR mqtt_send_keepalive(MQTT_Client *client) { INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); err_t result = ESPCONN_OK; if (client->security) { #ifdef MQTT_SSL_ENABLE result = espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { result = espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } client->mqtt_state.outbound_message = NULL; if(ESPCONN_OK == result) { client->keepAliveTick = 0; client->connState = MQTT_DATA; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); } else { client->connState = TCP_RECONNECT_DISCONNECTING; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); } }
/** * @brief Tcp client connect success callback function. * @param arg: contain the ip link information * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_connect_cb(void *arg) { struct espconn *pCon = (struct espconn *)arg; MQTT_Client* client = (MQTT_Client *)pCon->reverse; espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);//////// espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);/////// INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if(client->security){ espconn_secure_sent(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } else{ espconn_sent(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } client->mqtt_state.outbound_message = NULL; client->connState = MQTT_CONNECT_SENDING; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); }
/** * @brief Tcp client connect success callback function. * @param arg: contain the ip link information * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_connect_cb(void *arg) { struct espconn *pCon = (struct espconn *)arg; MQTT_Client* client = (MQTT_Client *)pCon->reserve; espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);//////// espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);/////// INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if (client->security) { #ifdef MQTT_SSL_ENABLE espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } client->mqtt_state.outbound_message = NULL; client->connState = MQTT_CONNECT_SENDING; xSemaphoreGive(client->mqttTaskSem); }
void ICACHE_FLASH_ATTR mqtt_timer(void *arg) { MQTT_Client* client = (MQTT_Client*)arg; INFO("%s, %d\n", __func__, client->connState); if(client->connState == MQTT_DATA){ client->keepAliveTick ++; if(client->keepAliveTick > client->mqtt_state.connect_info->keepalive){ // check heart beat. if(client->heart_beat_flag == 0) { client->connState = TCP_RECONNECT_REQ; } INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if(client->security){ espconn_secure_sent(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } else{ espconn_sent(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); } client->mqtt_state.outbound_message = NULL; client->keepAliveTick = 0; client->heart_beat_flag = 0; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); } } else if(client->connState == TCP_RECONNECT_REQ){ INFO("%s, client->reconnectTick:%d\n", __func__, client->reconnectTick); client->reconnectTick ++; if(client->reconnectTick > MQTT_RECONNECT_TIMEOUT) { client->reconnectTick = 0; client->connState = TCP_RECONNECT; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); } }else if(client->connState == TCP_CONNECTING){ client->connectTick ++; if(client->connectTick > MQTT_CONNECT_TIMEOUT) { client->connState = TCP_CONNECTING_ERROR; client->connectTick = 0; system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); } } if(client->sendTimeout > 0) client->sendTimeout --; }
void FUNCTION_ATTRIBUTE mqtt_timer(void *arg) { MQTT_Client* client = (MQTT_Client*)arg; struct data_buf buffer; INFO("%s, %d\n", __func__, client->connState); if(client->connState == MQTT_DATA){ client->keepAliveTick ++; if(client->keepAliveTick > client->mqtt_state.connect_info->keepalive){ // check heart beat. if(client->heart_beat_flag == 0) { client->connState = TCP_RECONNECT_REQ; } INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; buffer.length = client->mqtt_state.outbound_message->length; buffer.data = client->mqtt_state.outbound_message->data; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); net_tcp_send(client->pCon, buffer, client->sendTimeout); client->mqtt_state.outbound_message = NULL; client->keepAliveTick = 0; client->heart_beat_flag = 0; MQTT_Task(client); } } else if(client->connState == TCP_RECONNECT_REQ){ INFO("%s, client->reconnectTick:%d\n", __func__, client->reconnectTick); client->reconnectTick ++; if(client->reconnectTick > MQTT_RECONNECT_TIMEOUT) { client->reconnectTick = 0; client->connState = TCP_RECONNECT; MQTT_Task(client); } }else if(client->connState == TCP_CONNECTING){ INFO("%s, client->connectTick:%d\n", __func__, client->connectTick); client->connectTick ++; if(client->connectTick > MQTT_CONNECT_TIMEOUT) { client->connState = TCP_CONNECTING_ERROR; client->connectTick = 0; MQTT_Task(client); } } if(client->sendTimeout > 0) client->sendTimeout --; }
/** * @brief Send out top message in queue onto socket */ static void ICACHE_FLASH_ATTR mqtt_send_message(MQTT_Client* client) { //DBG_MQTT("MQTT: Send_message\n"); PktBuf *buf = client->msgQueue; if (buf == NULL || client->sending) return; // ahem... client->msgQueue = PktBuf_Shift(client->msgQueue); // get some details about the message uint16_t msg_type = mqtt_get_type(buf->data); uint8_t msg_id = mqtt_get_id(buf->data, buf->filled); msg_id = msg_id; #ifdef MQTT_DBG os_printf("MQTT: Send type=%s id=%04X len=%d\n", mqtt_msg_type[msg_type], msg_id, buf->filled); #if 0 for (int i=0; i<buf->filled; i++) { if (buf->data[i] >= ' ' && buf->data[i] <= '~') os_printf("%c", buf->data[i]); else os_printf("\\x%02X", buf->data[i]); } os_printf("\n"); #endif #endif // send the message out if (client->security) espconn_secure_sent(client->pCon, buf->data, buf->filled); else espconn_sent(client->pCon, buf->data, buf->filled); client->sending = true; // depending on whether it needs an ack we need to hold on to the message bool needsAck = (msg_type == MQTT_MSG_TYPE_PUBLISH && mqtt_get_qos(buf->data) > 0) || msg_type == MQTT_MSG_TYPE_PUBREL || msg_type == MQTT_MSG_TYPE_PUBREC || msg_type == MQTT_MSG_TYPE_SUBSCRIBE || msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE || msg_type == MQTT_MSG_TYPE_PINGREQ; if (msg_type == MQTT_MSG_TYPE_PINGREQ) { client->pending_buffer = NULL; // we don't need to rexmit this one client->sending_buffer = buf; } else if (needsAck) { client->pending_buffer = buf; // remeber for rexmit on disconnect/reconnect client->sending_buffer = NULL; client->timeoutTick = client->sendTimeout+1; // +1 to ensure full sendTireout seconds } else { client->pending_buffer = NULL; client->sending_buffer = buf; client->timeoutTick = 0; } client->keepAliveTick = client->connect_info.keepalive > 0 ? client->connect_info.keepalive+1 : 0; }
void ICACHE_FLASH_ATTR MQTT_Task(os_event_t *e) { MQTT_Client* client = (MQTT_Client*)e->par; uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; if(e->par == 0) return; switch(client->connState){ case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DATA: if(QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if(QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0){ client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if(client->security){ espconn_secure_sent(client->pCon, dataBuffer, dataLen); } else{ espconn_sent(client->pCon, dataBuffer, dataLen); } client->mqtt_state.outbound_message = NULL; break; } break; case TCP_CONNECTING_ERROR: MQTT_Disconnect(client); MQTT_exit(client); break; } }
void FUNCTION_ATTRIBUTE MQTT_Task(MQTT_Client *client) { INFO("MQTT TASK: state: %d\n", client->connState); uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; struct data_buf buffer; if(client == NULL) return; switch(client->connState){ case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DATA: INFO("MQTT TASK DATA\n"); if(QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if(QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0){ INFO("%s, dataLen:%d\n", __func__, dataLen); client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; buffer.length = dataLen; buffer.data = dataBuffer; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); net_tcp_send(client->pCon, buffer, client->sendTimeout); client->mqtt_state.outbound_message = NULL; break; } break; case TCP_CONNECTING_ERROR: MQTT_Disconnect(client); MQTT_exit(client); break; } }
/** * @brief Tcp client connect success callback function. * @param arg: contain the ip link information * @retval None */ void FUNCTION_ATTRIBUTE mqtt_tcpclient_connect_cb(void *arg, int8_t errno) { struct pando_tcp_conn *pCon = (struct pando_tcp_conn *)arg; MQTT_Client* client = (MQTT_Client *)pCon->reverse; struct data_buf buffer; net_tcp_register_disconnected_callback(pCon, mqtt_tcpclient_discon_cb); net_tcp_register_recv_callback(pCon, mqtt_tcpclient_recv); net_tcp_register_sent_callback(pCon, mqtt_tcpclient_sent_cb); INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); client->sendTimeout = MQTT_SEND_TIMOUT; buffer.length = client->mqtt_state.outbound_message->length; buffer.data = client->mqtt_state.outbound_message->data; INFO("MQTT: Sending, type: %d, id: %04X\r\n",client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); net_tcp_send(pCon, buffer, client->sendTimeout); client->mqtt_state.outbound_message = NULL; client->connState = MQTT_CONNECT_SENDING; MQTT_Task(client); }
/** * @brief Client received callback function. * @param arg: contain the ip link information * @param pdata: received data * @param len: the lenght of received data * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) { INFO("TCP: data received %d bytes\r\n", len); uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; struct espconn *pCon = (struct espconn*)arg; MQTT_Client *client = (MQTT_Client *)pCon->reverse; if(len > MQTT_BUF_SIZE || len == 0) { INFO("receive length is invalid.\n"); return; } os_memcpy(client->mqtt_state.in_buffer + client->mqtt_state.message_length_read, pdata, len); client->mqtt_state.message_length_read += len; READPACKET: if(client->mqtt_state.message_length_read == 1) { INFO("not enough data for read package length.\n!"); return; } client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); INFO("message length:%d\n", client->mqtt_state.message_length); show_package(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); if(client->mqtt_state.message_length > client->mqtt_state.message_length_read) { INFO("not enough data.\n"); return; } msg_type = mqtt_get_type(client->mqtt_state.in_buffer); msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.message_length); INFO("client->connstate:%d, type:%d, Qos:%d, id:%d, message length:%d\n", client->connState, msg_type, msg_qos, \ msg_id, client->mqtt_state.message_length); switch(client->connState) { case MQTT_CONNECT_SENDING: if(msg_type == MQTT_MSG_TYPE_CONNACK) { if(client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT) { INFO("MQTT: Invalid packet\r\n"); if(client->security) { espconn_secure_disconnect(client->pCon); } else { espconn_disconnect(client->pCon); } } else { INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); client->connState = MQTT_DATA; if(client->connectedCb) client->connectedCb((uint32_t*)client); } } break; case MQTT_DATA: switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) INFO("MQTT: Subscribe successful\r\n"); break; case MQTT_MSG_TYPE_UNSUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) INFO("MQTT: UnSubscribe successful\r\n"); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); else if(msg_qos == 2) client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); if(msg_qos == 1 || msg_qos == 2) { INFO("MQTT: Queue response QoS: %d\r\n", msg_qos); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data,\ client->mqtt_state.outbound_message->length) == -1) { INFO("MQTT: Queue full\r\n"); } } show_package(client->mqtt_state.in_buffer, client->mqtt_state.message_length); deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length); break; case MQTT_MSG_TYPE_PUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n"); } break; case MQTT_MSG_TYPE_PUBREC: client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PUBREL: client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PUBCOMP: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n"); } break; case MQTT_MSG_TYPE_PINGREQ: client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PINGRESP: INFO("receive a heart beat response!\n"); client->heart_beat_flag = 1; break; } break; } // process package adhesive. uint16_t remain_length = client->mqtt_state.message_length_read - client->mqtt_state.message_length; client->mqtt_state.message_length_read = remain_length; INFO("client->mqtt_state.message_length_read = %d\n", client->mqtt_state.message_length_read); INFO("client->mqtt_state.message_length = %d\n", client->mqtt_state.message_length); INFO("the package is\n"); show_package(client->mqtt_state.in_buffer, client->mqtt_state.message_length); if(remain_length > 0) { int i = 0; for(i = 0; i< remain_length; i++) { client->mqtt_state.in_buffer[i] = \ client->mqtt_state.in_buffer[client->mqtt_state.message_length_read - remain_length + i]; } INFO("Get another published message\r\n"); goto READPACKET; } system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); }
/** * @brief Client received callback function. * @param arg: contain the ip link information * @param pdata: received data * @param len: the lenght of received data * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) { uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; struct espconn *pCon = (struct espconn*)arg; MQTT_Client *client = (MQTT_Client *)pCon->reverse; READPACKET: INFO("TCP: data received %d bytes\r\n", len); if(len < MQTT_BUF_SIZE && len > 0){ os_memcpy(client->mqtt_state.in_buffer, pdata, len); msg_type = mqtt_get_type(client->mqtt_state.in_buffer); msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); switch(client->connState){ case MQTT_CONNECT_SENDING: if(msg_type == MQTT_MSG_TYPE_CONNACK){ if(client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT){ INFO("MQTT: Invalid packet\r\n"); if(client->security){ espconn_secure_disconnect(client->pCon); } else { espconn_disconnect(client->pCon); } } else { INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); client->connState = MQTT_DATA; if(client->connectedCb) client->connectedCb((uint32_t*)client); } } break; case MQTT_DATA: client->mqtt_state.message_length_read = len; client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) INFO("MQTT: Subscribe successful\r\n"); break; case MQTT_MSG_TYPE_UNSUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) INFO("MQTT: UnSubscribe successful\r\n"); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); else if(msg_qos == 2) client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); if(msg_qos == 1 || msg_qos == 2){ INFO("MQTT: Queue response QoS: %d\r\n", msg_qos); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1){ INFO("MQTT: Queue full\r\n"); } } deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n"); } break; case MQTT_MSG_TYPE_PUBREC: client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1){ INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PUBREL: client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1){ INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PUBCOMP: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n"); } break; case MQTT_MSG_TYPE_PINGREQ: client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); if(QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1){ INFO("MQTT: Queue full\r\n"); } break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { len = client->mqtt_state.message_length_read; if(client->mqtt_state.message_length < client->mqtt_state.message_length_read) { //client->connState = MQTT_PUBLISH_RECV; //Not Implement yet len -= client->mqtt_state.message_length; pdata += client->mqtt_state.message_length; INFO("Get another published message\r\n"); goto READPACKET; } } break; } } else { INFO("ERROR: Message too long\r\n"); } system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); }
/** * @brief Client received callback function. * @param arg: contain the ip link information * @param pdata: received data * @param len: the lenght of received data * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) { uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; struct espconn *pCon = (struct espconn*)arg; MQTT_Client *client = (MQTT_Client *)pCon->reverse; //spam INFO("TCP: data received\r\n"); if(len < MQTT_BUF_SIZE && len > 0){ memcpy(client->mqtt_state.in_buffer, pdata, len); switch(client->connState){ case MQTT_CONNECT_SENDING: if(mqtt_get_type(client->mqtt_state.in_buffer) != MQTT_MSG_TYPE_CONNACK){ //spam INFO("MQTT: Invalid packet\r\n"); if(client->security){ espconn_secure_disconnect(client->pCon); } else { espconn_disconnect(client->pCon); } } else { //spam INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); client->connState = MQTT_DATA; if(client->connectedCb) client->connectedCb((uint32_t*)client); } break; case MQTT_DATA: client->mqtt_state.message_length_read = len; client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); msg_type = mqtt_get_type(client->mqtt_state.in_buffer); msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: //spam if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) //spam INFO("MQTT: Subscribe successful to %s:%d\r\n", client->host, client->port); break; case MQTT_MSG_TYPE_UNSUBACK: //spam if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) //spam INFO("MQTT: UnSubscribe successful\r\n"); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); else if(msg_qos == 2) client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ //spam INFO("MQTT: Publish successful\r\n"); if(client->publishedCb) client->publishedCb((uint32_t*)client); } break; case MQTT_MSG_TYPE_PUBREC: client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBREL: client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBCOMP: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ //spam INFO("MQTT: Public successful\r\n"); if(client->publishedCb) client->publishedCb((uint32_t*)client); } break; case MQTT_MSG_TYPE_PINGREQ: client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { uint16_t len; // adjust message_length and message_length_read so that // they only account for the publish data and not the rest of the // message, this is done so that the offset passed with the // continuation event is the offset within the publish data and // not the offset within the message as a whole. len = client->mqtt_state.message_length_read; mqtt_get_publish_data(client->mqtt_state.in_buffer, &len); len = client->mqtt_state.message_length_read - len; client->mqtt_state.message_length -= len; client->mqtt_state.message_length_read -= len; if(client->mqtt_state.message_length_read < client->mqtt_state.message_length) { //client->connState = MQTT_PUBLISH_RECV; } } break; case MQTT_PUBLISH_RECV: /* * Long publish message, not implement yet * TODO: Implement method used deliver_publish_continuation */ break; } } system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); }
void ICACHE_FLASH_ATTR MQTT_Task(os_event_t *e) { MQTT_Client* client = (MQTT_Client*)e->par; uint8_t dataBuffer[MQTT_BUF_SIZE]; uint16_t dataLen; if (e->par == 0) return; switch (client->connState) { case TCP_RECONNECT_REQ: break; case TCP_RECONNECT: mqtt_tcpclient_delete(client); MQTT_Connect(client); INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); client->connState = TCP_CONNECTING; break; case MQTT_DELETING: case TCP_DISCONNECTING: case TCP_RECONNECT_DISCONNECTING: if (client->security) { #ifdef MQTT_SSL_ENABLE espconn_secure_disconnect(client->pCon); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { espconn_disconnect(client->pCon); } break; case TCP_DISCONNECTED: INFO("MQTT: Disconnected\r\n"); mqtt_tcpclient_delete(client); break; case MQTT_DELETED: INFO("MQTT: Deleted client\r\n"); mqtt_client_delete(client); break; case MQTT_KEEPALIVE_SEND: mqtt_send_keepalive(client); break; case MQTT_DATA: if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { break; } if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) { client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); client->sendTimeout = MQTT_SEND_TIMOUT; INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); if (client->security) { #ifdef MQTT_SSL_ENABLE espconn_secure_send(client->pCon, dataBuffer, dataLen); #else INFO("TCP: Do not support SSL\r\n"); #endif } else { espconn_send(client->pCon, dataBuffer, dataLen); } client->mqtt_state.outbound_message = NULL; break; } break; } }
static PT_THREAD(handle_mqtt_connection(mqtt_state_t* state)) { static struct etimer keepalive_timer; uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; PSOCK_BEGIN(&state->ps); // Initialise and send CONNECT message mqtt_msg_init(&state->mqtt_connection, state->out_buffer, state->out_buffer_length); state->outbound_message = mqtt_msg_connect(&state->mqtt_connection, state->connect_info); PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // Wait for CONACK message PSOCK_READBUF_LEN(&state->ps, 2); if(mqtt_get_type(state->in_buffer) != MQTT_MSG_TYPE_CONNACK) PSOCK_CLOSE_EXIT(&state->ps); // Tell the client we're connected mqtt_flags |= MQTT_FLAG_CONNECTED; complete_pending(state, MQTT_EVENT_TYPE_CONNECTED); // Setup the keep alive timer and enter main message processing loop etimer_set(&keepalive_timer, CLOCK_SECOND * state->connect_info->keepalive); while(1) { // Wait for something to happen: // new incoming data, // new outgoing data, // keep alive timer expired PSOCK_WAIT_UNTIL(&state->ps, PSOCK_NEWDATA(&state->ps) || state->outbound_message != NULL || etimer_expired(&keepalive_timer)); // If there's a new message waiting to go out, then send it if(state->outbound_message != NULL) { PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // If it was a PUBLISH message with QoS-0 then tell the client it's done if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == 0) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); // Reset the keepalive timer as we've just sent some data etimer_restart(&keepalive_timer); continue; } // If the keep-alive timer expired then prepare a ping for sending // and reset the timer if(etimer_expired(&keepalive_timer)) { state->outbound_message = mqtt_msg_pingreq(&state->mqtt_connection); etimer_reset(&keepalive_timer); continue; } // If we get here we must have woken for new incoming data, // read and process it. PSOCK_READBUF_LEN(&state->ps, 2); state->message_length_read = PSOCK_DATALEN(&state->ps); state->message_length = mqtt_get_total_length(state->in_buffer, state->message_length_read); msg_type = mqtt_get_type(state->in_buffer); msg_qos = mqtt_get_qos(state->in_buffer); msg_id = mqtt_get_id(state->in_buffer, state->in_buffer_length); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_SUBSCRIBED); break; case MQTT_MSG_TYPE_UNSUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_UNSUBSCRIBED); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) state->outbound_message = mqtt_msg_puback(&state->mqtt_connection, msg_id); else if(msg_qos == 2) state->outbound_message = mqtt_msg_pubrec(&state->mqtt_connection, msg_id); deliver_publish(state, state->in_buffer, state->message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PUBREC: state->outbound_message = mqtt_msg_pubrel(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBREL: state->outbound_message = mqtt_msg_pubcomp(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBCOMP: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PINGREQ: state->outbound_message = mqtt_msg_pingresp(&state->mqtt_connection); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { uint16_t len; // adjust message_length and message_length_read so that // they only account for the publish data and not the rest of the // message, this is done so that the offset passed with the // continuation event is the offset within the publish data and // not the offset within the message as a whole. len = state->message_length_read; mqtt_get_publish_data(state->in_buffer, &len); len = state->message_length_read - len; state->message_length -= len; state->message_length_read -= len; while(state->message_length_read < state->message_length) { PSOCK_READBUF_LEN(&state->ps, state->message_length - state->message_length_read); deliver_publish_continuation(state, state->message_length_read, state->in_buffer, PSOCK_DATALEN(&state->ps)); state->message_length_read += PSOCK_DATALEN(&state->ps); } } } PSOCK_END(&state->ps); }
static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) { NODE_DBG("enter mqtt_socket_received.\n"); uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; msg_queue_t *node = NULL; int length = (int)len; // uint8_t in_buffer[MQTT_BUF_SIZE]; uint8_t *in_buffer = (uint8_t *)pdata; struct espconn *pesp_conn = arg; if(pesp_conn == NULL) return; lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse; if(mud == NULL) return; READPACKET: if(length > MQTT_BUF_SIZE || length <= 0) return; // c_memcpy(in_buffer, pdata, length); uint8_t temp_buffer[MQTT_BUF_SIZE]; mqtt_msg_init(&mud->mqtt_state.mqtt_connection, temp_buffer, MQTT_BUF_SIZE); mqtt_message_t *temp_msg = NULL; switch(mud->connState){ case MQTT_CONNECT_SENDING: case MQTT_CONNECT_SENT: if(mqtt_get_type(in_buffer) != MQTT_MSG_TYPE_CONNACK){ NODE_DBG("MQTT: Invalid packet\r\n"); mud->connState = MQTT_INIT; if(mud->secure) espconn_secure_disconnect(pesp_conn); else espconn_disconnect(pesp_conn); } else { mud->connState = MQTT_DATA; NODE_DBG("MQTT: Connected\r\n"); if(mud->cb_connect_ref == LUA_NOREF) break; if(mud->self_ref == LUA_NOREF) break; if(mud->L == NULL) break; lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_connect_ref); lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); // pass the userdata(client) to callback func in lua lua_call(mud->L, 1, 0); break; } break; case MQTT_DATA: mud->mqtt_state.message_length_read = length; mud->mqtt_state.message_length = mqtt_get_total_length(in_buffer, mud->mqtt_state.message_length_read); msg_type = mqtt_get_type(in_buffer); msg_qos = mqtt_get_qos(in_buffer); msg_id = mqtt_get_id(in_buffer, mud->mqtt_state.message_length); msg_queue_t *pending_msg = msg_peek(&(mud->mqtt_state.pending_msg_q)); NODE_DBG("MQTT_DATA: type: %d, qos: %d, msg_id: %d, pending_id: %d\r\n", msg_type, msg_qos, msg_id, (pending_msg)?pending_msg->msg_id:0); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg->msg_id == msg_id){ NODE_DBG("MQTT: Subscribe successful\r\n"); msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); if (mud->cb_suback_ref == LUA_NOREF) break; if (mud->self_ref == LUA_NOREF) break; if(mud->L == NULL) break; lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_suback_ref); lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); lua_call(mud->L, 1, 0); } break; case MQTT_MSG_TYPE_UNSUBACK: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg->msg_id == msg_id){ NODE_DBG("MQTT: UnSubscribe successful\r\n"); msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); } break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1){ temp_msg = mqtt_msg_puback(&mud->mqtt_state.mqtt_connection, msg_id); node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, msg_id, MQTT_MSG_TYPE_PUBACK, (int)mqtt_get_qos(temp_msg->data) ); } else if(msg_qos == 2){ temp_msg = mqtt_msg_pubrec(&mud->mqtt_state.mqtt_connection, msg_id); node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, msg_id, MQTT_MSG_TYPE_PUBREC, (int)mqtt_get_qos(temp_msg->data) ); } if(msg_qos == 1 || msg_qos == 2){ NODE_DBG("MQTT: Queue response QoS: %d\r\n", msg_qos); } deliver_publish(mud, in_buffer, mud->mqtt_state.message_length); break; case MQTT_MSG_TYPE_PUBACK: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg->msg_id == msg_id){ NODE_DBG("MQTT: Publish with QoS = 1 successful\r\n"); msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); if(mud->cb_puback_ref == LUA_NOREF) break; if(mud->self_ref == LUA_NOREF) break; if(mud->L == NULL) break; lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_puback_ref); lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); // pass the userdata to callback func in lua lua_call(mud->L, 1, 0); } break; case MQTT_MSG_TYPE_PUBREC: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg->msg_id == msg_id){ NODE_DBG("MQTT: Publish with QoS = 2 Received PUBREC\r\n"); // Note: actrually, should not destroy the msg until PUBCOMP is received. msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); temp_msg = mqtt_msg_pubrel(&mud->mqtt_state.mqtt_connection, msg_id); node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, msg_id, MQTT_MSG_TYPE_PUBREL, (int)mqtt_get_qos(temp_msg->data) ); NODE_DBG("MQTT: Response PUBREL\r\n"); } break; case MQTT_MSG_TYPE_PUBREL: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg->msg_id == msg_id){ msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); temp_msg = mqtt_msg_pubcomp(&mud->mqtt_state.mqtt_connection, msg_id); node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, msg_id, MQTT_MSG_TYPE_PUBCOMP, (int)mqtt_get_qos(temp_msg->data) ); NODE_DBG("MQTT: Response PUBCOMP\r\n"); } break; case MQTT_MSG_TYPE_PUBCOMP: if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg->msg_id == msg_id){ NODE_DBG("MQTT: Publish with QoS = 2 successful\r\n"); msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q))); if(mud->cb_puback_ref == LUA_NOREF) break; if(mud->self_ref == LUA_NOREF) break; if(mud->L == NULL) break; lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_puback_ref); lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); // pass the userdata to callback func in lua lua_call(mud->L, 1, 0); } break; case MQTT_MSG_TYPE_PINGREQ: temp_msg = mqtt_msg_pingresp(&mud->mqtt_state.mqtt_connection); node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, msg_id, MQTT_MSG_TYPE_PINGRESP, (int)mqtt_get_qos(temp_msg->data) ); NODE_DBG("MQTT: Response PINGRESP\r\n"); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore NODE_DBG("MQTT: PINGRESP received\r\n"); break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { length = mud->mqtt_state.message_length_read; if(mud->mqtt_state.message_length < mud->mqtt_state.message_length_read) { length -= mud->mqtt_state.message_length; in_buffer += mud->mqtt_state.message_length; NODE_DBG("Get another published message\r\n"); goto READPACKET; } } break; } if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){ mud->event_timeout = MQTT_SEND_TIMEOUT; NODE_DBG("Sent: %d\n", node->msg.length); if( mud->secure ) espconn_secure_sent( pesp_conn, node->msg.data, node->msg.length ); else espconn_sent( pesp_conn, node->msg.data, node->msg.length ); } mud->keep_alive_tick = 0; NODE_DBG("receive, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q))); NODE_DBG("leave mqtt_socket_received.\n"); return; }
/** * @brief Client received callback function. * @param arg: contain the ip link information * @param pdata: received data * @param len: the length of received data * @retval None */ static void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) { //os_printf("MQTT: recv CB\n"); uint8_t msg_type; uint16_t msg_id; uint16_t msg_len; struct espconn* pCon = (struct espconn*)arg; MQTT_Client* client = (MQTT_Client *)pCon->reverse; if (client == NULL) return; // aborted connection //os_printf("MQTT: Data received %d bytes\n", len); do { // append data to our buffer int avail = client->in_buffer_size - client->in_buffer_filled; if (len <= avail) { os_memcpy(client->in_buffer + client->in_buffer_filled, pdata, len); client->in_buffer_filled += len; len = 0; } else { os_memcpy(client->in_buffer + client->in_buffer_filled, pdata, avail); client->in_buffer_filled += avail; len -= avail; pdata += avail; } // check out what's at the head of the buffer msg_type = mqtt_get_type(client->in_buffer); msg_id = mqtt_get_id(client->in_buffer, client->in_buffer_size); msg_len = mqtt_get_total_length(client->in_buffer, client->in_buffer_size); if (msg_len > client->in_buffer_size) { // oops, too long a message for us to digest, disconnect and hope for a miracle os_printf("MQTT: Too long a message (%d bytes)\n", msg_len); mqtt_doAbort(client); return; } // check whether what's left in the buffer is a complete message if (msg_len > client->in_buffer_filled) break; if (client->connState != MQTT_CONNECTED) { // why are we receiving something?? DBG_MQTT("MQTT ERROR: recv in invalid state %d\n", client->connState); mqtt_doAbort(client); return; } // we are connected and are sending/receiving data messages uint8_t pending_msg_type = 0; uint16_t pending_msg_id = 0; if (client->pending_buffer != NULL) { pending_msg_type = mqtt_get_type(client->pending_buffer->data); pending_msg_id = mqtt_get_id(client->pending_buffer->data, client->pending_buffer->filled); } DBG_MQTT("MQTT: Recv type=%s id=%04X len=%d; Pend type=%s id=%02X\n", mqtt_msg_type[msg_type], msg_id, msg_len, mqtt_msg_type[pending_msg_type],pending_msg_id); switch (msg_type) { case MQTT_MSG_TYPE_CONNACK: //DBG_MQTT("MQTT: Connect successful\n"); // callbacks for internal and external clients if (client->connectedCb) client->connectedCb((uint32_t*)client); if (client->cmdConnectedCb) client->cmdConnectedCb((uint32_t*)client); client->reconTimeout = 1; // reset the reconnect backoff break; case MQTT_MSG_TYPE_SUBACK: if (pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: Subscribe successful\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); } break; case MQTT_MSG_TYPE_UNSUBACK: if (pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: Unsubscribe successful\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); } break; case MQTT_MSG_TYPE_PUBACK: // ack for a publish we sent if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: QoS1 Publish successful\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); } break; case MQTT_MSG_TYPE_PUBREC: // rec for a publish we sent if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: QoS2 publish cont\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); // we need to send PUBREL mqtt_msg_pubrel(&client->mqtt_connection, msg_id); mqtt_enq_message(client, client->mqtt_connection.message.data, client->mqtt_connection.message.length); } break; case MQTT_MSG_TYPE_PUBCOMP: // comp for a pubrel we sent (originally publish we sent) if (pending_msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: QoS2 Publish successful\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); } break; case MQTT_MSG_TYPE_PUBLISH: { // incoming publish // we may need to ACK the publish uint8_t msg_qos = mqtt_get_qos(client->in_buffer); #ifdef MQTT_DBG uint16_t topic_length = msg_len; os_printf("MQTT: Recv PUBLISH qos=%d %s\n", msg_qos, mqtt_get_publish_topic(client->in_buffer, &topic_length)); #endif if (msg_qos == 1) mqtt_msg_puback(&client->mqtt_connection, msg_id); if (msg_qos == 2) mqtt_msg_pubrec(&client->mqtt_connection, msg_id); if (msg_qos == 1 || msg_qos == 2) { mqtt_enq_message(client, client->mqtt_connection.message.data, client->mqtt_connection.message.length); } // send the publish message to clients deliver_publish(client, client->in_buffer, msg_len); } break; case MQTT_MSG_TYPE_PUBREL: // rel for a rec we sent (originally publish received) if (pending_msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg_id == msg_id) { //DBG_MQTT("MQTT: Cont QoS2 recv\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); // we need to send PUBCOMP mqtt_msg_pubcomp(&client->mqtt_connection, msg_id); mqtt_enq_message(client, client->mqtt_connection.message.data, client->mqtt_connection.message.length); } break; case MQTT_MSG_TYPE_PINGRESP: client->keepAliveAckTick = 0; break; } // Shift out the message and see whether we have another one if (msg_len < client->in_buffer_filled) os_memcpy(client->in_buffer, client->in_buffer+msg_len, client->in_buffer_filled-msg_len); client->in_buffer_filled -= msg_len; } while(client->in_buffer_filled > 0 || len > 0); // Send next packet out, if possible if (!client->sending && client->pending_buffer == NULL && client->msgQueue != NULL) { mqtt_send_message(client); } }