Duy_new_test_Water_Monitor

Dependencies:   MQTT NDefLib

Fork of Cloud_IBM_MbedOS by ST

main.cpp

Committer:
DuyLionTran
Date:
2017-12-05
Revision:
3:e1f6c5af437e
Parent:
2:e3846f091b6b

File content as of revision 3:e1f6c5af437e:

/* SpwfInterface NetworkSocketAPI Example Program
 * Copyright (c) 2015 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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


//------------------------------------
// Hyperterminal configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------
static Serial pc(SERIAL_TX, SERIAL_RX); 
static DigitalOut myled(LED1);
static bool quickstartMode = false;      // set to false to connect with authentication tocken
static bool BlueButtonToggle = false;  

//#define ORG_QUICKSTART           // comment to connect to play.internetofthings.ibmcloud.com
#define SUBSCRIBE              // uncomment to subscribe to broker msgs (not to be used with IBM broker) 
//#define X_NUCLEO_NFC01A1_PRESENT // uncomment to add NFC support
    
#define MQTT_MAX_PACKET_SIZE 400   
#define MQTT_MAX_PAYLOAD_SIZE 300 

 // Configuration values needed to connect to IBM IoT Cloud
#ifdef ORG_QUICKSTART
#define ORG "a4nvkh"     // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org 
#define ID ""
#define AUTH_TOKEN ""
#define DEFAULT_TYPE_NAME "iotsample-mbed-Nucleo"
#else   // not def ORG_QUICKSTART
#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
#endif

#define TYPE DEFAULT_TYPE_NAME       // For a registered connection, replace with your type
#define IBM_IOT_PORT MQTT_PORT
    
static char id[30] = ID;                 // mac without colons  
static char org[12] = ORG;        
static int connack_rc = 0; // MQTT connack return code
static char type[30] = TYPE;
static char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
static bool netConnecting = false;
static int connectTimeout = 1000;
static bool mqttConnecting = false;
static bool netConnected = false;
static bool connected = false;
static int retryAttempt = 0;
static char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
char topicCMD[]   = "iot-2/cmd/command/fmt/json";

//static LPS22HBSensor *pressure_sensor;
//static HTS221Sensor  *humidity_sensor;
//static HTS221Sensor  *temp_sensor1;

//#ifndef TARGET_SENSOR_TILE
static void BlueButtonPressed ()
{
	BlueButtonToggle = true;	
}
//#endif

#ifdef SUBSCRIBE
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);
}
#endif

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_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
    if (!quickstartMode) 
    {        
        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"); 
#ifdef SUBSCRIBE
//		    int rc=0;
        if ((rc=subscribe(topicCMD, client)) == 0) { 
        	LOG ("--->>>MQTT subscribed to: %s\n\r",topicCMD);
        }
		else {
			LOG ("--->>>ERROR MQTT subscribe : %s\n\r",topicCMD);
		}
#endif    
    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)
{
    MQTT::Message message;
    const char* pubTopic = MQTT_TOPIC;
            
    char buf[MQTT_MAX_PAYLOAD_SIZE];
    float temp, press, hum;

	if (!client->isConnected()) { printf ("---> MQTT DISCONNECTED\n\r"); return MQTT::FAILURE; }
//    temp_sensor1->get_temperature(&temp);
//    pressure_sensor->get_pressure(&press);
//    humidity_sensor->get_humidity(&hum);
	temp = 17.7;
	press = 70.7;
	hum = 80.9;
    sprintf(buf,
     "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
              temp, press, hum);
    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);    
}
 
int main()
{   
//   myled=0;
//   DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL);
//   i2c->frequency(400000);    
//	
//   XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(i2c);   
//   pressure_sensor = mems_expansion_board->pt_sensor;
//   temp_sensor1 = mems_expansion_board->ht_sensor;  
//   humidity_sensor = mems_expansion_board->ht_sensor; 
//   pressure_sensor->enable();
//   temp_sensor1->enable();
//   humidity_sensor->enable();
    
//#if !defined (TARGET_SENSOR_TILE)
//    InterruptIn BlueButton(USER_BUTTON);    
//    BlueButton.fall(&BlueButtonPressed);
	BlueButtonToggle = false;
//#endif    
   pc.baud(115200);
   pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n");     
   pc.printf("\r\nconnecting to AP\r\n");            

   quickstartMode=false;
   if (strcmp(org, "quickstart") == 0){quickstartMode = true;}
   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);
		
   if (quickstartMode){
       char mac[50];  // remove all : from mac
       char *digit=NULL;
       sprintf (id,"%s", "");                
       sprintf (mac,"%s",network->get_mac_address()); 
       digit = strtok (mac,":");
       while (digit != NULL)
       {
           strcat (id, digit);
           digit = strtok (NULL, ":");
       }     
   }
   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
   }
#ifdef X_NUCLEO_NFC01A1_PRESENT      
   // program NFC with broker URL        
   XNucleoNFC01A1 *nfcNucleo = XNucleoNFC01A1::instance(*i2c, NULL, XNucleoNFC01A1::DEFAULT_GPO_PIN, XNucleoNFC01A1::DEFAULT_RF_DISABLE_PIN, NC,NC,NC);  
   NDefLib::NDefNfcTag& tag = nfcNucleo->get_M24SR().get_NDef_tag();
   printf("NFC Init done: !\r\n");
   //open the i2c session with the nfc chip
   if(tag.open_session()){
       //create the NDef message and record
       NDefLib::Message msg;
       NDefLib::RecordURI rUri(NDefLib::RecordURI::HTTPS, subscription_url);
       msg.add_record(&rUri);
       //write the tag
       if(tag.write(msg)){
           printf("Tag writed \r\n");
       }
       //close the i2c session
       if(!tag.close_session()){
           printf("Error Closing the session\r\n");
       }
   }else printf("Error open Session\r\n");             
#endif    
   myled=1;         
   int count = 0;    
   while (true)
   {
	if (BlueButtonToggle == false && connected == true) {
       if (++count == 6)
       {               // Publish a message every 3 second
    	if (publish(&client) != MQTT::SUCCESS) { 
        	myled=0;
			count=0;
            client.disconnect();
			mqttNetwork.disconnect();			   
            attemptConnect(&client, &mqttNetwork, network);   // if we have lost the connection                
        } else {					 
			myled=1;
            count=0;
		}
       }        
       client.yield(500);  // allow the MQTT client to receive subscribe messages and manage keep alive
	} else if (BlueButtonToggle == true && connected == true){   // disconnect MQTT
		printf ("--->> Disconnect\n\r");
       	connected = false;
		count = 0;
		BlueButtonToggle = false;
#ifdef SUBSCRIBE			 
  //			 unsubscribe(const char* topicFilter);   // unsubscribe if subscribed
#endif			 
			 client.disconnect();
			 mqttNetwork.disconnect();
		 } else if (BlueButtonToggle == true && connected == false) {
			 connected = true;
			 BlueButtonToggle = false;
	 } else wait (0.5);
   }
}