Duy tran / Mbed OS iot_water_monitor_v2

Dependencies:   easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code

main.cpp

Committer:
DuyLionTran
Date:
2017-12-10
Revision:
14:0129ac8844ee
Parent:
13:344a5e2b2f53
Child:
15:7ba48f016569

File content as of revision 14:0129ac8844ee:

/***************************************************************
 * Includes
 ***************************************************************/
#include "mbed.h"
#include "easy-connect.h"
#include "MQTTClient.h"
#include "NDefLib/NDefNfcTag.h"
#include "NDefLib/RecordType/RecordURI.h"
#include "MQTTNetwork.h"
#include "MQTTmbed.h"

/***************************************************************
 * Definitions
 ***************************************************************/
// Configuration values needed to connect to IBM IoT Cloud
#define ORG               	MQTT_ORG_ID            	// connect to ORG.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
#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 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)

/***************************************************************
 * Variables
 ***************************************************************/
char       *projectName     = "WaterMonitor";
uint16_t    cmdID           = 0;
uint32_t 	lastRead        = 0;
uint32_t    uploadInterval  = 5;

/* MQTT Varialbles */ 
static char id[30] 			= ID;               // mac without colons  
static char org[12] 		= ORG;        
static char type[30] 		= TYPE;
static char auth_token[30] 	= AUTH_TOKEN; 		// Auth_token is only used in non-quickstart mode
static int 	connack_rc 		= 0; 				// MQTT connack return code
static bool netConnecting 	= false;
static bool mqttConnecting 	= false;
static bool netConnected 	= false;
static bool connected 		= false;
static int 	retryAttempt 	= 0;
static int 	connectTimeout 	= 1000;
static char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
char 		topicCMD[]   	= "iot-2/cmd/command/fmt/json";

/* Analog Handles */
float ADC_PHVal;
float ADC_DOVal;

/***************************************************************
 * Structs/Classess
 ***************************************************************/
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();

/***************************************************************
 * Unity function declarations
 ***************************************************************/ 
void subscribe_cb(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);
}

int subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client) {
    return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
}

int 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];
    
    sprintf(hostname, "%s%s", org, iot_ibm);
    // Construct clientId - d:org:type:id
    char clientId[strlen(org) + strlen(type) + strlen(id) + 5];  
    sprintf(clientId, "d:%s:%s:%s", org, type, id);  
    sprintf(subscription_url, "%s.%s/#/device/%s/%s/", org, "internetofthings.ibmcloud.com", id, DEFAULT_TYPE_NAME);

    // Network debug statements 
    LOG("=====================================\n\r");
    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);
    LOG("=====================================\n\r");    
    netConnecting = true;
    int rc = mqttNetwork->connect(hostname, IBM_IOT_PORT);
    if (rc != 0) {
        printf("rc from TCP connect is %d\r\n", rc);
        return rc;
    }
    
    printf ("--->TCP Connected\n\r");
    netConnected 	= true;
    netConnecting 	= false;		
		
    // MQTT Connect
    mqttConnecting = true;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.MQTTVersion 			= 4;
    data.struct_version 		= 0;
    data.clientID.cstring 		= clientId; 
	data.keepAliveInterval 		= MQTT_KEEPALIVE;  // in Sec   
    data.username.cstring 		= "use-token-auth";
    data.password.cstring 		= auth_token;
    printf ("AutToken: %s\n\r", auth_token);
       
    if ((rc = client->connect(data)) != 0) {
        printf("rc from MQTT connect is %d\r\n", rc);
        connack_rc = rc;
        return rc;
    }
    connected = true;
    printf ("--->MQTT Connected\n\r"); 
    if ((rc=subscribe(topicCMD, client)) == 0) { 
       	LOG ("--->>>MQTT subscribed to: %s\n\r", topicCMD);
    } else {
		LOG ("--->>>ERROR MQTT subscribe : %s\n\r", topicCMD);
	}  
    mqttConnecting = false;
    connack_rc = rc;
    return rc;       
}


int 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) {
    connected = false;
           
    while (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);
        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(...)        
        // this works - reset the system when the retry count gets to a threshold
        if (retryAttempt == 5)
            NVIC_SystemReset(); 
        else
            wait(timeout);
    }    
}

int 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);
    message.qos        = MQTT::QOS0;
    message.retained   = false;
    message.dup        = false;
    message.payload    = (void*)buf;
    message.payloadlen = strlen(buf);

    if((message.payloadlen + strlen(pubTopic)+1) >= MQTT_MAX_PACKET_SIZE)
        printf("message too long!\r\n");
    
    LOG("Publishing %s\n\r", buf);
    return client->publish(pubTopic, message);    
}

void getADC() {
    ADC_PHVal    = phSensor.read();
//    ADC_DOVal    = DOSensor.read();
//    voltageValue = (ADC_PHVal * 5.0);  
}
/***************************************************************
 * Main
 ***************************************************************/ 
int main() {   
   pc.baud(115200);
   timer.start();
   lastRead = 0;
//   set_time(1512950250);
   pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n");     
   pc.printf("\r\nconnecting to AP\r\n");            

   NetworkInterface* network = easy_connect(true);
   if (!network) {
       printf ("Error easy_connect\n\r");
       return -1;
   } 
   MQTTNetwork mqttNetwork(network);	
   MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork);
		
   printf ("ATTEMPT CONNECT\n\r");
   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)
       wait(1.0); // Permanent failures - don't retry
   }

   myled=1;          
	while (true) {
		time_t seconds = time(NULL);
		getADC();
		if (connected == true) {
	       	if ((uint32_t)(timer.read() - lastRead) >= uploadInterval) {               // Publish a message every 3 second
	    		if (publish(&client, seconds) != MQTT::SUCCESS) {    			 
	        		myled=0;
	            	client.disconnect();
					mqttNetwork.disconnect();			   
	            	attemptConnect(&client, &mqttNetwork, network);   // if we have lost the connection                
	        	} else {					 
					myled = 1;
	            	cmdID++;
				}
			lastRead = timer.read();
	    	}        
	    	client.yield(500);  // allow the MQTT client to receive subscribe messages and manage keep alive
		} else if (connected == false) {
			connected = true;
		} else {
			wait(0.5);
		}
	}
}