Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code
Revision 15:7ba48f016569, committed 2017-12-12
- Comitter:
- DuyLionTran
- Date:
- Tue Dec 12 15:58:44 2017 +0000
- Parent:
- 14:0129ac8844ee
- Child:
- 16:a4118bfd7b41
- Commit message:
- version 1.6
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MQTT.lib Tue Dec 12 15:58:44 2017 +0000 @@ -0,0 +1,1 @@ +MQTT#818366b014c9
--- a/MQTT/FP.lib Sun Dec 10 17:17:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/sam_grove/code/FP/#3c62ba1807ac
--- a/MQTT/MQTTAsync.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,607 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- *
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Ian Craggs - initial API and implementation and/or initial documentation
- *******************************************************************************/
-
-#if !defined(MQTTASYNC_H)
-#define MQTTASYNC_H
-
-#include "FP.h"
-#include "MQTTPacket.h"
-#include "stdio.h"
-
-namespace MQTT
-{
-
-
-enum QoS { QOS0, QOS1, QOS2 };
-
-
-struct Message
-{
- enum QoS qos;
- bool retained;
- bool dup;
- unsigned short id;
- void *payload;
- size_t payloadlen;
-};
-
-
-class PacketId
-{
-public:
- PacketId();
-
- int getNext();
-
-private:
- static const int MAX_PACKET_ID = 65535;
- int next;
-};
-
-typedef void (*messageHandler)(Message*);
-
-typedef struct limits
-{
- int MAX_MQTT_PACKET_SIZE; //
- int MAX_MESSAGE_HANDLERS; // each subscription requires a message handler
- int MAX_CONCURRENT_OPERATIONS; // each command which runs concurrently can have a result handler, when we are in multi-threaded mode
- int command_timeout_ms;
-
- limits()
- {
- MAX_MQTT_PACKET_SIZE = 100;
- MAX_MESSAGE_HANDLERS = 5;
- MAX_CONCURRENT_OPERATIONS = 1; // 1 indicates single-threaded mode - set to >1 for multithreaded mode
- command_timeout_ms = 30000;
- }
-} Limits;
-
-
-/**
- * @class Async
- * @brief non-blocking, threaded MQTT client API
- * @param Network a network class which supports send, receive
- * @param Timer a timer class with the methods:
- */
-template<class Network, class Timer, class Thread, class Mutex> class Async
-{
-
-public:
-
- struct Result
- {
- /* success or failure result data */
- Async<Network, Timer, Thread, Mutex>* client;
- int rc;
- };
-
- typedef void (*resultHandler)(Result*);
-
- Async(Network* network, const Limits limits = Limits());
-
- typedef struct
- {
- Async* client;
- Network* network;
- } connectionLostInfo;
-
- typedef int (*connectionLostHandlers)(connectionLostInfo*);
-
- /** Set the connection lost callback - called whenever the connection is lost and we should be connected
- * @param clh - pointer to the callback function
- */
- void setConnectionLostHandler(connectionLostHandlers clh)
- {
- connectionLostHandler.attach(clh);
- }
-
- /** Set the default message handling callback - used for any message which does not match a subscription message handler
- * @param mh - pointer to the callback function
- */
- void setDefaultMessageHandler(messageHandler mh)
- {
- defaultMessageHandler.attach(mh);
- }
-
- int connect(resultHandler fn, MQTTPacket_connectData* options = 0);
-
- template<class T>
- int connect(void(T::*method)(Result *), MQTTPacket_connectData* options = 0, T *item = 0); // alternative to pass in pointer to member function
-
- int publish(resultHandler rh, const char* topic, Message* message);
-
- int subscribe(resultHandler rh, const char* topicFilter, enum QoS qos, messageHandler mh);
-
- int unsubscribe(resultHandler rh, const char* topicFilter);
-
- int disconnect(resultHandler rh);
-
-private:
-
- void run(void const *argument);
- int cycle(int timeout);
- int waitfor(int packet_type, Timer& atimer);
- int keepalive();
- int findFreeOperation();
-
- int decodePacket(int* value, int timeout);
- int readPacket(int timeout);
- int sendPacket(int length, int timeout);
- int deliverMessage(MQTTString* topic, Message* message);
-
- Thread* thread;
- Network* ipstack;
-
- Limits limits;
-
- char* buf;
- char* readbuf;
-
- Timer ping_timer, connect_timer;
- unsigned int keepAliveInterval;
- bool ping_outstanding;
-
- PacketId packetid;
-
- typedef FP<void, Result*> resultHandlerFP;
- resultHandlerFP connectHandler;
-
- typedef FP<void, Message*> messageHandlerFP;
- struct MessageHandlers
- {
- const char* topic;
- messageHandlerFP fp;
- } *messageHandlers; // Message handlers are indexed by subscription topic
-
- // how many concurrent operations should we allow? Each one will require a function pointer
- struct Operations
- {
- unsigned short id;
- resultHandlerFP fp;
- const char* topic; // if this is a publish, store topic name in case republishing is required
- Message* message; // for publish,
- Timer timer; // to check if the command has timed out
- } *operations; // result handlers are indexed by packet ids
-
- static void threadfn(void* arg);
-
- messageHandlerFP defaultMessageHandler;
-
- typedef FP<int, connectionLostInfo*> connectionLostFP;
-
- connectionLostFP connectionLostHandler;
-
-};
-
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> void MQTT::Async<Network, Timer, Thread, Mutex>::threadfn(void* arg)
-{
- ((Async<Network, Timer, Thread, Mutex>*) arg)->run(NULL);
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> MQTT::Async<Network, Timer, Thread, Mutex>::Async(Network* network, Limits limits) : limits(limits), packetid()
-{
- this->thread = 0;
- this->ipstack = network;
- this->ping_timer = Timer();
- this->ping_outstanding = 0;
-
- // How to make these memory allocations portable? I was hoping to avoid the heap
- buf = new char[limits.MAX_MQTT_PACKET_SIZE];
- readbuf = new char[limits.MAX_MQTT_PACKET_SIZE];
- this->operations = new struct Operations[limits.MAX_CONCURRENT_OPERATIONS];
- for (int i = 0; i < limits.MAX_CONCURRENT_OPERATIONS; ++i)
- operations[i].id = 0;
- this->messageHandlers = new struct MessageHandlers[limits.MAX_MESSAGE_HANDLERS];
- for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
- messageHandlers[i].topic = 0;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::sendPacket(int length, int timeout)
-{
- int sent = 0;
-
- while (sent < length)
- sent += ipstack->write(&buf[sent], length, timeout);
- if (sent == length)
- ping_timer.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet
- return sent;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::decodePacket(int* value, int timeout)
-{
- char c;
- int multiplier = 1;
- int len = 0;
- const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
-
- *value = 0;
- do
- {
- int rc = MQTTPACKET_READ_ERROR;
-
- if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
- {
- rc = MQTTPACKET_READ_ERROR; /* bad data */
- goto exit;
- }
- rc = ipstack->read(&c, 1, timeout);
- if (rc != 1)
- goto exit;
- *value += (c & 127) * multiplier;
- multiplier *= 128;
- } while ((c & 128) != 0);
-exit:
- return len;
-}
-
-
-/**
- * If any read fails in this method, then we should disconnect from the network, as on reconnect
- * the packets can be retried.
- * @param timeout the max time to wait for the packet read to complete, in milliseconds
- * @return the MQTT packet type, or -1 if none
- */
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::readPacket(int timeout)
-{
- int rc = -1;
- MQTTHeader header = {0};
- int len = 0;
- int rem_len = 0;
-
- /* 1. read the header byte. This has the packet type in it */
- if (ipstack->read(readbuf, 1, timeout) != 1)
- goto exit;
-
- len = 1;
- /* 2. read the remaining length. This is variable in itself */
- decodePacket(&rem_len, timeout);
- len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
-
- /* 3. read the rest of the buffer using a callback to supply the rest of the data */
- if (ipstack->read(readbuf + len, rem_len, timeout) != rem_len)
- goto exit;
-
- header.byte = readbuf[0];
- rc = header.bits.type;
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::deliverMessage(MQTTString* topic, Message* message)
-{
- int rc = -1;
-
- // we have to find the right message handler - indexed by topic
- for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
- {
- if (messageHandlers[i].topic != 0 && MQTTPacket_equals(topic, (char*)messageHandlers[i].topic))
- {
- messageHandlers[i].fp(message);
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::cycle(int timeout)
-{
- /* get one piece of work off the wire and one pass through */
-
- // read the socket, see what work is due
- int packet_type = readPacket(timeout);
-
- int len, rc;
- switch (packet_type)
- {
- case CONNACK:
- if (this->thread)
- {
- Result res = {this, 0};
- if (MQTTDeserialize_connack(&res.rc, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- ;
- connectHandler(&res);
- connectHandler.detach(); // only invoke the callback once
- }
- break;
- case PUBACK:
- if (this->thread)
- ; //call resultHandler
- case SUBACK:
- break;
- case PUBLISH:
- MQTTString topicName;
- Message msg;
- rc = MQTTDeserialize_publish((int*)&msg.dup, (int*)&msg.qos, (int*)&msg.retained, (int*)&msg.id, &topicName,
- (char**)&msg.payload, (int*)&msg.payloadlen, readbuf, limits.MAX_MQTT_PACKET_SIZE);;
- if (msg.qos == QOS0)
- deliverMessage(&topicName, &msg);
- break;
- case PUBREC:
- int type, dup, mypacketid;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- ;
- // must lock this access against the application thread, if we are multi-threaded
- len = MQTTSerialize_ack(buf, limits.MAX_MQTT_PACKET_SIZE, PUBREL, 0, mypacketid);
- rc = sendPacket(len, timeout); // send the PUBREL packet
- if (rc != len)
- goto exit; // there was a problem
-
- break;
- case PUBCOMP:
- break;
- case PINGRESP:
- ping_outstanding = false;
- break;
- }
- keepalive();
-exit:
- return packet_type;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::keepalive()
-{
- int rc = 0;
-
- if (keepAliveInterval == 0)
- goto exit;
-
- if (ping_timer.expired())
- {
- if (ping_outstanding)
- rc = -1;
- else
- {
- int len = MQTTSerialize_pingreq(buf, limits.MAX_MQTT_PACKET_SIZE);
- rc = sendPacket(len, 1000); // send the ping packet
- if (rc != len)
- rc = -1; // indicate there's a problem
- else
- ping_outstanding = true;
- }
- }
-
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> void MQTT::Async<Network, Timer, Thread, Mutex>::run(void const *argument)
-{
- while (true)
- cycle(ping_timer.left_ms());
-}
-
-
-// only used in single-threaded mode where one command at a time is in process
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::waitfor(int packet_type, Timer& atimer)
-{
- int rc = -1;
-
- do
- {
- if (atimer.expired())
- break; // we timed out
- }
- while ((rc = cycle(atimer.left_ms())) != packet_type);
-
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::connect(resultHandler resultHandler, MQTTPacket_connectData* options)
-{
- connect_timer.countdown(limits.command_timeout_ms);
-
- MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
- if (options == 0)
- options = &default_options; // set default options if none were supplied
-
- this->keepAliveInterval = options->keepAliveInterval;
- ping_timer.countdown(this->keepAliveInterval);
- int len = MQTTSerialize_connect(buf, limits.MAX_MQTT_PACKET_SIZE, options);
- int rc = sendPacket(len, connect_timer.left_ms()); // send the connect packet
- if (rc != len)
- goto exit; // there was a problem
-
- if (resultHandler == 0) // wait until the connack is received
- {
- // this will be a blocking call, wait for the connack
- if (waitfor(CONNACK, connect_timer) == CONNACK)
- {
- int connack_rc = -1;
- if (MQTTDeserialize_connack(&connack_rc, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- rc = connack_rc;
- }
- }
- else
- {
- // set connect response callback function
- connectHandler.attach(resultHandler);
-
- // start background thread
- this->thread = new Thread((void (*)(void const *argument))&MQTT::Async<Network, Timer, Thread, Mutex>::threadfn, (void*)this);
- }
-
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::findFreeOperation()
-{
- int found = -1;
- for (int i = 0; i < limits.MAX_CONCURRENT_OPERATIONS; ++i)
- {
- if (operations[i].id == 0)
- {
- found = i;
- break;
- }
- }
- return found;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::subscribe(resultHandler resultHandler, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
-{
- int index = 0;
- if (this->thread)
- index = findFreeOperation();
- Timer& atimer = operations[index].timer;
-
- atimer.countdown(limits.command_timeout_ms);
- MQTTString topic = {(char*)topicFilter, 0, 0};
-
- int len = MQTTSerialize_subscribe(buf, limits.MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
- int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
- if (rc != len)
- goto exit; // there was a problem
-
- /* wait for suback */
- if (resultHandler == 0)
- {
- // this will block
- if (waitfor(SUBACK, atimer) == SUBACK)
- {
- int count = 0, grantedQoS = -1, mypacketid;
- if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- rc = grantedQoS; // 0, 1, 2 or 0x80
- if (rc != 0x80)
- {
- for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
- {
- if (messageHandlers[i].topic == 0)
- {
- messageHandlers[i].topic = topicFilter;
- messageHandlers[i].fp.attach(messageHandler);
- rc = 0;
- break;
- }
- }
- }
- }
- }
- else
- {
- // set subscribe response callback function
-
- }
-
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::unsubscribe(resultHandler resultHandler, const char* topicFilter)
-{
- int index = 0;
- if (this->thread)
- index = findFreeOperation();
- Timer& atimer = operations[index].timer;
-
- atimer.countdown(limits.command_timeout_ms);
- MQTTString topic = {(char*)topicFilter, 0, 0};
-
- int len = MQTTSerialize_unsubscribe(buf, limits.MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic);
- int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
- if (rc != len)
- goto exit; // there was a problem
-
- // set unsubscribe response callback function
-
-
-exit:
- return rc;
-}
-
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::publish(resultHandler resultHandler, const char* topicName, Message* message)
-{
- int index = 0;
- if (this->thread)
- index = findFreeOperation();
- Timer& atimer = operations[index].timer;
-
- atimer.countdown(limits.command_timeout_ms);
- MQTTString topic = {(char*)topicName, 0, 0};
-
- if (message->qos == QOS1 || message->qos == QOS2)
- message->id = packetid.getNext();
-
- int len = MQTTSerialize_publish(buf, limits.MAX_MQTT_PACKET_SIZE, 0, message->qos, message->retained, message->id, topic, (char*)message->payload, message->payloadlen);
- int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
- if (rc != len)
- goto exit; // there was a problem
-
- /* wait for acks */
- if (resultHandler == 0)
- {
- if (message->qos == QOS1)
- {
- if (waitfor(PUBACK, atimer) == PUBACK)
- {
- int type, dup, mypacketid;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- rc = 0;
- }
- }
- else if (message->qos == QOS2)
- {
- if (waitfor(PUBCOMP, atimer) == PUBCOMP)
- {
- int type, dup, mypacketid;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
- rc = 0;
- }
-
- }
- }
- else
- {
- // set publish response callback function
-
- }
-
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::disconnect(resultHandler resultHandler)
-{
- Timer timer = Timer(limits.command_timeout_ms); // we might wait for incomplete incoming publishes to complete
- int len = MQTTSerialize_disconnect(buf, limits.MAX_MQTT_PACKET_SIZE);
- int rc = sendPacket(len, timer.left_ms()); // send the disconnect packet
-
- return (rc == len) ? 0 : -1;
-}
-
-
-
-#endif
\ No newline at end of file
--- a/MQTT/MQTTClient.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1052 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014, 2017 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- *
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Ian Craggs - initial API and implementation and/or initial documentation
- * Ian Craggs - fix for bug 458512 - QoS 2 messages
- * Ian Craggs - fix for bug 460389 - send loop uses wrong length
- * Ian Craggs - fix for bug 464169 - clearing subscriptions
- * Ian Craggs - fix for bug 464551 - enums and ints can be different size
- * Mark Sonnentag - fix for bug 475204 - inefficient instantiation of Timer
- * Ian Craggs - fix for bug 475749 - packetid modified twice
- * Ian Craggs - add ability to set message handler separately #6
- *******************************************************************************/
-
-#if !defined(MQTTCLIENT_H)
-#define MQTTCLIENT_H
-
-#include "FP.h"
-#include "MQTTPacket.h"
-#include <stdio.h>
-#include "MQTTLogging.h"
-
-#if !defined(MQTTCLIENT_QOS1)
- #define MQTTCLIENT_QOS1 1
-#endif
-#if !defined(MQTTCLIENT_QOS2)
- #define MQTTCLIENT_QOS2 0
-#endif
-
-namespace MQTT
-{
-
-
-enum QoS { QOS0, QOS1, QOS2 };
-
-// all failure return codes must be negative
-enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
-
-
-struct Message
-{
- enum QoS qos;
- bool retained;
- bool dup;
- unsigned short id;
- void *payload;
- size_t payloadlen;
-};
-
-
-struct MessageData
-{
- MessageData(MQTTString &aTopicName, struct Message &aMessage) : message(aMessage), topicName(aTopicName)
- { }
-
- struct Message &message;
- MQTTString &topicName;
-};
-
-
-struct connackData
-{
- int rc;
- bool sessionPresent;
-};
-
-
-struct subackData
-{
- int grantedQoS;
-};
-
-
-class PacketId
-{
-public:
- PacketId()
- {
- next = 0;
- }
-
- int getNext()
- {
- return next = (next == MAX_PACKET_ID) ? 1 : next + 1;
- }
-
-private:
- static const int MAX_PACKET_ID = 65535;
- int next;
-};
-
-
-/**
- * @class Client
- * @brief blocking, non-threaded MQTT client API
- *
- * This version of the API blocks on all method calls, until they are complete. This means that only one
- * MQTT request can be in process at any one time.
- * @param Network a network class which supports send, receive
- * @param Timer a timer class with the methods:
- */
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5>
-class Client
-{
-
-public:
-
- typedef void (*messageHandler)(MessageData&);
-
- /** Construct the client
- * @param network - pointer to an instance of the Network class - must be connected to the endpoint
- * before calling MQTT connect
- * @param limits an instance of the Limit class - to alter limits as required
- */
- Client(Network& network, unsigned int command_timeout_ms = 30000);
-
- /** Set the default message handling callback - used for any message which does not match a subscription message handler
- * @param mh - pointer to the callback function. Set to 0 to remove.
- */
- void setDefaultMessageHandler(messageHandler mh)
- {
- if (mh != 0)
- defaultMessageHandler.attach(mh);
- else
- defaultMessageHandler.detach();
- }
-
- /** Set a message handling callback. This can be used outside of the the subscribe method.
- * @param topicFilter - a topic pattern which can include wildcards
- * @param mh - pointer to the callback function. If 0, removes the callback if any
- */
- int setMessageHandler(const char* topicFilter, messageHandler mh);
-
- /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
- * The nework object must be connected to the network endpoint before calling this
- * Default connect options are used
- * @return success code -
- */
- int connect();
-
- /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
- * The nework object must be connected to the network endpoint before calling this
- * @param options - connect options
- * @return success code -
- */
- int connect(MQTTPacket_connectData& options);
-
- /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
- * The nework object must be connected to the network endpoint before calling this
- * @param options - connect options
- * @param connackData - connack data to be returned
- * @return success code -
- */
- int connect(MQTTPacket_connectData& options, connackData& data);
-
- /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
- * @param topic - the topic to publish to
- * @param message - the message to send
- * @return success code -
- */
- int publish(const char* topicName, Message& message);
-
- /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
- * @param topic - the topic to publish to
- * @param payload - the data to send
- * @param payloadlen - the length of the data
- * @param qos - the QoS to send the publish at
- * @param retained - whether the message should be retained
- * @return success code -
- */
- int publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos = QOS0, bool retained = false);
-
- /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
- * @param topic - the topic to publish to
- * @param payload - the data to send
- * @param payloadlen - the length of the data
- * @param id - the packet id used - returned
- * @param qos - the QoS to send the publish at
- * @param retained - whether the message should be retained
- * @return success code -
- */
- int publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos = QOS1, bool retained = false);
-
- /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
- * @param topicFilter - a topic pattern which can include wildcards
- * @param qos - the MQTT QoS to subscribe at
- * @param mh - the callback function to be invoked when a message is received for this subscription
- * @return success code -
- */
- int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh);
-
- /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
- * @param topicFilter - a topic pattern which can include wildcards
- * @param qos - the MQTT QoS to subscribe at©
- * @param mh - the callback function to be invoked when a message is received for this subscription
- * @param
- * @return success code -
- */
- int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh, subackData &data);
-
- /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback
- * @param topicFilter - a topic pattern which can include wildcards
- * @return success code -
- */
- int unsubscribe(const char* topicFilter);
-
- /** MQTT Disconnect - send an MQTT disconnect packet, and clean up any state
- * @return success code -
- */
- int disconnect();
-
- /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive
- * yield can be called if no other MQTT operation is needed. This will also allow messages to be
- * received.
- * @param timeout_ms the time to wait, in milliseconds
- * @return success code - on failure, this means the client has disconnected
- */
- int yield(unsigned long timeout_ms = 1000L);
-
- /** Is the client connected?
- * @return flag - is the client connected or not?
- */
- bool isConnected()
- {
- return isconnected;
- }
-
-private:
-
- void closeSession();
- void cleanSession();
- int cycle(Timer& timer);
- int waitfor(int packet_type, Timer& timer);
- int keepalive();
- int publish(int len, Timer& timer, enum QoS qos);
-
- int decodePacket(int* value, int timeout);
- int readPacket(Timer& timer);
- int sendPacket(int length, Timer& timer);
- int deliverMessage(MQTTString& topicName, Message& message);
- bool isTopicMatched(char* topicFilter, MQTTString& topicName);
-
- Network& ipstack;
- unsigned long command_timeout_ms;
-
- unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
- unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
-
- Timer last_sent, last_received;
- unsigned int keepAliveInterval;
- bool ping_outstanding;
- bool cleansession;
-
- PacketId packetid;
-
- struct MessageHandlers
- {
- const char* topicFilter;
- FP<void, MessageData&> fp;
- } messageHandlers[MAX_MESSAGE_HANDLERS]; // Message handlers are indexed by subscription topic
-
- FP<void, MessageData&> defaultMessageHandler;
-
- bool isconnected;
-
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- unsigned char pubbuf[MAX_MQTT_PACKET_SIZE]; // store the last publish for sending on reconnect
- int inflightLen;
- unsigned short inflightMsgid;
- enum QoS inflightQoS;
-#endif
-
-#if MQTTCLIENT_QOS2
- bool pubrel;
- #if !defined(MAX_INCOMING_QOS2_MESSAGES)
- #define MAX_INCOMING_QOS2_MESSAGES 10
- #endif
- unsigned short incomingQoS2messages[MAX_INCOMING_QOS2_MESSAGES];
- bool isQoS2msgidFree(unsigned short id);
- bool useQoS2msgid(unsigned short id);
- void freeQoS2msgid(unsigned short id);
-#endif
-
-};
-
-}
-
-
-template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
-void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::cleanSession()
-{
- for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
- messageHandlers[i].topicFilter = 0;
-
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- inflightMsgid = 0;
- inflightQoS = QOS0;
-#endif
-
-#if MQTTCLIENT_QOS2
- pubrel = false;
- for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
- incomingQoS2messages[i] = 0;
-#endif
-}
-
-
-template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
-void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::closeSession()
-{
- ping_outstanding = false;
- isconnected = false;
- if (cleansession)
- cleanSession();
-}
-
-
-template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
-MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms) : ipstack(network), packetid()
-{
- this->command_timeout_ms = command_timeout_ms;
- cleansession = true;
- closeSession();
-}
-
-
-#if MQTTCLIENT_QOS2
-template<class Network, class Timer, int a, int b>
-bool MQTT::Client<Network, Timer, a, b>::isQoS2msgidFree(unsigned short id)
-{
- for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
- {
- if (incomingQoS2messages[i] == id)
- return false;
- }
- return true;
-}
-
-
-template<class Network, class Timer, int a, int b>
-bool MQTT::Client<Network, Timer, a, b>::useQoS2msgid(unsigned short id)
-{
- for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
- {
- if (incomingQoS2messages[i] == 0)
- {
- incomingQoS2messages[i] = id;
- return true;
- }
- }
- return false;
-}
-
-
-template<class Network, class Timer, int a, int b>
-void MQTT::Client<Network, Timer, a, b>::freeQoS2msgid(unsigned short id)
-{
- for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
- {
- if (incomingQoS2messages[i] == id)
- {
- incomingQoS2messages[i] = 0;
- return;
- }
- }
-}
-#endif
-
-
-template<class Network, class Timer, int a, int b>
-int MQTT::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer)
-{
- int rc = FAILURE,
- sent = 0;
-
- while (sent < length)
- {
- rc = ipstack.write(&sendbuf[sent], length - sent, timer.left_ms());
- if (rc < 0) // there was an error writing the data
- break;
- sent += rc;
- if (timer.expired()) // only check expiry after at least one attempt to write
- break;
- }
- if (sent == length)
- {
- if (this->keepAliveInterval > 0)
- last_sent.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet
- rc = SUCCESS;
- }
- else
- rc = FAILURE;
-
-#if defined(MQTT_DEBUG)
- char printbuf[150];
- DEBUG("Rc %d from sending packet %s\r\n", rc,
- MQTTFormat_toServerString(printbuf, sizeof(printbuf), sendbuf, length));
-#endif
- return rc;
-}
-
-
-template<class Network, class Timer, int a, int b>
-int MQTT::Client<Network, Timer, a, b>::decodePacket(int* value, int timeout)
-{
- unsigned char c;
- int multiplier = 1;
- int len = 0;
- const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
-
- *value = 0;
- do
- {
- int rc = MQTTPACKET_READ_ERROR;
-
- if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
- {
- rc = MQTTPACKET_READ_ERROR; /* bad data */
- goto exit;
- }
- rc = ipstack.read(&c, 1, timeout);
- if (rc != 1)
- goto exit;
- *value += (c & 127) * multiplier;
- multiplier *= 128;
- } while ((c & 128) != 0);
-exit:
- return len;
-}
-
-
-/**
- * If any read fails in this method, then we should disconnect from the network, as on reconnect
- * the packets can be retried.
- * @param timeout the max time to wait for the packet read to complete, in milliseconds
- * @return the MQTT packet type, 0 if none, -1 if error
- */
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::readPacket(Timer& timer)
-{
- int rc = FAILURE;
- MQTTHeader header = {0};
- int len = 0;
- int rem_len = 0;
-
- /* 1. read the header byte. This has the packet type in it */
- rc = ipstack.read(readbuf, 1, timer.left_ms());
- if (rc != 1)
- goto exit;
-
- len = 1;
- /* 2. read the remaining length. This is variable in itself */
- decodePacket(&rem_len, timer.left_ms());
- len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
-
- if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
- {
- rc = BUFFER_OVERFLOW;
- goto exit;
- }
-
- /* 3. read the rest of the buffer using a callback to supply the rest of the data */
- if (rem_len > 0 && (ipstack.read(readbuf + len, rem_len, timer.left_ms()) != rem_len))
- goto exit;
-
- header.byte = readbuf[0];
- rc = header.bits.type;
- if (this->keepAliveInterval > 0)
- last_received.countdown(this->keepAliveInterval); // record the fact that we have successfully received a packet
-exit:
-
-#if defined(MQTT_DEBUG)
- if (rc >= 0)
- {
- char printbuf[50];
- DEBUG("Rc %d receiving packet %s\r\n", rc,
- MQTTFormat_toClientString(printbuf, sizeof(printbuf), readbuf, len));
- }
-#endif
- return rc;
-}
-
-
-// assume topic filter and name is in correct format
-// # can only be at end
-// + and # can only be next to separator
-template<class Network, class Timer, int a, int b>
-bool MQTT::Client<Network, Timer, a, b>::isTopicMatched(char* topicFilter, MQTTString& topicName)
-{
- char* curf = topicFilter;
- char* curn = topicName.lenstring.data;
- char* curn_end = curn + topicName.lenstring.len;
-
- while (*curf && curn < curn_end)
- {
- if (*curn == '/' && *curf != '/')
- break;
- if (*curf != '+' && *curf != '#' && *curf != *curn)
- break;
- if (*curf == '+')
- { // skip until we meet the next separator, or end of string
- char* nextpos = curn + 1;
- while (nextpos < curn_end && *nextpos != '/')
- nextpos = ++curn + 1;
- }
- else if (*curf == '#')
- curn = curn_end - 1; // skip until end of string
- curf++;
- curn++;
- };
-
- return (curn == curn_end) && (*curf == '\0');
-}
-
-
-
-template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
-int MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTString& topicName, Message& message)
-{
- int rc = FAILURE;
-
- // we have to find the right message handler - indexed by topic
- for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
- {
- if (messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(&topicName, (char*)messageHandlers[i].topicFilter) ||
- isTopicMatched((char*)messageHandlers[i].topicFilter, topicName)))
- {
- if (messageHandlers[i].fp.attached())
- {
- MessageData md(topicName, message);
- messageHandlers[i].fp(md);
- rc = SUCCESS;
- }
- }
- }
-
- if (rc == FAILURE && defaultMessageHandler.attached())
- {
- MessageData md(topicName, message);
- defaultMessageHandler(md);
- rc = SUCCESS;
- }
-
- return rc;
-}
-
-
-
-template<class Network, class Timer, int a, int b>
-int MQTT::Client<Network, Timer, a, b>::yield(unsigned long timeout_ms)
-{
- int rc = SUCCESS;
- Timer timer;
-
- timer.countdown_ms(timeout_ms);
- while (!timer.expired())
- {
- if (cycle(timer) < 0)
- {
- rc = FAILURE;
- break;
- }
- }
-
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle(Timer& timer)
-{
- // get one piece of work off the wire and one pass through
- int len = 0,
- rc = SUCCESS;
-
- int packet_type = readPacket(timer); // read the socket, see what work is due
-
- switch (packet_type)
- {
- default:
- // no more data to read, unrecoverable. Or read packet fails due to unexpected network error
- rc = packet_type;
- goto exit;
- case NSAPI_ERROR_WOULD_BLOCK:
- case NSAPI_ERROR_OK: // timed out reading packet
- break;
- case CONNACK:
- case PUBACK:
- case SUBACK:
- break;
- case PUBLISH:
- {
- MQTTString topicName = MQTTString_initializer;
- Message msg;
- int intQoS;
- msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */
- if (MQTTDeserialize_publish((unsigned char*)&msg.dup, &intQoS, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
- (unsigned char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
- goto exit;
- msg.qos = (enum QoS)intQoS;
-#if MQTTCLIENT_QOS2
- if (msg.qos != QOS2)
-#endif
- deliverMessage(topicName, msg);
-#if MQTTCLIENT_QOS2
- else if (isQoS2msgidFree(msg.id))
- {
- if (useQoS2msgid(msg.id))
- deliverMessage(topicName, msg);
- else
- WARN("Maximum number of incoming QoS2 messages exceeded");
- }
-#endif
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- if (msg.qos != QOS0)
- {
- if (msg.qos == QOS1)
- len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBACK, 0, msg.id);
- else if (msg.qos == QOS2)
- len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREC, 0, msg.id);
- if (len <= 0)
- rc = FAILURE;
- else
- rc = sendPacket(len, timer);
- if (rc == FAILURE)
- goto exit; // there was a problem
- }
- break;
-#endif
- }
-#if MQTTCLIENT_QOS2
- case PUBREC:
- case PUBREL:
- unsigned short mypacketid;
- unsigned char dup, type;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
- rc = FAILURE;
- else if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE,
- (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
- rc = FAILURE;
- else if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet
- rc = FAILURE; // there was a problem
- if (rc == FAILURE)
- goto exit; // there was a problem
- if (packet_type == PUBREL)
- freeQoS2msgid(mypacketid);
- break;
-
- case PUBCOMP:
- break;
-#endif
- case PINGRESP:
- ping_outstanding = false;
- break;
- }
-
- if (keepalive() != SUCCESS)
- //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
- rc = FAILURE;
-
-exit:
- if (rc == SUCCESS)
- rc = packet_type;
- else if (isconnected)
- closeSession();
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::keepalive()
-{
- int rc = SUCCESS;
- static Timer ping_sent;
-
- if (keepAliveInterval == 0)
- goto exit;
-
- if (ping_outstanding)
- {
- if (ping_sent.expired())
- {
- rc = FAILURE; // session failure
- #if defined(MQTT_DEBUG)
- DEBUG("PINGRESP not received in keepalive interval\r\n");
- #endif
- }
- }
- else if (last_sent.expired() || last_received.expired())
- {
- Timer timer(1000);
- int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
- if (len > 0 && (rc = sendPacket(len, timer)) == SUCCESS) // send the ping packet
- {
- ping_outstanding = true;
- ping_sent.countdown(this->keepAliveInterval);
- }
- }
-exit:
- return rc;
-}
-
-
-// only used in single-threaded mode where one command at a time is in process
-template<class Network, class Timer, int a, int b>
-int MQTT::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer)
-{
- int rc = FAILURE;
-
- do
- {
- if (timer.expired())
- break; // we timed out
- rc = cycle(timer);
- }
- while (rc != packet_type && rc >= 0);
-
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options, connackData& data)
-{
- Timer connect_timer(command_timeout_ms);
- int rc = FAILURE;
- int len = 0;
-
- if (isconnected) // don't send connect packet again if we are already connected
- goto exit;
-
- this->keepAliveInterval = options.keepAliveInterval;
- this->cleansession = options.cleansession;
- if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &options)) <= 0)
- goto exit;
- if ((rc = sendPacket(len, connect_timer)) != SUCCESS) // send the connect packet
- goto exit; // there was a problem
-
- if (this->keepAliveInterval > 0)
- last_received.countdown(this->keepAliveInterval);
- // this will be a blocking call, wait for the connack
- if (waitfor(CONNACK, connect_timer) == CONNACK)
- {
- data.rc = 0;
- data.sessionPresent = false;
- if (MQTTDeserialize_connack((unsigned char*)&data.sessionPresent,
- (unsigned char*)&data.rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
- rc = data.rc;
- else
- rc = FAILURE;
- }
- else
- rc = FAILURE;
-
-#if MQTTCLIENT_QOS2
- // resend any inflight publish
- if (inflightMsgid > 0 && inflightQoS == QOS2 && pubrel)
- {
- if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREL, 0, inflightMsgid)) <= 0)
- rc = FAILURE;
- else
- rc = publish(len, connect_timer, inflightQoS);
- }
- else
-#endif
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- if (inflightMsgid > 0)
- {
- memcpy(sendbuf, pubbuf, MAX_MQTT_PACKET_SIZE);
- rc = publish(inflightLen, connect_timer, inflightQoS);
- }
-#endif
-
-exit:
- if (rc == SUCCESS)
- {
- isconnected = true;
- ping_outstanding = false;
- }
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options)
-{
- connackData data;
- return connect(options, data);
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect()
-{
- MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
- return connect(default_options);
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::setMessageHandler(const char* topicFilter, messageHandler messageHandler)
-{
- int rc = FAILURE;
- int i = -1;
-
- // first check for an existing matching slot
- for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
- {
- if (messageHandlers[i].topicFilter != 0 && strcmp(messageHandlers[i].topicFilter, topicFilter) == 0)
- {
- if (messageHandler == 0) // remove existing
- {
- messageHandlers[i].topicFilter = 0;
- messageHandlers[i].fp.detach();
- }
- rc = SUCCESS; // return i when adding new subscription
- break;
- }
- }
- // if no existing, look for empty slot (unless we are removing)
- if (messageHandler != 0) {
- if (rc == FAILURE)
- {
- for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
- {
- if (messageHandlers[i].topicFilter == 0)
- {
- rc = SUCCESS;
- break;
- }
- }
- }
- if (i < MAX_MESSAGE_HANDLERS)
- {
- messageHandlers[i].topicFilter = topicFilter;
- messageHandlers[i].fp.attach(messageHandler);
- }
- }
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter,
- enum QoS qos, messageHandler messageHandler, subackData& data)
-{
- int rc = FAILURE;
- Timer timer(command_timeout_ms);
- int len = 0;
- MQTTString topic = {(char*)topicFilter, {0, 0}};
-
- if (!isconnected)
- goto exit;
-
- len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
- if (len <= 0)
- goto exit;
- if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet
- goto exit; // there was a problem
-
- if (waitfor(SUBACK, timer) == SUBACK) // wait for suback
- {
- int count = 0;
- unsigned short mypacketid;
- data.grantedQoS = 0;
- if (MQTTDeserialize_suback(&mypacketid, 1, &count, &data.grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
- {
- if (data.grantedQoS != 0x80)
- rc = setMessageHandler(topicFilter, messageHandler);
- }
- }
- else
- rc = FAILURE;
-
-exit:
- if (rc == FAILURE)
- closeSession();
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter, enum QoS qos, messageHandler messageHandler)
-{
- subackData data;
- return subscribe(topicFilter, qos, messageHandler, data);
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(const char* topicFilter)
-{
- int rc = FAILURE;
- Timer timer(command_timeout_ms);
- MQTTString topic = {(char*)topicFilter, {0, 0}};
- int len = 0;
-
- if (!isconnected)
- goto exit;
-
- if ((len = MQTTSerialize_unsubscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic)) <= 0)
- goto exit;
- if ((rc = sendPacket(len, timer)) != SUCCESS) // send the unsubscribe packet
- goto exit; // there was a problem
-
- if (waitfor(UNSUBACK, timer) == UNSUBACK)
- {
- unsigned short mypacketid; // should be the same as the packetid above
- if (MQTTDeserialize_unsuback(&mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
- {
- // remove the subscription message handler associated with this topic, if there is one
- setMessageHandler(topicFilter, 0);
- }
- }
- else
- rc = FAILURE;
-
-exit:
- if (rc != SUCCESS)
- closeSession();
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(int len, Timer& timer, enum QoS qos)
-{
- int rc;
-
- if ((rc = sendPacket(len, timer)) != SUCCESS) // send the publish packet
- goto exit; // there was a problem
-
-#if MQTTCLIENT_QOS1
- if (qos == QOS1)
- {
- if (waitfor(PUBACK, timer) == PUBACK)
- {
- unsigned short mypacketid;
- unsigned char dup, type;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
- rc = FAILURE;
- else if (inflightMsgid == mypacketid)
- inflightMsgid = 0;
- }
- else
- rc = FAILURE;
- }
-#endif
-#if MQTTCLIENT_QOS2
- else if (qos == QOS2)
- {
- if (waitfor(PUBCOMP, timer) == PUBCOMP)
- {
- unsigned short mypacketid;
- unsigned char dup, type;
- if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
- rc = FAILURE;
- else if (inflightMsgid == mypacketid)
- inflightMsgid = 0;
- }
- else
- rc = FAILURE;
- }
-#endif
-
-exit:
- if (rc != SUCCESS)
- closeSession();
- return rc;
-}
-
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos, bool retained)
-{
- int rc = FAILURE;
- Timer timer(command_timeout_ms);
- MQTTString topicString = MQTTString_initializer;
- int len = 0;
-
- if (!isconnected)
- goto exit;
-
- topicString.cstring = (char*)topicName;
-
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- if (qos == QOS1 || qos == QOS2)
- id = packetid.getNext();
-#endif
-
- len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, qos, retained, id,
- topicString, (unsigned char*)payload, payloadlen);
- if (len <= 0)
- goto exit;
-
-#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
- if (!cleansession)
- {
- memcpy(pubbuf, sendbuf, len);
- inflightMsgid = id;
- inflightLen = len;
- inflightQoS = qos;
-#if MQTTCLIENT_QOS2
- pubrel = false;
-#endif
- }
-#endif
-
- rc = publish(len, timer, qos);
-exit:
- return rc;
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos, bool retained)
-{
- unsigned short id = 0; // dummy - not used for anything
- return publish(topicName, payload, payloadlen, id, qos, retained);
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, Message& message)
-{
- return publish(topicName, message.payload, message.payloadlen, message.qos, message.retained);
-}
-
-
-template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
-int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::disconnect()
-{
- int rc = FAILURE;
- Timer timer(command_timeout_ms); // we might wait for incomplete incoming publishes to complete
- int len = MQTTSerialize_disconnect(sendbuf, MAX_MQTT_PACKET_SIZE);
- if (len > 0)
- rc = sendPacket(len, timer); // send the disconnect packet
- closeSession();
- return rc;
-}
-
-#endif
--- a/MQTT/MQTTEthernet.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-
-#if !defined(MQTTETHERNET_H)
-#define MQTTETHERNET_H
-
-#include "MQTTmbed.h"
-#include "EthernetInterface.h"
-#include "MQTTSocket.h"
-
-class MQTTEthernet : public MQTTSocket
-{
-public:
- MQTTEthernet() : MQTTSocket(ð)
- {
- eth.connect();
- }
-
- EthernetInterface& getEth()
- {
- return eth;
- }
-
-private:
-
- EthernetInterface eth;
-
-};
-
-
-#endif
--- a/MQTT/MQTTLogging.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#if !defined(MQTT_LOGGING_H)
-#define MQTT_LOGGING_H
-
-#define STREAM stdout
-#if !defined(DEBUG)
-#define DEBUG(...) \
- {\
- fprintf(STREAM, "DEBUG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
- fprintf(STREAM, ##__VA_ARGS__); \
- fflush(STREAM); \
- }
-#endif
-#if !defined(LOG)
-#define LOG(...) \
- {\
- fprintf(STREAM, "LOG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
- fprintf(STREAM, ##__VA_ARGS__); \
- fflush(STREAM); \
- }
-#endif
-#if !defined(WARN)
-#define WARN(...) \
- { \
- fprintf(STREAM, "WARN: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
- fprintf(STREAM, ##__VA_ARGS__); \
- fflush(STREAM); \
- }
-#endif
-#if !defined(ERROR)
-#define ERROR(...) \
- { \
- fprintf(STREAM, "ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
- fprintf(STREAM, ##__VA_ARGS__); \
- fflush(STREAM); \
- exit(1); \
- }
-#endif
-
-#endif
\ No newline at end of file
--- a/MQTT/MQTTPacket.lib Sun Dec 10 17:17:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/teams/mqtt/code/MQTTPacket/#aedcaf7984d5
--- a/MQTT/MQTTSocket.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-#if !defined(MQTTSOCKET_H)
-#define MQTTSOCKET_H
-
-#include "MQTTmbed.h"
-#include <EthernetInterface.h>
-#include <Timer.h>
-
-class MQTTSocket
-{
-public:
- MQTTSocket(EthernetInterface *anet)
- {
- net = anet;
- open = false;
- }
-
- int connect(char* hostname, int port, int timeout=1000)
- {
- if (open)
- disconnect();
- nsapi_error_t rc = mysock.open(net);
- open = true;
- mysock.set_blocking(true);
- mysock.set_timeout((unsigned int)timeout);
- rc = mysock.connect(hostname, port);
- mysock.set_blocking(false); // blocking timeouts seem not to work
- return rc;
- }
-
- // common read/write routine, avoiding blocking timeouts
- int common(unsigned char* buffer, int len, int timeout, bool read)
- {
- timer.start();
- mysock.set_blocking(false); // blocking timeouts seem not to work
- int bytes = 0;
- bool first = true;
- do
- {
- if (first)
- first = false;
- else
- wait_ms(timeout < 100 ? timeout : 100);
- int rc;
- if (read)
- rc = mysock.recv((char*)buffer, len);
- else
- rc = mysock.send((char*)buffer, len);
- if (rc < 0)
- {
- if (rc != NSAPI_ERROR_WOULD_BLOCK)
- {
- bytes = -1;
- break;
- }
- }
- else
- bytes += rc;
- }
- while (bytes < len && timer.read_ms() < timeout);
- timer.stop();
- return bytes;
- }
-
- /* returns the number of bytes read, which could be 0.
- -1 if there was an error on the socket
- */
- int read(unsigned char* buffer, int len, int timeout)
- {
- return common(buffer, len, timeout, true);
- }
-
- int write(unsigned char* buffer, int len, int timeout)
- {
- return common(buffer, len, timeout, false);
- }
-
- int disconnect()
- {
- open = false;
- return mysock.close();
- }
-
- /*bool is_connected()
- {
- return mysock.is_connected();
- }*/
-
-private:
-
- bool open;
- TCPSocket mysock;
- EthernetInterface *net;
- Timer timer;
-
-};
-
-#endif
--- a/MQTT/MQTTmbed.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#if !defined(MQTT_MBED_H)
-#define MQTT_MBED_H
-
-#include "mbed.h"
-
-class Countdown
-{
-public:
- Countdown() : t()
- {
-
- }
-
- Countdown(int ms) : t()
- {
- countdown_ms(ms);
- }
-
-
- bool expired()
- {
- return t.read_ms() >= interval_end_ms;
- }
-
- void countdown_ms(unsigned long ms)
- {
- t.stop();
- interval_end_ms = ms;
- t.reset();
- t.start();
- }
-
- void countdown(int seconds)
- {
- countdown_ms((unsigned long)seconds * 1000L);
- }
-
- int left_ms()
- {
- return interval_end_ms - t.read_ms();
- }
-
-private:
- Timer t;
- unsigned long interval_end_ms;
-};
-
-#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NDefLib.lib Tue Dec 12 15:58:44 2017 +0000 @@ -0,0 +1,1 @@ +NDefLib#6eb44b07d867
--- a/NDefLib/Message.cpp Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/**
- ******************************************************************************
- * @file Message.cpp
- * @author ST / Central Labs
- * @version V2.0.0
- * @date 28 Apr 2017
- * @brief NDef Message class implementation
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-
-#include <cstdlib>
-#include "NDefLib/Message.h"
-#include "RecordType/EmptyRecord.h"
-#include "RecordType/RecordText.h"
-#include "RecordType/RecordAAR.h"
-#include "RecordType/RecordMimeType.h"
-#include "RecordType/RecordURI.h"
-
-namespace NDefLib {
-
-uint16_t Message::get_byte_length() const {
- uint16_t lenght = 2; //length size
-
- if (mRecords.size() == 0) {
- return lenght + EmptyRecord().get_byte_length();
- }
-
- std::vector<Record*>::const_iterator it = mRecords.begin();
- const std::vector<Record*>::const_iterator end = mRecords.end();
-
- for (; it != end; ++it) {
- lenght += (*it)->get_byte_length();
- } //for
-
- return lenght;
-} //getByteLenght
-
-uint16_t Message::write(uint8_t *buffer) const {
-
- const uint16_t length = get_byte_length() - 2;
- uint16_t offset = 0;
- buffer[offset++] = (uint8_t) ((length & 0xFF00) >> 8);
- buffer[offset++] = (uint8_t) ((length & 0x00FF));
-
- const uint32_t nRecord = mRecords.size();
-
- if (mRecords.size() == 0) {
- offset += EmptyRecord().write(buffer + offset);
- return offset;
- } //else
-
- for (uint32_t i = 0; i < nRecord; i++) {
- Record *r = mRecords[i];
-
- r->set_as_middle_record();
- if (i == 0) {
- r->set_as_first_record();
- }
- if (i == nRecord - 1) {
- r->set_as_last_record();
- }
-
- offset += r->write(buffer + offset);
- } //for
-
- return offset;
-} //write
-
-void Message::parse_message(const uint8_t * const rawNdefFile, const uint16_t length, Message *msg) {
- uint16_t offset = 0;
- Record *r;
-
- RecordHeader header;
- do {
- const uint8_t headerLenght = header.load_header(rawNdefFile + offset);
- r = RecordText::parse(header, rawNdefFile + offset + headerLenght);
- if (r == NULL) {
- r = RecordAAR::parse(header, rawNdefFile + offset + headerLenght);
- }
- if (r == NULL) {
- r = RecordMimeType::parse(header,
- rawNdefFile + offset + headerLenght);
- }
- if (r == NULL) {
- r = RecordURI::parse(header, rawNdefFile + offset + headerLenght);
- }
-
- offset += header.get_record_length();
- msg->add_record(r);
- } while (offset < length);
-}
-
-void Message::remove_and_delete_all_record(Message &msg){
- const uint32_t nRecords =msg.get_N_records();
- for (uint32_t i =0 ;i<nRecords ;i++) {
- NDefLib::Record *r = msg[i];
- delete r;
- }//for
- msg.mRecords.clear();
-}//removeAndDeleteAllRecord
-
-} /* namespace NDefLib */
-
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- a/NDefLib/Message.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/**
- ******************************************************************************
- * @file Message.h
- * @author ST / Central Labs
- * @version V2.0.0
- * @date 28 Apr 2017
- * @brief NDef Message class
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-
-#ifndef NDEFLIB_MESSAGE_H_
-#define NDEFLIB_MESSAGE_H_
-
-#include <algorithm>
-#include <vector>
-
-#include "Record.h"
-
-namespace NDefLib {
-
-/**
- * Class containing a list of {@link Record}
- */
-class Message {
-public:
-
- /**
- * Add a ndef record to this message.
- * @param r Record to add
- */
- void add_record(Record *r) {
- mRecords.push_back(r);
- }
-
- /**
- * Remove a ndef record to this message
- * @param r record to remove
- */
- void remove_record(Record *r){
- mRecords.erase( std::remove( mRecords.begin(), mRecords.end(), r ), mRecords.end() );
- }
-
-
- /**
- * Add all the records in the list to this message.
- * @param addList List of records to add.
- */
- void add_records(const std::vector<Record*> &addList) {
- mRecords.insert(mRecords.end(), addList.begin(), addList.end());
- }
-
- /**
- * Get the specific record contained by this message, NULL if not a valid index.
- * @param index Record index.
- * @return a Record object if present, otherwise NULL
- */
- Record* operator[](const uint32_t index)const{
- if (index >= mRecords.size()) {
- return NULL;
- }
-
- return mRecords[index];
- }
-
- /**
- * Get the number of records in this message.
- * @return number of records in this message
- */
- uint32_t get_N_records() const {
- return mRecords.size();
- }
-
- /**
- * Length in bytes needed to write this message.
- * @return number of bytes needed to write this message
- */
- uint16_t get_byte_length() const;
-
- /**
- * Write message in the provided buffer
- * @par The first 2 bytes contain the NDEF message length.
- * @param[out] buffer Buffer the message must be written into.
- * @return number of bytes written
- */
- uint16_t write(uint8_t *buffer) const;
-
- /**
- * Create a set of records from a raw buffer adding them to a message object.
- * @par Message buffer must NOT contain the buffer length in the first two bytes.
- * @param buffer Buffer containing the message record.
- * @param bufferLength Buffer length.
- * @param[in,out] Message message that will contain the new records.
- */
- static void parse_message(const uint8_t * const buffer,
- const uint16_t bufferLength, Message *message);
-
- /**
- * Remove all the recrods from the mesasge and delete it
- * @param msg Message with the records to delete
- */
- static void remove_and_delete_all_record(Message &msg);
-
- virtual ~Message() {
- }
-
-private:
- /**
- * List of records contained by this message.
- */
- std::vector<Record*> mRecords;
-};
-
-} /* namespace NDefLib */
-
-#endif /* NDEFLIB_MESSAGE_H_ */
--- a/NDefLib/NDefNfcTag.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/**
- ******************************************************************************
- * @file NDefNfcTag.h
- * @author ST / Central Labs
- * @version V2.0.0
- * @date 28 Apr 2017
- * @brief Generic interface that a device must implement to use the NDefLib
- * with async communication
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-
-#ifndef NDEFLIB_NDEFNFCTAG_H_
-#define NDEFLIB_NDEFNFCTAG_H_
-
-#include "NDefLib/Message.h"
-
-namespace NDefLib {
-
-/**
- * Abstract class used to write/read NDef messages to/from a nfc tag.
- * This class is made to handle also asynchronous communication with the nfc component.
- * All the functions in this class will return immediately, when a command ends a proper callback function will
- * be called.
- */
-class NDefNfcTag {
-
-public:
-
- /**
- * Class that contains all the function called when a command finished.
- * The default implementation is an empty function.
- */
- class Callbacks {
- public:
-
- /**
- * Called when a session is open.
- * @param tag Tag where the session is open.
- * @param success True if the operation has success.
- */
- virtual void on_session_open(NDefNfcTag *tag,bool success){
- (void)tag;(void)success;
- };
-
- /**
- * Called when a message is written.
- * @param tag Tag where the message is written.
- * @param success True if the operation has success.
- */
- virtual void on_message_write(NDefNfcTag *tag,bool success){
- (void)tag;(void)success;
-
- };
-
- /**
- * Called when a message is read.
- * @param tag Tag where the message is read.
- * @param success True if the operation has success.
- */
- virtual void on_message_read(NDefNfcTag *tag,bool success,
- const Message *msg){
- (void)tag;(void)success; (void)msg;
- };
-
-
- /**
- * Called when a session is closed.
- * @param tag Tag where the session is closed.
- * @param success True if the operation has success.
- */
- virtual void on_session_close(NDefNfcTag *tag,bool success){
- (void)tag;(void)success;
- };
-
- virtual ~Callbacks(){};
- };
-
-private:
-
- /**
- * Data used to store the callback status during a read/write operation.
- */
- struct CallbackStatus{
-
- /** Object that triggers the callback */
- NDefNfcTag *callOwner;
-
- /** Message that the callback is writing/reading */
- Message *msg;
- };
-
-public:
-
- NDefNfcTag():mCallBack(&mDefaultCallBack){}
-
- /**
- * Set the callback object.
- * @param c Object containing the callback.
- */
- void set_callback(Callbacks *c){
- if (c!=NULL) {
- mCallBack=c;
- } else {
- mCallBack=&mDefaultCallBack;
- }
- }//setCallBack
-
-
- /**
- * Open the communication session with the nfc tag.
- * @param force Force to open a communication.
- * @return true if success
- */
- virtual bool open_session(bool force = false)=0;
-
- /**
- * Close the communication with the nfc tag.
- * @return true if success
- */
- virtual bool close_session()=0;
-
- /**
- * Returns true if a communication with the nfc tag is open.
- * @return true if a communication with the nfc tag is open
- */
- virtual bool is_session_open()=0;
-
- /**
- * Write a message in the nfc tag.
- * @par This call will delete the previous message.
- * @param msg Message to write.
- * @return true if success
- */
- virtual bool write(Message &msg) {
- if (!is_session_open()) {
- mCallBack->on_message_write(this,false);
- return false;
- }
-
- const uint16_t length = msg.get_byte_length();
- uint8_t *buffer = new uint8_t[length];
- if (buffer==NULL){ //impossible to allocate the buffer
- mCallBack->on_message_write(this,false);
- return false;
- }
-
- msg.write(buffer);
-
- mCallBackStatus.callOwner=this;
- mCallBackStatus.msg=NULL;
-
- return writeByte(buffer, length,0,NDefNfcTag::onWriteMessageCallback,&mCallBackStatus);
- }
-
- /**
- * Read a message from the tag.
- * @param[in,out] msg Message object the read records are added to.
- * @return true if success
- */
- virtual bool read(Message *msg) {
- if (!is_session_open()) {
- mCallBack->on_message_read(this,false,msg);
- return false;
- }
-
- uint8_t *buffer = new uint8_t[2];
- if (buffer==NULL) {
- mCallBack->on_message_read(this,false,msg);
- return false;
- }
-
- mCallBackStatus.callOwner=this;
- mCallBackStatus.msg=msg;
- return readByte(0,2,buffer,NDefNfcTag::onReadMessageLength,&mCallBackStatus);
- }
-
- virtual ~NDefNfcTag() {}
-
-protected:
-
- typedef struct CallbackStatus CallbackStatus_t;
-
- /**
- * Function that the component will call when a read/write operation is completed
- * @param internalState Callback internal state data.
- * @param status True if the operation succeed.
- * @param buffer Buffer to read/write.
- * @param length Number of byte read/write.
- * @return true if the operation had success
- */
- typedef bool(*byteOperationCallback_t)(CallbackStatus_t *internalState,
- bool status,const uint8_t *buffer, uint16_t length);
-
- /**
- * Write a sequence of bytes to the NDEF file.
- * @param buffer Buffer to write.
- * @param length Number of bytes to write.
- * @param offset Offset where start to write.
- * @param callback Function to call when the operation ended.
- * @param callbackStatus Parameter to pass to the callback function.
- * @return true if the operation has success
- */
- virtual bool writeByte(const uint8_t *buffer, uint16_t length,uint16_t offset,
- byteOperationCallback_t callback,CallbackStatus_t *callbackStatus)=0;
-
- /**
- * Read a sequence of bytes from the NDEF file.
- * @param byteOffset Read offset in bytes.
- * @param byteLength Number of bytes to read.
- * @param[out] buffer Buffer to store the read data into.
- * @param callback Function to call when the operation ended.
- * @param callbackStatus Parameter to pass to the callback function.
- * @return true if the operation has success
- */
- virtual bool readByte(const uint16_t byteOffset, const uint16_t byteLength,
- uint8_t *buffer, byteOperationCallback_t callback,CallbackStatus_t *callbackStatus)=0;
-
-
- /** object with the user callback */
- Callbacks *mCallBack;
-private:
-
- /** object with the current callback status */
- CallbackStatus_t mCallBackStatus;
- /** default callback object, all the functions are empty */
- Callbacks mDefaultCallBack;
-
- /**
- * Function called when a write operation completes, it will invoke on_message_write
- * @param internalState Object that invokes the write operation.
- * @param status True if the operation had success.
- * @param buffer Buffer written.
- * @param length Number of bytes written.
- * @return true if the write had success
- */
- static bool onWriteMessageCallback(CallbackStatus_t *internalState,
- bool status,const uint8_t *buffer, uint16_t ){
- delete [] buffer;
-
- internalState->callOwner->mCallBack->on_message_write(internalState->callOwner,status);
-
- return status;
- }
-
- /**
- * Function called when a read operation completes.
- * In this case we read the message length, this function will read all the message
- * @param internalState Object that invokes the write operation.
- * @param status true If the operation had success.
- * @param buffer Buffer read.
- * @param length Number of bytes read.
- * @return true if the read had success
- */
- static bool onReadMessageLength(CallbackStatus_t *internalState,
- bool status,const uint8_t *buffer, uint16_t length){
-
- if (!status || length!=2) {
- internalState->callOwner->mCallBack->on_message_read(internalState->callOwner,false,internalState->msg);
- return false;
- }//if
-
- length = (((uint16_t) buffer[0]) << 8 | buffer[1]);
- delete [] buffer;
-
- uint8_t *readBuffer = new uint8_t[length];
- if (readBuffer==NULL) {
- internalState->callOwner->mCallBack->on_message_read(internalState->callOwner,false,internalState->msg);
- return false;
- }//readBuffer
-
- internalState->callOwner->readByte(2,length,readBuffer, &NDefNfcTag::onReadMessageCallback,internalState);
- return status;
- }
-
- /**
- * Function called when all messages have been read
- * @param internalState Object that invokes the write operation.
- * @param status True if the operation had success.
- * @param buffer Buffer read.
- * @param length Number of bytes read.
- * @return true if the read had success
- */
- static bool onReadMessageCallback(CallbackStatus_t *internalState,
- bool status,const uint8_t *buffer, uint16_t length){
- if(!status) {
- internalState->callOwner->mCallBack->on_message_read(internalState->callOwner,false,internalState->msg);
- return false;
- }
- Message::parse_message(buffer, length, internalState->msg);
- delete [] buffer;
- internalState->callOwner->mCallBack-> on_message_read(internalState->callOwner,true,internalState->msg);
- return status ;
- }
-
-}; //class NDefNfcTagASync
-
-}// namespace NDefLib
-
-#endif /* NDEFLIB_NDEFNFCTAG_H_ */
-
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- a/NDefLib/Record.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/**
- ******************************************************************************
- * @file Record.h
- * @author ST / Central Labs
- * @version V2.0.0
- * @date 28 Apr 2017
- * @brief Generic Record class
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-
-#ifndef NDEFLIB_RECORD_H_
-#define NDEFLIB_RECORD_H_
-#include <stdint.h>
-
-#include "RecordHeader.h"
-
-namespace NDefLib {
-
-/**
- * Base class for a NDefRecord
- * @see NFC Data Exchange Format (NDEF) Technical Specification NDEF 1.0
- */
-class Record {
-public:
-
- /**
- * Enum used to identify the record type.
- */
- typedef enum {
- TYPE_UNKNOWN, //!< UNKNOWN record
- TYPE_TEXT, //!< TEXT
- TYPE_AAR, //!< Android Archive record
- TYPE_MIME, //!< generic MIME type
- TYPE_URI, //!< generic URI
- TYPE_URI_MAIL, //!< Email URI record
- TYPE_URI_SMS, //!< SMS URI record
- TYPE_URI_GEOLOCATION,//!< position URI record
- TYPE_MIME_VCARD, //!< VCard record
- TYPE_WIFI_CONF //!< Wifi configuration
- } RecordType_t;
-
- Record() {
- }
-
- /**
- * Set the record as the first record in the message.
- */
- void set_as_first_record() {
- mRecordHeader.set_MB(true);
- }
-
- /**
- * Set the record as the last record in the message.
- */
- void set_as_last_record() {
- mRecordHeader.set_ME(true);
- }
-
- /**
- * Check if it is the last record in the message.
- * @return true if it is the last record in the message
- */
- bool is_last_record() const {
- return mRecordHeader.get_ME();
- }
-
- /**
- * Check if it is the first record in the message.
- * @return true if it is the fist record in the message
- */
- bool is_first_record() const {
- return mRecordHeader.get_MB();
- }
-
- /**
- * Set the record as generic (not the first one and not the last one)
- */
- void set_as_middle_record() {
- mRecordHeader.set_MB(false);
- mRecordHeader.set_ME(false);
- }
-
- /**
- * Check if the record is in the middle of a chain.
- * @return true if is not the fist or the last one
- */
- bool is_middle_record() const{
- return ! (mRecordHeader.get_MB() || mRecordHeader.get_ME());
- }
-
- /**
- * Get tag type.
- * @par This method should be overridden to return a valid type.
- * @return tag type
- */
- virtual RecordType_t get_type() const {
- return TYPE_UNKNOWN;
- } //getType
-
-
- /**
- * Get the record header.
- * @return record header
- */
- const RecordHeader& get_header() const{
- return mRecordHeader;
- }
-
- /**
- * Number of bytes needed to store this record.
- * @return size of the header + size of the record content
- */
- virtual uint16_t get_byte_length() {
- return mRecordHeader.get_record_length();
- }
-
- /**
- * Write the record content into a buffer.
- * @param[out] buffer buffer to write the record content into, the buffer size
- * must be almost {@link Record#getByteLength} bytes.
- * @return number of written bytes
- */
- virtual uint16_t write(uint8_t *buffer)=0;
-
- virtual ~Record() {
- };
-
-protected:
- RecordHeader mRecordHeader;
-};
-
-} /* namespace NDefLib */
-
-#endif /* NDEFLIB_RECORD_H_ */
--- a/NDefLib/RecordHeader.h Sun Dec 10 17:17:41 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/**
- ******************************************************************************
- * @file RecordHeader.h
- * @author ST / Central Labs
- * @version V2.0.0
- * @date 28 Apr 2017
- * @brief Record header class
- ******************************************************************************
- * @attention
- *
- * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
-
-#ifndef NDEFLIB_RECORDHEADER_H_
-#define NDEFLIB_RECORDHEADER_H_
-
-#include <stdint.h>
-
-namespace NDefLib {
-
-/**
- * Record header class.
- * @see NFC Data Exchange Format (NDEF) Technical Specification NDEF 1.0
- */
-class RecordHeader {
-
-public:
-
- /**
- * Record type format
- */
- typedef enum TypeNameFormat {
- Empty = 0x00, //!< Empty
- NFC_well_known = 0x01, //!< NFC_well_known
- Mime_media_type = 0x02,//!< Mime_media_type
- Absolute_URI = 0x03, //!< Absolute_URI
- NFC_external = 0x04, //!< NFC_external
- Unknown = 0x05, //!< Unknown
- Unchanged = 0x06, //!< Unchanged
- Reserved = 0x07 //!< Reserved
- } TypeNameFormat_t;
-
-
- RecordHeader() :
- headerFlags(0), typeLength(0), payloadLength(0) {
- set_SR(true);
- }
-
- /**
- * Set the 'message begin' flag.
- * @param value True if the record is the first within the message.
- */
- void set_MB(bool value) {
- if (value) {
- headerFlags |= 0x80;
- } else {
- headerFlags &= ~0x80;
- }
- }//set_MB
-
- /**
- * Check the 'message begin' flag.
- * @return true if it is the first record in the message
- */
- bool get_MB() const {
- return (headerFlags & 0x80) != 0;
- }//get_MB
-
- /**
- * Set the 'message end' flag.
- * @param value True if it is the last record in the message.
- */
- void set_ME(bool value) {
- if (value) {
- headerFlags |= 0x40;
- } else {
- headerFlags &= ~0x40;
- }
- }//set_ME
-
- /**
- * Check the 'message end' flag.
- * @return true if it is the last record in the message
- */
- bool get_ME() const {
- return (headerFlags & 0x40) != 0;
- }//get_ME
-
- /**
- * Set the 'Chunk' flag.
- * @param value True if the record is in the first record chunk or in a middle record
- * chunk of a chunked payload.
- */
- void set_CF(bool value) {
- if (value) {
- headerFlags |= 0x20;
- } else {
- headerFlags &= ~0x20;
- }
- }//set_CF
-
- /**
- * Check the 'Chunk' flag value.
- * @return true if the record is in the first record chunk or in a middle record
- * chunk of a chunked payload
- */
- bool get_CF() const {
- return (headerFlags & 0x20) != 0;
- }//get_CF
-
- /**
- * Set the 'Short record' flag value.
- * @param value True if the record size can be encoded with 8 bits.
- */
- void set_SR(bool value) {
- if (value) {
- headerFlags |= 0x10;
- } else {
- headerFlags &= ~0x10;
- }
- }//setSR
-
- /**
- * Check the 'Short record' flag.
- * @return true if the short range header format is set
- */
- bool get_SR() const {
- return (headerFlags & 0x10) != 0;
- }//getSR
-
- /**
- * Set the 'ID length' flag.
- * @param value True if the 'ID length' value is used.
- */
- void set_IL(bool value) {
- if (value) {
- headerFlags |= 0x08;
- } else {
- headerFlags &= ~0x08;
- }
- }//setIL
-
- /**
- * Check the 'ID length' flag.
- * @param value True if 'ID length' is set.
- */
- bool get_IL() const {
- return (headerFlags & 0x08) != 0;
- }//getIL
-
- /**
- * Set the type name format field.
- * @param value Record type name format.
- */
- void set_FNT(const TypeNameFormat_t value) {
- uint8_t temp = (uint8_t) value;
- temp &= 0x07; //keep the first 3 bits
- headerFlags &= 0xF8; //clean the fist 3 bits
- headerFlags |= temp; //set the fist 3 bits
- }//setFNT
-
- /**
- * Get the record type name.
- * @return type name format of the record
- */
- TypeNameFormat_t get_FNT() const {
- return (TypeNameFormat_t) (headerFlags & 0x07);
- }
-
- /**
- * Set the record payload length.
- * @par This function will update the SR field as needed.
- * @param length payload length
- */
- void set_payload_length(uint32_t length) {
- payloadLength = length;
- set_SR(payloadLength <= 255);
- }
-
- /**
- * Get the payload length.
- * @return payload length
- */
- uint32_t get_payload_length() const {
- return payloadLength;
- }
-
- /**
- * Set the type length.
- * @param size.
- */
- void set_type_length(uint8_t size) {
- typeLength = size;
- }
-
- /**
- * Get the type length.
- * @return type length
- */
- uint8_t get_type_length() const {
- return typeLength;
- }
-
- /**
- * Set the id length.
- * @param size.
- */
- void set_id_length(uint8_t size) {
- if (size!=0) {
- idLength = size;
- set_IL(true);
- } else {
- set_IL(false);
- }
- }
-
- /**
- * Get the id length.
- * @return id length
- */
- uint8_t get_id_length() const {
- return idLength;
- }
-
- /**
- * Get the number of bytes needed to store this record.
- * @return 3 or 6
- */
- uint16_t get_record_length() const {
- return (get_SR() ? 3 : 6) + (get_IL() ? idLength : 0)+typeLength + payloadLength;
- }
-
- /**
- * Store the header information in the buffer.
- * @param[out] outBuffer Buffer to write the header into.
- * @return number of write bytes
- */
- uint8_t write_header(uint8_t *outBuffer) const {
-
- uint32_t index = 0;
-
- outBuffer[index++] = headerFlags;
- outBuffer[index++] = typeLength;
- if (get_SR()) {
- outBuffer[index++] = (uint8_t) payloadLength;
- } else {
- outBuffer[index++] = (uint8_t) ((payloadLength & 0xFF000000)
- >> 24);
- outBuffer[index++] = (uint8_t) ((payloadLength & 0x00FF0000)
- >> 16);
- outBuffer[index++] = (uint8_t) ((payloadLength & 0x0000FF00)
- >> 8);
- outBuffer[index++] = (uint8_t) (payloadLength & 0x000000FF);
- } //if-else
- if (get_IL()) {
- outBuffer[index++] =idLength;
- }
-
- return index;
- } //writeHeader
-
- /**
- * Load an header from a buffer.
- * @param buffer Buffer to load the header from.
- * @return number of read bytes
- */
- uint16_t load_header(const uint8_t * const buffer) {
- uint32_t index = 0;
- headerFlags = buffer[index++];
- typeLength = buffer[index++];
- if (get_SR()) {
- payloadLength = buffer[index++];
- } else {
- payloadLength = (((uint32_t) buffer[index + 0]) << 24)
- | (((uint32_t) buffer[index + 1]) << 16)
- | (((uint32_t) buffer[index + 2]) << 8)
- | ((uint32_t) buffer[index + 3]);
- index += 4;
- } //if-else
- if (get_IL()) {
- idLength = buffer[index++];
- } else {
- idLength = 0;
- }
-
- return index;
- } //loadHeader
-
- /**
- * Equal operator.
- * @param other Other object to compare with.
- * @return true if the two record headers are equal
- */
- bool operator==(const RecordHeader &other) const{
- return (headerFlags==other.headerFlags) &&
- (typeLength==other.typeLength) &&
- (payloadLength==other.payloadLength);
- }
-
- bool operator!=(const RecordHeader &other) const{
- return !(*this==other);
- }
-
-private:
- uint8_t idLength;
- uint8_t headerFlags;
- uint8_t typeLength;
- uint32_t payloadLength;
-};
-
-} /* namespace NDefLib */
-
-#endif /* NDEFLIB_RECORDHEADER_H_ */
-
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- a/NDefLib/RecordType.lib Sun Dec 10 17:17:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://os.mbed.com/users/DuyLionTran/code/RecordType/#51d7bdf88981
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Sensor/ReadSensor.cpp Tue Dec 12 15:58:44 2017 +0000
@@ -0,0 +1,29 @@
+#include "mbed.h"
+#include "ReadSensor.h"
+
+const float saturationValueTab[41] = { //saturation dissolved oxygen concentrations at various temperatures
+14.46, 14.22, 13.82, 13.44, 13.09,
+12.74, 12.42, 12.11, 11.81, 11.53,
+11.26, 11.01, 10.77, 10.53, 10.30,
+10.08, 9.86, 9.66, 9.46, 9.27,
+9.08, 8.90, 8.73, 8.57, 8.41,
+8.25, 8.11, 7.96, 7.82, 7.69,
+7.56, 7.43, 7.30, 7.18, 7.07,
+6.95, 6.84, 6.73, 6.63, 6.53,
+6.41,
+};
+
+float saturationDoVoltage;
+float saturationDoTemperature;
+float averageVoltage;
+
+AnalogIn phSensor(SENSOR_1_PIN);
+AnalogIn DOSensor(SENSOR_2_PIN);
+
+void SENSOR_Calib() {
+
+}
+
+float SENSOR_ReadPHValue() {
+ return phSensor.read();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/ReadSensor.h Tue Dec 12 15:58:44 2017 +0000 @@ -0,0 +1,18 @@ +#ifndef __READSENSOR_H__ +#define __READSENSOR_H__ + +#define SENSOR_1_PIN (A0) +#define SENSOR_2_PIN (A1) +#define SENSOR_3_PIN (A3) +#define SENSOR_4_PIN (A4) + +#define SaturationDoVoltageAddress 12 //the address of the Saturation Oxygen voltage stored in the Flash +#define SaturationDoTemperatureAddress 16 //the address of the Saturation Oxygen temperature stored in the Flash + +#define VREF 3.3 +#define SCOUNT 30 + +void SENSOR_Calib(); +float SENSOR_ReadPHValue(); + +#endif /* __READSENSOR_H__ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SimpleMQTT.cpp Tue Dec 12 15:58:44 2017 +0000 @@ -0,0 +1,3 @@ +#include "SimpleMQTT.h" + +#include "mbed.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SimpleMQTT.h Tue Dec 12 15:58:44 2017 +0000 @@ -0,0 +1,4 @@ +#ifndef __SIMPLEMQTT_H__ +#define __SIMPLEMQTT_H__ + +#endif /* __SIMPLEMQTT_H__ */ \ No newline at end of file
--- a/easy-connect.lib Sun Dec 10 17:17:41 2017 +0000 +++ b/easy-connect.lib Tue Dec 12 15:58:44 2017 +0000 @@ -1,1 +1,1 @@ -https://os.mbed.com/users/DuyLionTran/code/easy-connect/#c9094fbda0bd +easy-connect#9fa9929d1a8c
--- a/main.cpp Sun Dec 10 17:17:41 2017 +0000
+++ b/main.cpp Tue Dec 12 15:58:44 2017 +0000
@@ -8,6 +8,8 @@
#include "NDefLib/RecordType/RecordURI.h"
#include "MQTTNetwork.h"
#include "MQTTmbed.h"
+#include "ReadSensor.h"
+#include "SimpleMQTT.h"
/***************************************************************
* Definitions
@@ -17,17 +19,14 @@
#define ID MQTT_DEVICE_ID // For a registered connection is your device id
#define AUTH_TOKEN MQTT_DEVICE_PASSWORD // For a registered connection is a device auth-token
#define DEFAULT_TYPE_NAME MQTT_DEVICE_TYPE // For a registered connection is device type
+#define AUTH_METHOD MQTT_USERNAME
-#define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
-#define IBM_IOT_PORT MQTT_PORT
+#define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
+#define IBM_IOT_PORT MQTT_PORT
#define MQTT_MAX_PACKET_SIZE 400
#define MQTT_MAX_PAYLOAD_SIZE 300
-#define SENSOR_1_PIN (A0)
-#define SENSOR_2_PIN (A1)
-#define SENSOR_3_PIN (A3)
-#define SENSOR_4_PIN (A4)
#define RELAY_1_PIN (D11)
#define RELAY_2_PIN (D12)
@@ -64,37 +63,34 @@
static Serial pc(SERIAL_TX, SERIAL_RX);
DigitalOut myled(LED1);
-AnalogIn phSensor(SENSOR_1_PIN);
-AnalogIn DOSensor(SENSOR_2_PIN);
Timer timer;
/***************************************************************
* Unity function definitions
***************************************************************/
-void subscribe_cb(MQTT::MessageData & msgMQTT);
-int subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client);
-int connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
-int getConnTimeout(int attemptNumber);
-void attemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
-int publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client);
-void getADC();
+void MQTT_SubscribeCallback(MQTT::MessageData & msgMQTT);
+int MQTT_Subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client);
+int MQTT_Connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
+int MQTT_GetConnTimeout(int attemptNumber);
+void MQTT_AttemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network);
+int MQTT_Publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime);
/***************************************************************
* Unity function declarations
***************************************************************/
-void subscribe_cb(MQTT::MessageData & msgMQTT) {
+void MQTT_SubscribeCallback(MQTT::MessageData & msgMQTT) {
char msg[MQTT_MAX_PAYLOAD_SIZE];
msg[0]='\0';
strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
- printf ("--->>> subscribe_cb msg: %s\n\r", msg);
+ printf ("--->>> MQTT_SubscribeCallback msg: %s\n\r", msg);
}
-int subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client) {
- return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
+int MQTT_Subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client) {
+ return client->subscribe(pubTopic, MQTT::QOS1, MQTT_SubscribeCallback);
}
-int connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
+int MQTT_Connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
const char* iot_ibm = MQTT_BROKER_URL;
char hostname[strlen(org) + strlen(iot_ibm) + 1];
@@ -109,9 +105,6 @@
LOG("Nucleo IP ADDRESS: %s\n\r", network->get_ip_address());
LOG("Nucleo MAC ADDRESS: %s\n\r", network->get_mac_address());
LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT);
-// for(int i = 0; clientId[i]; i++){ // set lowercase mac
-// clientId[i] = tolower(clientId[i]);
-// }
LOG("Client ID: %s\n\r", clientId);
LOG("Topic: %s\n\r",MQTT_EVENT_TOPIC);
LOG("Subscription URL: %s\n\r", subscription_url);
@@ -134,7 +127,7 @@
data.struct_version = 0;
data.clientID.cstring = clientId;
data.keepAliveInterval = MQTT_KEEPALIVE; // in Sec
- data.username.cstring = "use-token-auth";
+ data.username.cstring = AUTH_METHOD;
data.password.cstring = auth_token;
printf ("AutToken: %s\n\r", auth_token);
@@ -145,7 +138,7 @@
}
connected = true;
printf ("--->MQTT Connected\n\r");
- if ((rc=subscribe(topicCMD, client)) == 0) {
+ if ((rc = MQTT_Subscribe(topicCMD, client)) == 0) {
LOG ("--->>>MQTT subscribed to: %s\n\r", topicCMD);
} else {
LOG ("--->>>ERROR MQTT subscribe : %s\n\r", topicCMD);
@@ -156,25 +149,25 @@
}
-int getConnTimeout(int attemptNumber) { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
+int MQTT_GetConnTimeout(int attemptNumber) { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
// after 20 attempts, retry every 10 minutes
return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
}
-void attemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
+void MQTT_AttemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) {
connected = false;
- while (connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED) {
+ while (MQTT_Connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED) {
if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);
return; // don't reattempt to connect if credentials are wrong
}
- int timeout = getConnTimeout(++retryAttempt);
+ int timeout = MQTT_GetConnTimeout(++retryAttempt);
WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
// if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
- // or maybe just add the proper members to do this disconnect and call attemptConnect(...)
+ // or maybe just add the proper members to do this disconnect and call MQTT_AttemptConnect(...)
// this works - reset the system when the retry count gets to a threshold
if (retryAttempt == 5)
NVIC_SystemReset();
@@ -183,23 +176,21 @@
}
}
-int publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime) {
+int MQTT_Publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, time_t inputTime) {
MQTT::Message message;
const char* pubTopic = MQTT_EVENT_TOPIC;
char buf[MQTT_MAX_PAYLOAD_SIZE];
char timeBuf[50];
- float adc0;
if (!client->isConnected()) {
printf ("---> MQTT DISCONNECTED\n\r"); return MQTT::FAILURE;
}
- adc0 = ADC_PHVal;
strftime(timeBuf, 50, "%Y/%m/%d %H:%M:%S", localtime(&inputTime));
sprintf(buf,
"{\"Project\":\"%s\",\"Time\":\"%s\",\"Type\":1,\"cmdID\":%d,\"ADC0\":%0.4f}",
- projectName, timeBuf, cmdID, adc0);
+ projectName, timeBuf, cmdID, ADC_PHVal);
message.qos = MQTT::QOS0;
message.retained = false;
message.dup = false;
@@ -213,11 +204,6 @@
return client->publish(pubTopic, message);
}
-void getADC() {
- ADC_PHVal = phSensor.read();
-// ADC_DOVal = DOSensor.read();
-// voltageValue = (ADC_PHVal * 5.0);
-}
/***************************************************************
* Main
***************************************************************/
@@ -238,7 +224,7 @@
MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork);
printf ("ATTEMPT CONNECT\n\r");
- attemptConnect(&client, &mqttNetwork, network);
+ MQTT_AttemptConnect(&client, &mqttNetwork, network);
if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
printf ("---ERROR line : %d\n\r", __LINE__);
while (true)
@@ -248,14 +234,14 @@
myled=1;
while (true) {
time_t seconds = time(NULL);
- getADC();
+ ADC_PHVal = SENSOR_ReadPHValue();
if (connected == true) {
if ((uint32_t)(timer.read() - lastRead) >= uploadInterval) { // Publish a message every 3 second
- if (publish(&client, seconds) != MQTT::SUCCESS) {
+ if (MQTT_Publish(&client, seconds) != MQTT::SUCCESS) {
myled=0;
client.disconnect();
mqttNetwork.disconnect();
- attemptConnect(&client, &mqttNetwork, network); // if we have lost the connection
+ MQTT_AttemptConnect(&client, &mqttNetwork, network); // if we have lost the connection
} else {
myled = 1;
cmdID++;