int keepalive(MQTTClient *c)
{
    int rc = SUCCESS;

    if (c->keepAliveInterval == 0) {
        goto exit;
    }

    if (TimerIsExpired(&c->last_sent) || TimerIsExpired(&c->last_received)) {
        if (c->ping_outstanding && TimerIsExpired(&c->ping_wait)) {
            rc = FAILURE; /* PINGRESP not received in keepalive interval */
        } else {
            Timer timer;
            TimerInit(&timer);
            TimerCountdownMS(&timer, 1000);
            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);

            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS) { // send the ping packet
                c->ping_outstanding = 1;
                TimerCountdownMS(&c->ping_wait, CONFIG_MQTT_PING_TIMEOUT);
            }
        }
    }

exit:
    return rc;
}
int MQTTDisconnect(MQTTClient *c)
{
    int rc = FAILURE;
    Timer timer;     // we might wait for incomplete incoming publishes to complete
    int len = 0;

#if defined(MQTT_TASK)
    MutexLock(&c->mutex);
#endif
    TimerInit(&timer);
    TimerCountdownMS(&timer, c->command_timeout_ms);

    len = MQTTSerialize_disconnect(c->buf, c->buf_size);

    if (len > 0) {
        rc = sendPacket(c, len, &timer);    // send the disconnect packet
    }

    MQTTCloseSession(c);

#if defined(MQTT_TASK)
    MutexUnlock(&c->mutex);
#endif
    return rc;
}
void MQTTRun(void *parm)
{
    Timer timer;
    MQTTClient *c = (MQTTClient *)parm;

    TimerInit(&timer);

    while (1) {
        TimerCountdownMS(&timer, CONFIG_MQTT_RECV_CYCLE); /* Don't wait too long if no traffic is incoming */

#if CONFIG_MQTT_RECV_CYCLE == 0     /* The smaller cycle, the greater throughput */
        esp_task_wdt_reset();
#endif

#if defined(MQTT_TASK)
        MutexLock(&c->mutex);
#endif

        int rc = cycle(c, &timer);

        if (rc == FAILURE) {
            ESP_LOGE(TAG, "MQTTRun cycle failed");
#if defined(MQTT_TASK)
            MutexUnlock(&c->mutex);
#endif
            vTaskDelete(NULL);
        }

#if defined(MQTT_TASK)
        MutexUnlock(&c->mutex);
#endif
    }
}
int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter)
{
	int rc = FAILURE;
	Timer timer;
	MQTTString topic = MQTTString_initializer;
	topic.cstring = (char *)topicFilter;
	int len = 0;

#if defined(MQTT_TASK)
	FreeRTOS_MutexLock(&c->mutex);
#endif
	if (!c->isconnected)
		goto exit;

	TimerInit(&timer);
	TimerCountdownMS(&timer, c->command_timeout_ms);

	if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
		goto exit;
	if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
		goto exit; // there was a problem

	if (waitfor(c, UNSUBACK, &timer) == UNSUBACK) {
		unsigned short mypacketid;  // should be the same as the packetid above
		if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
			rc = 0;
	} else
		rc = FAILURE;

exit:
#if defined(MQTT_TASK)
	FreeRTOS_MutexUnlock(&c->mutex);
#endif
	return rc;
}
int MQTTSubscribeWithResults(MQTTClient *c, const char *topicFilter, enum QoS qos,
                             messageHandler messageHandler, MQTTSubackData *data)
{
    int rc = FAILURE;
    Timer timer;
    int len = 0;
    MQTTString topic = MQTTString_initializer;
    topic.cstring = (char *)topicFilter;

#if defined(MQTT_TASK)
    MutexLock(&c->mutex);
#endif

    if (!c->isconnected) {
        goto exit;
    }

    TimerInit(&timer);
    TimerCountdownMS(&timer, c->command_timeout_ms);

    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int *)&qos);

    if (len <= 0) {
        goto exit;
    }

    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) { // send the subscribe packet
        goto exit;    // there was a problem
    }

    if (waitfor(c, SUBACK, &timer) == SUBACK) {    // wait for suback
        int count = 0;
        unsigned short mypacketid;
        data->grantedQoS = QOS0;

        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int *)&data->grantedQoS, c->readbuf, c->readbuf_size) == 1) {
            if (data->grantedQoS != 0x80) {
                rc = MQTTSetMessageHandler(c, topicFilter, messageHandler);
            }
        }
    } else {
        rc = FAILURE;
    }

exit:

    if (rc == FAILURE) {
        MQTTCloseSession(c);
    }

#if defined(MQTT_TASK)
    MutexUnlock(&c->mutex);
#endif
    return rc;
}
int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)
{
	int rc = FAILURE;
	Timer timer;
	MQTTString topic = MQTTString_initializer;
	topic.cstring = (char *)topicName;
	int len = 0;

#if defined(MQTT_TASK)
	FreeRTOS_MutexLock(&c->mutex);
#endif
	if (!c->isconnected)
		goto exit;

	TimerInit(&timer);
	TimerCountdownMS(&timer, c->command_timeout_ms);

	if (message->qos == QOS1 || message->qos == QOS2)
		message->id = getNextPacketId(c);

	len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,
	                            topic, (unsigned char*)message->payload, message->payloadlen);
	if (len <= 0)
		goto exit;
	if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
		goto exit; // there was a problem

	if (message->qos == QOS1) {
		if (waitfor(c, PUBACK, &timer) == PUBACK) {
			unsigned short mypacketid;
			unsigned char dup, type;
			if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
				rc = FAILURE;
		} else
			rc = FAILURE;
	} else if (message->qos == QOS2) {
		if (waitfor(c, PUBCOMP, &timer) == PUBCOMP) {
			unsigned short mypacketid;
			unsigned char dup, type;
			if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
				rc = FAILURE;
		} else
			rc = FAILURE;
	}

exit:
#if defined(MQTT_TASK)
	FreeRTOS_MutexUnlock(&c->mutex);
#endif
	return rc;
}
int MQTTUnsubscribe(MQTTClient *c, const char *topicFilter)
{
    int rc = FAILURE;
    Timer timer;
    MQTTString topic = MQTTString_initializer;
    topic.cstring = (char *)topicFilter;
    int len = 0;

#if defined(MQTT_TASK)
    MutexLock(&c->mutex);
#endif

    if (!c->isconnected) {
        goto exit;
    }

    TimerInit(&timer);
    TimerCountdownMS(&timer, c->command_timeout_ms);

    if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0) {
        goto exit;
    }

    if ((rc = sendPacket(c, len, &timer)) != SUCCESS) { // send the subscribe packet
        goto exit;    // there was a problem
    }

    if (waitfor(c, UNSUBACK, &timer) == UNSUBACK) {
        unsigned short mypacketid;  // should be the same as the packetid above

        if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1) {
            /* remove the subscription message handler associated with this topic, if there is one */
            MQTTSetMessageHandler(c, topicFilter, NULL);
        }
    } else {
        rc = FAILURE;
    }

exit:

    if (rc == FAILURE) {
        MQTTCloseSession(c);
    }

#if defined(MQTT_TASK)
    MutexUnlock(&c->mutex);
#endif
    return rc;
}
int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
{
	int rc = FAILURE;
	Timer timer;
	int len = 0;
	MQTTString topic = MQTTString_initializer;
	topic.cstring = (char *)topicFilter;

#if defined(MQTT_TASK)
	FreeRTOS_MutexLock(&c->mutex);
#endif
	if (!c->isconnected)
		goto exit;

	TimerInit(&timer);
	TimerCountdownMS(&timer, c->command_timeout_ms);

	len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int*)&qos);
	if (len <= 0)
		goto exit;
	if ((rc = sendPacket(c, len, &timer)) != SUCCESS) // send the subscribe packet
		goto exit;             // there was a problem

	if (waitfor(c, SUBACK, &timer) == SUBACK) {    // wait for suback
		int count = 0, grantedQoS = -1;
		unsigned short mypacketid;
		if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1)
			rc = grantedQoS; // 0, 1, 2 or 0x80
		if (rc != 0x80) {
			int i;
			for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i) {
				if (c->messageHandlers[i].topicFilter == 0) {
					c->messageHandlers[i].topicFilter = topicFilter;
					c->messageHandlers[i].fp = messageHandler;
					rc = 0;
					break;
				}
			}
		}
	} else
		rc = FAILURE;

exit:
#if defined(MQTT_TASK)
	FreeRTOS_MutexUnlock(&c->mutex);
#endif
	return rc;
}
int MQTTYield(MQTTClient *c, int timeout_ms)
{
    int rc = SUCCESS;
    Timer timer;

    TimerInit(&timer);
    TimerCountdownMS(&timer, timeout_ms);

    do {
        if (cycle(c, &timer) < 0) {
            rc = FAILURE;
            break;
        }
    } while (!TimerIsExpired(&timer));

    return rc;
}
int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)
{
	Timer connect_timer;
	int rc = FAILURE;
	MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
	int len = 0;

#if defined(MQTT_TASK)
	FreeRTOS_MutexLock(&c->mutex);
#endif
	if (c->isconnected) /* don't send connect packet again if we are already connected */
		goto exit;

	TimerInit(&connect_timer);
	TimerCountdownMS(&connect_timer, c->command_timeout_ms);

	if (options == 0)
		options = &default_options; /* set default options if none were supplied */

	c->keepAliveInterval = options->keepAliveInterval;
	TimerCountdown(&c->ping_timer, c->keepAliveInterval);
	if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
		goto exit;
	if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESS) 
		goto exit;
	// this will be a blocking call, wait for the connack
	if (waitfor(c, CONNACK, &connect_timer) == CONNACK) {
		unsigned char connack_rc = 255;
		unsigned char sessionPresent = 0;
		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, c->readbuf, c->readbuf_size) == 1)
			rc = connack_rc;
		else
			rc = FAILURE;
	} else
		rc = FAILURE;

exit:
	if (rc == SUCCESS)
		c->isconnected = 1;

#if defined(MQTT_TASK)
	FreeRTOS_MutexUnlock(&c->mutex);
#endif

	return rc;
}
void MQTTRun(void* parm)
{
	Timer timer;
	MQTTClient* c = (MQTTClient*)parm;

	TimerInit(&timer);

	while (1) {
#if defined(MQTT_TASK)
		FreeRTOS_MutexLock(&c->mutex);
#endif
		TimerCountdownMS(&timer, 500); /* Don't wait too long if no traffic is incoming */
		cycle(c, &timer);
#if defined(MQTT_TASK)
		FreeRTOS_MutexUnlock(&c->mutex);
#endif
	}
}
int MQTTYield(MQTTClient* c, int timeout_ms)
{
	int rc = SUCCESS;
	Timer timer;
	TimerInit(&timer);

#if defined(MQTT_TASK)
	FreeRTOS_MutexLock(&c->mutex);
#endif
	TimerCountdownMS(&timer, timeout_ms);
	//printf(".");
	rc = cycle(c, &timer);
#if defined(MQTT_TASK)
	FreeRTOS_MutexUnlock(&c->mutex);
#endif
	sys_msleep(1); 

	return rc;
}
int keepalive(MQTTClient* c)
{
	int rc = SUCCESS;

	if (c->keepAliveInterval == 0) {
		rc = SUCCESS;
		goto exit;
	}

	if (TimerIsExpired(&c->ping_timer)) {
		printf("keep alive counter expired\n");
		if (!c->ping_outstanding) {
			printf("keep alive counter reset\n");
			//Set the pingreq send timeout
			Timer timer;
			TimerInit(&timer);
			TimerCountdownMS(&timer, 1000);
			int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
			/* If the sendPacket success, the keep alive works with keepAliveInterval */
			if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESS)  {// send the ping packet
				c->ping_outstanding = 1;
				TimerCountdown(&c->ping_timer, c->keepAliveInterval); // record the fact that we have successfully sent the packet
			} else {
				rc = FAILURE;
			}
		} else {
		
			printf("keep alive counter failure\n");

			rc = FAILURE;
		}
	}

exit:
	return rc;
}
void TimerCountdown(Timer* timer, uint32_t timeout) {
    TimerCountdownMS(timer, timeout * 1000);
}
Beispiel #15
0
int MQTTConnectWithResults(MQTTClient *c, MQTTPacket_connectData *options, MQTTConnackData *data)
{
    Timer connect_timer;
    int rc = FAILURE;
    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
    int len = 0;

#if defined(MQTT_TASK)
    MutexLock(&c->mutex);
#endif

    if (c->isconnected) { /* don't send connect packet again if we are already connected */
        goto exit;
    }

    TimerInit(&connect_timer);
    TimerCountdownMS(&connect_timer, c->command_timeout_ms);

    if (options == 0) {
        options = &default_options;    /* set default options if none were supplied */
    }

    c->keepAliveInterval = options->keepAliveInterval;
    c->cleansession = options->cleansession;
    TimerCountdown(&c->last_received, c->keepAliveInterval);

    if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0) {
        goto exit;
    }

    if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESS) { // send the connect packet
        goto exit;    // there was a problem
    }

    // this will be a blocking call, wait for the connack
    if (waitfor(c, CONNACK, &connect_timer) == CONNACK) {
        data->rc = 0;
        data->sessionPresent = 0;

        if (MQTTDeserialize_connack(&data->sessionPresent, &data->rc, c->readbuf, c->readbuf_size) == 1) {
            rc = data->rc;
        } else {
            rc = FAILURE;
        }
    } else {
        rc = FAILURE;
    }

exit:

    if (rc == SUCCESS) {
        c->isconnected = 1;
        c->ping_outstanding = 0;
    }

#if defined(MQTT_TASK)
    MutexUnlock(&c->mutex);
#endif

    return rc;
}