elementzonline / SIM800_MQTT

Visit our blog/website for more information
http://www.elementzonline.com
GNU General Public License v3.0
171 stars 95 forks source link

Doesn't work if the Serial ports are changed #5

Closed solankigithub closed 4 years ago

solankigithub commented 8 years ago

Hi, First of all, a wonderful job for creating such library. Issue: When i look into the source, "Serial" (Hardware Serial) has been used to communicate with the SIM800 modem and mySerial has been used to print the output.

I am using MEGA, where i need to use "Serial1" to communicate with SIM800 and "Serial" to print the output. So i replaced the occurrence of "Serial" with "Serial1" and "mySerial" with "Serial". I didn't change any other code. The library is not working anymore.. Can you please help to make it little flexible with respect to choosing the serial ports.

nithinkurian commented 8 years ago

You have to replace occurrence of "SerialEvent" with "SerialEvent1". I think this will solve your problem.

solankigithub commented 8 years ago

Thanks Nithin, I changed the occurrence of serialEvent() to serialEvent1(). It's still not working and giving the below response on the Serial port.

AT

OK
+++AT
ATE1

OK

OK
AT+CREG?

+CREG: 0,1

OK
AT+CIPMUX=0
AT+CIPMODE=1

OK

OK
AT+CGATT?

+CGATT: 0

OK

Call Ready
AT+CGATT=1

OK
AT+CIPSTATUS

OK

STATE: IP INITIAL

SMS Ready
AT+CSTT="AIRTELGPRS.COM"

OK
AT+CIPSTATUS

OK

STATE: IP START
AT+CIICR

OK
AT+CIPSTATUS

OK

STATE: IP GPRSACT
AT+CIFSR

106.218.239.147
AT+CIPSTATUS

OK

STATE: IP STATUS
AT+CIPSTART="TCP","broker.mqttdashboard.com","1883"

OK
AT+CIPSTATUS

OK

STATE: TCP CONNECTING

CONNECT
MQTT.TCP_Flag = True
2
2
Connect Acknowledgment

0
0
PING Response

0
0
PING Response
solankigithub commented 8 years ago

This is my arduino main program

`
#include "GSM_MQTT.h"
#include <SoftwareSerial.h>
String MQTT_HOST = "broker.mqttdashboard.com";
/*
   MQTT host address
*/
String MQTT_PORT = "1883";
/*
   MQTT port
*/
SoftwareSerial mySerial(10, 11); // RX, TX
/*
   Software Serial through which mqtt events log is printed at 9600 baud rate
*/
void GSM_MQTT::AutoConnect(void)
{
  /*
     Use this function if you want to use autoconnect(and auto reconnect) facility
     This function is called whenever TCP connection is established (or re-established).
     put your connect codes here.
  */
  connect("clientId-i8ZSXDfphz", 0, 0, "", "", 1, 0, 0, 0, "", "");
  /*    void connect(char *ClientIdentifier, char UserNameFlag, char PasswordFlag, char *UserName, char *Password, char CleanSession, char WillFlag, char WillQoS, char WillRetain, char *WillTopic, char *WillMessage);
          ClientIdentifier  :Is a string that uniquely identifies the client to the server.
                            :It must be unique across all clients connecting to a single server.(So it will be better for you to change that).
                            :It's length must be greater than 0 and less than 24
                            :Example "qwerty"
          UserNameFlag      :Indicates whether UserName is present
                            :Possible values (0,1)
                            :Default value 0 (Disabled)
          PasswordFlag      :Valid only when  UserNameFlag is 1, otherwise its value is disregarded.
                            :Indicates whether Password is present
                            :Possible values (0,1)
                            :Default value 0 (Disabled)
          UserName          :Mandatory when UserNameFlag is 1, otherwise its value is disregarded.
                            :The UserName corresponding to the user who is connecting, which can be used for authentication.
          Password          :alid only when  UserNameFlag and PasswordFlag are 1 , otherwise its value is disregarded.
                            :The password corresponding to the user who is connecting, which can be used for authentication.
          CleanSession      :If not set (0), then the server must store the subscriptions of the client after it disconnects.
                            :If set (1), then the server must discard any previously maintained information about the client and treat the connection as "clean".
                            :Possible values (0,1)
                            :Default value 1
          WillFlag          :This flag determines whether a WillMessage published on behalf of the client when client is disconnected involuntarily.
                            :If the WillFlag is set, the WillQoS, WillRetain, WillTopic, WilMessage fields are valid.
                            :Possible values (0,1)
                            :Default value 0 (Disables will Message)
          WillQoS           :Valid only when  WillFlag is 1, otherwise its value is disregarded.
                            :Determines the QoS level of WillMessage
                            :Possible values (0,1,2)
                            :Default value 0 (QoS 0)
          WillRetain        :Valid only when  WillFlag is 1, otherwise its value is disregarded.
                            :Determines whether the server should retain the Will message.
                            :Possible values (0,1)
                            :Default value 0
          WillTopic         :Mandatory when  WillFlag is 1, otherwise its value is disregarded.
                            :The Will Message will published to this topic (WillTopic) in case of involuntary client disconnection.
          WillMessage       :Mandatory when  WillFlag is 1, otherwise its value is disregarded.
                            :This message (WillMessage) will published to WillTopic in case of involuntary client disconnection.
  */

}
void GSM_MQTT::OnConnect(void)
{
  /*
     This function is called when mqqt connection is established.
     put your subscription publish codes here.
  */
  subscribe(0, _generateMessageID(), "sandeepsolanki/s", 2);
  /*    void subscribe(char DUP, unsigned int MessageID, char *SubTopic, char SubQoS);
          DUP       :This flag is set when the client or server attempts to re-deliver a SUBSCRIBE message
                    :This applies to messages where the value of QoS is greater than zero (0)
                    :Possible values (0,1)
                    :Default value 0
          Message ID:The Message Identifier (Message ID) field
                    :Used only in messages where the QoS levels greater than 0 (SUBSCRIBE message is at QoS =1)
          SubTopic  :Topic names to which  subscription is needed
          SubQoS    :QoS level at which the client wants to receive messages
                    :Possible values (0,1,2)
                    :Default value 0
  */

  publish(0, 0, 0, _generateMessageID(), "sandeepsolanki/s", "Hello MQTT Broker, How are you?");
  /*  void publish(char DUP, char Qos, char RETAIN, unsigned int MessageID, char *Topic, char *Message);
      DUP       :This flag is set when the client or server attempts to re-deliver a PUBLISH message
                :This applies to messages where the value of QoS is greater than zero (0)
                :Possible values (0,1)
                :Default value 0
      QoS       :Quality of Service
                :This flag indicates the level of assurance for delivery of a PUBLISH message
                :Possible values (0,1,2)
                :Default value 0
      RETAIN    :if the Retain flag is set (1), the server should hold on to the message after it has been delivered to the current subscribers.
                :When a new subscription is established on a topic, the last retained message on that topic is sent to the subscriber
                :Possible values (0,1)
                :Default value 0
      Message ID:The Message Identifier (Message ID) field
                :Used only in messages where the QoS levels greater than 0
      Topic     :Publishing topic
      Message   :Publishing Message
  */
}
void GSM_MQTT::OnMessage(char *Topic, int TopicLength, char *Message, int MessageLength)
{
  /*
    This function is called whenever a message received from subscribed topics
    put your subscription publish codes here.
  */

  /*
     Topic        :Name of the topic from which message is coming
     TopicLength  :Number of characters in topic name
     Message      :The containing array
     MessageLength:Number of characters in message
  */
  Serial.println(TopicLength);
  Serial.println(Topic);
  Serial.println(MessageLength);
  Serial.println(Message);

}
GSM_MQTT MQTT(20);
/*
   20 is the keepalive duration in seconds
*/

void setup()
{
  MQTT.begin();

  /*
     You can write your code here
  */

}

void loop()
{

  /*
     You can write your code here
  */
  if (MQTT.available())
  { 
    Serial.println("MQTT AVAILABLE");

    /*
      if you want to do something when mqtt connection is live.
      You can write your code here
    */
  }

  MQTT.processing();
}

`

solankigithub commented 8 years ago

This is my GSM_MQTT.cpp


/*
  MQTT.h - Library for GSM MQTT Client.
  Created by Nithin K. Kurian, Dhanish Vijayan, Elementz Engineers Guild Pvt. Ltd, July 2, 2016.
  Released into the public domain.
*/

#include "GSM_MQTT.h"
#include "Arduino.h"
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
extern uint8_t GSM_Response;

extern SoftwareSerial mySerial;
extern String MQTT_HOST;
extern String MQTT_PORT;

extern GSM_MQTT MQTT;
uint8_t GSM_Response = 0;
unsigned long previousMillis = 0;
//char inputString[UART_BUFFER_LENGTH];         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
void serialEvent1();
GSM_MQTT::GSM_MQTT(unsigned long KeepAlive)
{
  _KeepAliveTimeOut = KeepAlive;
}

void GSM_MQTT::begin(void)
{
  Serial.begin(2400);
  Serial1.begin(2400);
  Serial1.write("AT\r\n");
  delay(1000);
  _tcpInit();
}
char GSM_MQTT::_sendAT(char *command, unsigned long waitms)
{
  unsigned long PrevMillis = millis();
  strcpy(reply, "none");
  GSM_Response = 0;
  Serial1.write(command);
  unsigned long currentMillis = millis();
  //  Serial.println(PrevMillis);
  //  Serial.println(currentMillis);
  while ( (GSM_Response == 0) && ((currentMillis - PrevMillis) < waitms) )
  {
    //    delay(1);
    serialEvent1();
    currentMillis = millis();
  }
  return GSM_Response;
}
char GSM_MQTT::sendATreply(char *command, char *replystr, unsigned long waitms)
{
  strcpy(reply, replystr);
  unsigned long PrevMillis = millis();
  GSM_ReplyFlag = 0;
  Serial1.write(command);
  unsigned long currentMillis = millis();

  //  Serial.println(PrevMillis);
  //  Serial.println(currentMillis);
  while ( (GSM_ReplyFlag == 0) && ((currentMillis - PrevMillis) < waitms) )
  {
    //    delay(1);
    serialEvent1();
    currentMillis = millis();
  }
  return GSM_ReplyFlag;
}
void GSM_MQTT::_tcpInit(void)
{
  switch (modemStatus)
  {
    case 0:
      {
        delay(1000);
        Serial1.print("+++");
        delay(500);
        if (_sendAT("AT\r\n", 5000) == 1)
        {
          modemStatus = 1;
        }
        else
        {
          modemStatus = 0;
          break;
        }
      }
    case 1:
      {
        if (_sendAT("ATE1\r\n", 2000) == 1)
        {
          modemStatus = 2;
        }
        else
        {
          modemStatus = 1;
          break;
        }
      }
    case 2:
      {
        if (sendATreply("AT+CREG?\r\n", "0,1", 5000) == 1)
        {
          _sendAT("AT+CIPMUX=0\r\n", 2000);
          _sendAT("AT+CIPMODE=1\r\n", 2000);
          if (sendATreply("AT+CGATT?\r\n", ": 1", 4000) != 1)
          {
            _sendAT("AT+CGATT=1\r\n", 2000);
          }
          modemStatus = 3;
          _tcpStatus = 2;
        }
        else
        {
          modemStatus = 2;
          break;
        }
      }
    case 3:
      {
        if (GSM_ReplyFlag != 7)
        {
          _tcpStatus = sendATreply("AT+CIPSTATUS\r\n", "STATE", 4000);
          if (_tcpStatusPrev == _tcpStatus)
          {
            tcpATerrorcount++;
            if (tcpATerrorcount >= 10)
            {
              tcpATerrorcount = 0;
              _tcpStatus = 7;
            }

          }
          else
          {
            _tcpStatusPrev = _tcpStatus;
            tcpATerrorcount = 0;
          }
        }
        _tcpStatusPrev = _tcpStatus;
        Serial.print(_tcpStatus);
        switch (_tcpStatus)
        {
          case 2:
            {
              _sendAT("AT+CSTT=\"AIRTELGPRS.COM\"\r\n", 5000);
              break;
            }
          case 3:
            {
              _sendAT("AT+CIICR\r\n", 5000)  ;
              break;
            }
          case 4:
            {
              sendATreply("AT+CIFSR\r\n", ".", 4000) ;
              break;
            }
          case 5:
            {
              Serial1.print("AT+CIPSTART=\"TCP\",\"");
              Serial1.print(MQTT_HOST);
              Serial1.print("\",\"");
              Serial1.print(MQTT_PORT);
              if (_sendAT("\"\r\n", 5000) == 1)
              {
                unsigned long PrevMillis = millis();
                unsigned long currentMillis = millis();
                while ( (GSM_Response != 4) && ((currentMillis - PrevMillis) < 20000) )
                {
                  //    delay(1);
                  serialEvent1();
                  currentMillis = millis();
                }
              }
              break;
            }
          case 6:
            {
              unsigned long PrevMillis = millis();
              unsigned long currentMillis = millis();
              while ( (GSM_Response != 4) && ((currentMillis - PrevMillis) < 20000) )
              {
                //    delay(1);
                serialEvent1();
                currentMillis = millis();
              }
              break;
            }
          case 7:
            {
              sendATreply("AT+CIPSHUT\r\n", "OK", 4000) ;
              modemStatus = 0;
              _tcpStatus = 2;
              break;
            }
        }
      }
  }

}

void GSM_MQTT::_ping(void)
{

  if (pingFlag == true)
  {
    unsigned long currentMillis = millis();
    if ((currentMillis - _PingPrevMillis ) >= _KeepAliveTimeOut * 1000)
    {
      // save the last time you blinked the LED
      _PingPrevMillis = currentMillis;
      Serial1.print(char(PINGREQ * 16));
      _sendLength(0);
    }
  }
}
void GSM_MQTT::_sendUTFString(char *string)
{
  int localLength = strlen(string);
  Serial1.print(char(localLength / 256));
  Serial1.print(char(localLength % 256));
  Serial1.print(string);
}
void GSM_MQTT::_sendLength(int len)
{
  bool  length_flag = false;
  while (length_flag == false)
  {
    if ((len / 128) > 0)
    {
      Serial1.print(char(len % 128 + 128));
      len /= 128;
    }
    else
    {
      length_flag = true;
      Serial1.print(char(len));
    }
  }
}
void GSM_MQTT::connect(char *ClientIdentifier, char UserNameFlag, char PasswordFlag, char *UserName, char *Password, char CleanSession, char WillFlag, char WillQoS, char WillRetain, char *WillTopic, char *WillMessage)
{
  ConnectionAcknowledgement = NO_ACKNOWLEDGEMENT ;
  Serial1.print(char(CONNECT * 16 ));
  char ProtocolName[7] = "MQIsdp";
  int localLength = (2 + strlen(ProtocolName)) + 1 + 3 + (2 + strlen(ClientIdentifier));
  if (WillFlag != 0)
  {
    localLength = localLength + 2 + strlen(WillTopic) + 2 + strlen(WillMessage);
  }
  if (UserNameFlag != 0)
  {
    localLength = localLength + 2 + strlen(UserName);

    if (PasswordFlag != 0)
    {
      localLength = localLength + 2 + strlen(Password);
    }
  }
  _sendLength(localLength);
  _sendUTFString(ProtocolName);
  Serial1.print(char(_ProtocolVersion));
  Serial1.print(char(UserNameFlag * User_Name_Flag_Mask + PasswordFlag * Password_Flag_Mask + WillRetain * Will_Retain_Mask + WillQoS * Will_QoS_Scale + WillFlag * Will_Flag_Mask + CleanSession * Clean_Session_Mask));
  Serial1.print(char(_KeepAliveTimeOut / 256));
  Serial1.print(char(_KeepAliveTimeOut % 256));
  _sendUTFString(ClientIdentifier);
  if (WillFlag != 0)
  {
    _sendUTFString(WillTopic);
    _sendUTFString(WillMessage);
  }
  if (UserNameFlag != 0)
  {
    _sendUTFString(UserName);
    if (PasswordFlag != 0)
    {
      _sendUTFString(Password);
    }
  }
}
void GSM_MQTT::publish(char DUP, char Qos, char RETAIN, unsigned int MessageID, char *Topic, char *Message)
{
  Serial1.print(char(PUBLISH * 16 + DUP * DUP_Mask + Qos * QoS_Scale + RETAIN));
  int localLength = (2 + strlen(Topic));
  if (Qos > 0)
  {
    localLength += 2;
  }
  localLength += strlen(Message);
  _sendLength(localLength);
  _sendUTFString(Topic);
  if (Qos > 0)
  {
    Serial1.print(char(MessageID / 256));
    Serial1.print(char(MessageID % 256));
  }
  Serial1.print(Message);
}
void GSM_MQTT::publishACK(unsigned int MessageID)
{
  Serial1.print(char(PUBACK * 16));
  _sendLength(2);
  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));
}
void GSM_MQTT::publishREC(unsigned int MessageID)
{
  Serial1.print(char(PUBREC * 16));
  _sendLength(2);
  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));
}
void GSM_MQTT::publishREL(char DUP, unsigned int MessageID)
{
  Serial1.print(char(PUBREL * 16 + DUP * DUP_Mask + 1 * QoS_Scale));
  _sendLength(2);
  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));
}

void GSM_MQTT::publishCOMP(unsigned int MessageID)
{
  Serial1.print(char(PUBCOMP * 16));
  _sendLength(2);
  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));
}
void GSM_MQTT::subscribe(char DUP, unsigned int MessageID, char *SubTopic, char SubQoS)
{
  Serial1.print(char(SUBSCRIBE * 16 + DUP * DUP_Mask + 1 * QoS_Scale));
  int localLength = 2 + (2 + strlen(SubTopic)) + 1;
  _sendLength(localLength);
  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));
  _sendUTFString(SubTopic);
  Serial1.print(SubQoS);

}
void GSM_MQTT::unsubscribe(char DUP, unsigned int MessageID, char *SubTopic)
{
  Serial1.print(char(UNSUBSCRIBE * 16 + DUP * DUP_Mask + 1 * QoS_Scale));
  int localLength = (2 + strlen(SubTopic)) + 2;
  _sendLength(localLength);

  Serial1.print(char(MessageID / 256));
  Serial1.print(char(MessageID % 256));

  _sendUTFString(SubTopic);
}
void GSM_MQTT::disconnect(void)
{
  Serial1.print(char(DISCONNECT * 16));
  _sendLength(0);
  pingFlag = false;
}
//Messages
const char CONNECTMessage[] PROGMEM  = {"Client request to connect to Server\r\n"};
const char CONNACKMessage[] PROGMEM  = {"Connect Acknowledgment\r\n"};
const char PUBLISHMessage[] PROGMEM  = {"Publish message\r\n"};
const char PUBACKMessage[] PROGMEM  = {"Publish Acknowledgment\r\n"};
const char PUBRECMessage[] PROGMEM  = {"Publish Received (assured delivery part 1)\r\n"};
const char PUBRELMessage[] PROGMEM  = {"Publish Release (assured delivery part 2)\r\n"};
const char PUBCOMPMessage[] PROGMEM  = {"Publish Complete (assured delivery part 3)\r\n"};
const char SUBSCRIBEMessage[] PROGMEM  = {"Client Subscribe request\r\n"};
const char SUBACKMessage[] PROGMEM  = {"Subscribe Acknowledgment\r\n"};
const char UNSUBSCRIBEMessage[] PROGMEM  = {"Client Unsubscribe request\r\n"};
const char UNSUBACKMessage[] PROGMEM  = {"Unsubscribe Acknowledgment\r\n"};
const char PINGREQMessage[] PROGMEM  = {"PING Request\r\n"};
const char PINGRESPMessage[] PROGMEM  = {"PING Response\r\n"};
const char DISCONNECTMessage[] PROGMEM  = {"Client is Disconnecting\r\n"};

void GSM_MQTT::printMessageType(uint8_t Message)
{
  switch (Message)
  {
    case CONNECT:
      {
        int k, len = strlen_P(CONNECTMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(CONNECTMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case CONNACK:
      {
        int k, len = strlen_P(CONNACKMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(CONNACKMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case PUBLISH:
      {
        int k, len = strlen_P(PUBLISHMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PUBLISHMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case PUBACK:
      {
        int k, len = strlen_P(PUBACKMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PUBACKMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case  PUBREC:
      {
        int k, len = strlen_P(PUBRECMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PUBRECMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case PUBREL:
      {
        int k, len = strlen_P(PUBRELMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PUBRELMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case PUBCOMP:
      {
        int k, len = strlen_P(PUBCOMPMessage );
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PUBCOMPMessage  + k);
          Serial.print(myChar);
        }
        break;
      }
    case SUBSCRIBE:
      {
        int k, len = strlen_P(SUBSCRIBEMessage );
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(SUBSCRIBEMessage  + k);
          Serial.print(myChar);
        }
        break;
      }
    case SUBACK:
      {
        int k, len = strlen_P(SUBACKMessage );
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(SUBACKMessage  + k);
          Serial.print(myChar);
        }
        break;
      }
    case UNSUBSCRIBE:
      {
        int k, len = strlen_P(UNSUBSCRIBEMessage );
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(UNSUBSCRIBEMessage  + k);
          Serial.print(myChar);
        }
        break;
      }
    case UNSUBACK:
      {
        int k, len = strlen_P(UNSUBACKMessage );
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(UNSUBACKMessage  + k);
          Serial.print(myChar);
        }
        break;
      }
    case PINGREQ:
      {
        int k, len = strlen_P(PINGREQMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PINGREQMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case PINGRESP:
      {
        int k, len = strlen_P(PINGRESPMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(PINGRESPMessage + k);
          Serial.print(myChar);
        }
        break;
      }
    case DISCONNECT:
      {
        int k, len = strlen_P(DISCONNECTMessage);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(DISCONNECTMessage + k);
          Serial.print(myChar);
        }
        break;
      }
  }
}

//Connect Ack
const char ConnectAck0[] PROGMEM  = {"Connection Accepted\r\n"};
const char ConnectAck1[] PROGMEM  = {"Connection Refused: unacceptable protocol version\r\n"};
const char ConnectAck2[] PROGMEM  = {"Connection Refused: identifier rejected\r\n"};
const char ConnectAck3[] PROGMEM  = {"Connection Refused: server unavailable\r\n"};
const char ConnectAck4[] PROGMEM  = {"Connection Refused: bad user name or password\r\n"};
const char ConnectAck5[] PROGMEM  = {"Connection Refused: not authorized\r\n"};
void GSM_MQTT::printConnectAck(uint8_t Ack)
{
  switch (Ack)
  {
    case 0:
      {
        int k, len = strlen_P(ConnectAck0);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck0 + k);
          Serial.print(myChar);
        }
        break;
      }
    case 1:
      {
        int k, len = strlen_P(ConnectAck1);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck1 + k);
          Serial.print(myChar);
        }
        break;
      }
    case 2:
      {
        int k, len = strlen_P(ConnectAck2);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck2 + k);
          Serial.print(myChar);
        }
        break;
      }
    case 3:
      {
        int k, len = strlen_P(ConnectAck3);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck3 + k);
          Serial.print(myChar);
        }
        break;
      }
    case 4:
      {
        int k, len = strlen_P(ConnectAck4);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck4 + k);
          Serial.print(myChar);
        }
        break;
      }
    case 5:
      {
        int k, len = strlen_P(ConnectAck5);
        char myChar;
        for (k = 0; k < len; k++)
        {
          myChar =  pgm_read_byte_near(ConnectAck5 + k);
          Serial.print(myChar);
        }
        break;
      }
  }
}
unsigned int GSM_MQTT::_generateMessageID(void)
{
  if (_LastMessaseID < 65535)
  {
    return ++_LastMessaseID;
  }
  else
  {
    _LastMessaseID = 0;
    return _LastMessaseID;
  }
}
void GSM_MQTT::processing(void)
{
  if (TCP_Flag == false)
  {
    MQTT_Flag = false;
    _tcpInit();
  }
  _ping();
}
bool GSM_MQTT::available(void)
{
  return MQTT_Flag;
}
void serialEvent1()
{

  while (Serial1.available())
  {
    char inChar = (char)Serial1.read();
    if (MQTT.TCP_Flag == false)
    {
      if (MQTT.index < 200)
      {
        MQTT.inputString[MQTT.index++] = inChar;
      }
      if (inChar == '\n')
      {
        MQTT.inputString[MQTT.index] = 0;
        stringComplete = true;
        Serial.print(MQTT.inputString);
        if (strstr(MQTT.inputString, MQTT.reply) != NULL)
        {
          MQTT.GSM_ReplyFlag = 1;
          if (strstr(MQTT.inputString, " INITIAL") != 0)
          {
            MQTT.GSM_ReplyFlag = 2; //
          }
          else if (strstr(MQTT.inputString, " START") != 0)
          {
            MQTT.GSM_ReplyFlag = 3; //
          }
          else if (strstr(MQTT.inputString, "IP CONFIG") != 0)
          {
            _delay_us(10);
            MQTT.GSM_ReplyFlag = 4;
          }
          else if (strstr(MQTT.inputString, " GPRSACT") != 0)
          {
            MQTT.GSM_ReplyFlag = 4; //
          }
          else if ((strstr(MQTT.inputString, " STATUS") != 0) || (strstr(MQTT.inputString, "TCP CLOSED") != 0))
          {
            MQTT.GSM_ReplyFlag = 5; //
          }
          else if (strstr(MQTT.inputString, " TCP CONNECTING") != 0)
          {
            MQTT.GSM_ReplyFlag = 6; //
          }
          else if ((strstr(MQTT.inputString, " CONNECT OK") != 0) || (strstr(MQTT.inputString, "CONNECT FAIL") != NULL) || (strstr(MQTT.inputString, "PDP DEACT") != 0))
          {
            MQTT.GSM_ReplyFlag = 7;
          }
        }
        else if (strstr(MQTT.inputString, "OK") != NULL)
        {
          GSM_Response = 1;
        }
        else if (strstr(MQTT.inputString, "ERROR") != NULL)
        {
          GSM_Response = 2;
        }
        else if (strstr(MQTT.inputString, ".") != NULL)
        {
          GSM_Response = 3;
        }
        else if (strstr(MQTT.inputString, "CONNECT FAIL") != NULL)
        {
          GSM_Response = 5;
        }
        else if (strstr(MQTT.inputString, "CONNECT") != NULL)
        {
          GSM_Response = 4;
          MQTT.TCP_Flag = true;
          Serial.println("MQTT.TCP_Flag = True");
          MQTT.AutoConnect();
          MQTT.pingFlag = true;
          MQTT.tcpATerrorcount = 0;
        }
        else if (strstr(MQTT.inputString, "CLOSED") != NULL)
        {
          GSM_Response = 4;
          MQTT.TCP_Flag = false;
          MQTT.MQTT_Flag = false;
        }
        MQTT.index = 0;
        MQTT.inputString[0] = 0;
      }
    }
    else
    {
      uint8_t ReceivedMessageType = (inChar / 16) & 0x0F;
      uint8_t DUP = (inChar & DUP_Mask) / DUP_Mask;
      uint8_t QoS = (inChar & QoS_Mask) / QoS_Scale;
      uint8_t RETAIN = (inChar & RETAIN_Mask);
      if ((ReceivedMessageType >= CONNECT) && (ReceivedMessageType <= DISCONNECT))
      {
        bool NextLengthByte = true;
        MQTT.length = 0;
        MQTT.lengthLocal = 0;
        uint32_t multiplier=1;
        delay(2);
        char Cchar = inChar;
        while ( (NextLengthByte == true) && (MQTT.TCP_Flag == true))
        {
          if (Serial1.available())
          {
            inChar = (char)Serial1.read();
            Serial.println(inChar, DEC);
            if ((((Cchar & 0xFF) == 'C') && ((inChar & 0xFF) == 'L') && (MQTT.length == 0)) || (((Cchar & 0xFF) == '+') && ((inChar & 0xFF) == 'P') && (MQTT.length == 0)))
            {
              MQTT.index = 0;
              MQTT.inputString[MQTT.index++] = Cchar;
              MQTT.inputString[MQTT.index++] = inChar;
              MQTT.TCP_Flag = false;
              MQTT.MQTT_Flag = false;
              MQTT.pingFlag = false;
              Serial.println("Disconnecting");
            }
            else
            {
              if ((inChar & 128) == 128)
              {
                MQTT.length += (inChar & 127) *  multiplier;
                multiplier *= 128;
                Serial.println("More");
              }
              else
              {
                NextLengthByte = false;
                MQTT.length += (inChar & 127) *  multiplier;
                multiplier *= 128;
              }
            }
          }
        }
        MQTT.lengthLocal = MQTT.length;
        Serial.println(MQTT.length);
        if (MQTT.TCP_Flag == true)
        {
          MQTT.printMessageType(ReceivedMessageType);
          MQTT.index = 0L;
          uint32_t a = 0;
          while ((MQTT.length-- > 0) && (Serial1.available()))
          {
            MQTT.inputString[uint32_t(MQTT.index++)] = (char)Serial1.read();

            delay(1);

          }
          Serial.println(" ");
          if (ReceivedMessageType == CONNACK)
          {
            MQTT.ConnectionAcknowledgement = MQTT.inputString[0] * 256 + MQTT.inputString[1];
            if (MQTT.ConnectionAcknowledgement == 0)
            {
              MQTT.MQTT_Flag = true;
              MQTT.OnConnect();

            }

            MQTT.printConnectAck(MQTT.ConnectionAcknowledgement);
            // MQTT.OnConnect();
          }
          else if (ReceivedMessageType == PUBLISH)
          {
            uint32_t TopicLength = (MQTT.inputString[0]) * 256 + (MQTT.inputString[1]);
            Serial.print("Topic : '");
            MQTT.PublishIndex = 0;
            for (uint32_t iter = 2; iter < TopicLength + 2; iter++)
            {
              Serial.print(MQTT.inputString[iter]);
              MQTT.Topic[MQTT.PublishIndex++] = MQTT.inputString[iter];
            }
            MQTT.Topic[MQTT.PublishIndex] = 0;
            Serial.print("' Message :'");
            MQTT.TopicLength = MQTT.PublishIndex;

            MQTT.PublishIndex = 0;
            uint32_t MessageSTART = TopicLength + 2UL;
            int MessageID = 0;
            if (QoS != 0)
            {
              MessageSTART += 2;
              MessageID = MQTT.inputString[TopicLength + 2UL] * 256 + MQTT.inputString[TopicLength + 3UL];
            }
            for (uint32_t iter = (MessageSTART); iter < (MQTT.lengthLocal); iter++)
            {
              Serial.print(MQTT.inputString[iter]);
              MQTT.Message[MQTT.PublishIndex++] = MQTT.inputString[iter];
            }
            MQTT.Message[MQTT.PublishIndex] = 0;
            Serial.println("'");
            MQTT.MessageLength = MQTT.PublishIndex;
            if (QoS == 1)
            {
              MQTT.publishACK(MessageID);
            }
            else if (QoS == 2)
            {
              MQTT.publishREC(MessageID);
            }
            MQTT.OnMessage(MQTT.Topic, MQTT.TopicLength, MQTT.Message, MQTT.MessageLength);
            MQTT.MessageFlag = true;
          }
          else if (ReceivedMessageType == PUBREC)
          {
            Serial.print("Message ID :");
            MQTT.publishREL(0, MQTT.inputString[0] * 256 + MQTT.inputString[1]) ;
            Serial.println(MQTT.inputString[0] * 256 + MQTT.inputString[1]) ;

          }
          else if (ReceivedMessageType == PUBREL)
          {
            Serial.print("Message ID :");
            MQTT.publishCOMP(MQTT.inputString[0] * 256 + MQTT.inputString[1]) ;
            Serial.println(MQTT.inputString[0] * 256 + MQTT.inputString[1]) ;

          }
          else if ((ReceivedMessageType == PUBACK) || (ReceivedMessageType == PUBCOMP) || (ReceivedMessageType == SUBACK) || (ReceivedMessageType == UNSUBACK))
          {
            Serial.print("Message ID :");
            Serial.println(MQTT.inputString[0] * 256 + MQTT.inputString[1]) ;
          }
          else if (ReceivedMessageType == PINGREQ)
          {
            MQTT.TCP_Flag = false;
            MQTT.pingFlag = false;
            Serial.println("Disconnecting");
            MQTT.sendATreply("AT+CIPSHUT\r\n", ".", 4000) ;
            MQTT.modemStatus = 0;
          }
        }
      }
      else if ((inChar = 13) || (inChar == 10))
      {
      }
      else
      {
        Serial.print("Received :Unknown Message Type :");
        Serial.println(inChar);
      }
    }
  }
}
solankigithub commented 8 years ago

Hey Guys, any help ? The publish is working when i call it inside the loop(). But unfortunately, the subscribe not working, I am sending messages but not able to receive it to my Arduino i.e the OnMessage event/method doesn't execute.

Thanks

guillebot commented 8 years ago

Have you found any answers? I have the same problem. The library is working, but MQTT.available() returns allways false and some things behave weird.

durvesh09 commented 7 years ago

Same issue !! not working.. got stuck at MQTT.MessageFlag = true; any solution ?

nictally commented 7 years ago

I got it to work with Altsoft serial on pin 8 and 9

karanmakharia commented 7 years ago

@nictally Can you tell me the changes you did in the cpp file and the example file. For me the output is just stuck at +++AT i.e. SerialEvents @solankigithub Did you get it working?

arminsalcin commented 7 years ago

Guys for me all works like a charm when i rewrite serial event. I will upload my code in some days :D

guillebot commented 7 years ago

Can't wait to try it! Thanks.

arminsalcin commented 7 years ago

Here it is https://files.fm/f/6qwyj9z9

karanmakharia commented 7 years ago

@arminsalcin Hello. I need to know if this code works even for software serial because I don't want to use Mega. I will be using nano, pro mini or Uno with a software serial attached to the Sim808 module.

arminsalcin commented 7 years ago

I need to test it first with software serial , then if i make it it will be here. Have a nice day :D

arminsalcin commented 7 years ago

I found a way for Software serial but have a problems with SerialEvent() fuction becouse it work like a hardware interrupt when some informations come in serial it will run , so if we use a software serial nothing came in and code bug but if i connect arduino hardware serial RX with Software serial TX its run normaly. So found way but don't know is it okay to your project.

karanmakharia commented 7 years ago

@arminsalcin If I wanted to connect it on the 0,1 pins that is Serial of arduino uno, then do I need to replace all the Serial1.write/Serial1.print functions with Serial.write/print resp? Currently the Serial is used for notifying us right?

abhaysbharadwaj commented 7 years ago

Hello all, I am getting this error:

C:\Users\Abhay.S.Bharadwaj\Desktop\sim900_mqtt_test\sim900_mqtt_test.ino: In function 'void loop()':

sim900_mqtt_test:52: error: cannot convert 'GSM_MQTT::available' from type 'bool (GSM_MQTT::)()' to type 'bool'

   if (MQTT.available)

                     ^

sim900_mqtt_test:58: error: '_generateMessageID' was not declared in this scope

     MQTT.publish(0, 1, 0, _generateMessageID(), publishTopic, gasPayload);

                                              ^

Using library SoftwareSerial at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial 
exit status 1
**cannot convert 'GSM_MQTT::available' from type 'bool (GSM_MQTT::)()' to type 'bool'**

I have not done any changes to the library. My code is as follows:

`#include "GSM_MQTT.h"
#include <SoftwareSerial.h>
#define gasPin A1
String MQTT_HOST = "test.mosquitto.org";
String MQTT_PORT = "1883";
char* WillTopic = "*********";
char* WillMessage = "offline";
char* publishTopic = "*********";

SoftwareSerial mySerial(10, 11); // RX, TX
void GSM_MQTT::AutoConnect(void)
{

  connect("kumbh1", 0, 0, "username", "password", 1, 1, 1, 1, WillTopic, WillMessage);
}
void GSM_MQTT::OnConnect(void)
{
  subscribe(0, _generateMessageID(), "SampleTopic", 1);
  publish(0, 1, 0, _generateMessageID(), "SampleTopic", "Hello");
}
void GSM_MQTT::OnMessage(char *Topic, int TopicLength, char *Message, int MessageLength)
{
  mySerial.println("New MQTT Message Reseived! Details: ");
  mySerial.println(TopicLength);
  mySerial.println(Topic);
  mySerial.println(MessageLength);
  mySerial.println(Message);
}
GSM_MQTT MQTT(20); //20 is the keepalive duration in seconds

void setup()
{
  // initialize mqtt:
  // GSM modem should be connected to Hardware Serial
  //  index =0;
  MQTT.begin();

  /*
     Write your setup related arduino code like:
     pinMode(gasPin, INPUT);
  */

}
void loop()
{

  /*
     You can write your maincode here. Example:
  */
  float x = analogRead(gasPin);
  char* gasPayload = f2s(x, 0); //f2s is our function to convert float values to string
  if (MQTT.available)
  {
    /*
      if you want to do something when mqtt connection is live.
      You can write your code here
    */
    MQTT.publish(0, 1, 0, _generateMessageID(), publishTopic, gasPayload);
  }

  MQTT.processing();
}

/* float to string
   f is the float to turn into a string
   p is the precision (number of decimals)
   return a string representation of the float.
*/
char *f2s(float f, int p)
{
  char * pBuff;                         // use to remember which part of the buffer to use for dtostrf
  const int iSize = 10;                 // number of buffers, one for each float before wrapping around
  static char sBuff[iSize][20];         // space for 20 characters including NULL terminator for each float
  static int iCount = 0;                // keep a tab of next place in sBuff to use
  pBuff = sBuff[iCount];                // use this buffer
  if (iCount >= iSize - 1)
  { // check for wrap
    iCount = 0;                         // if wrapping start again and reset
  }
  else
  {
    iCount++;                           // advance the counter
  }
  return dtostrf(f, 0, p, pBuff);       // call the library function
}

` can anyone help me out?

abhaysbharadwaj commented 7 years ago

Edit: one error was resolved. i changed if (MQTT.available) to if (MQTT.available()).

but i still cant resolve this:

sim900_mqtt_test:58: error: '_generateMessageID' was not declared in this scope

     MQTT.publish(0, 1, 0, _generateMessageID(), publishTopic, gasPayload);

                                              ^
arminsalcin commented 7 years ago

in void loop change _generateMessageID() to example "armin" with quotes put your name or whatever tou want to be your message id

arminsalcin commented 7 years ago

MQTT.publish(0, 1, 0, "armin", publishTopic, gasPayload);

abhaysbharadwaj commented 7 years ago

ok. I shall try it out! Thank you for your quick response!

arminsalcin commented 7 years ago

You're welcome :D , try it and say if it works.

ameya24k commented 7 years ago

@karanmakharia I am also stuck at +++AT. Can someone please help? I am using the same code given above. @arminsalcin Can you please upload your code again? The link seems to be expired Any help would be appreciated guys. Thanks

arminsalcin commented 7 years ago

Can you provide us more information , like what module you use? , where do you connect your module rx and tx ? , how do you power your module ...

jalkestrup commented 7 years ago

Hi @arminsalcin , thanks for the responses. As @Akelectro asked it would be great if you could upload the edited library that allows for the use of software-serial interface with the Sim800 :-) Despite that it might have problems in relation to SerialEvent().

arminsalcin commented 7 years ago

@jalkestrup Hello guys sorry for link expired , i will uplaod new one ASAP !

bidyutper commented 7 years ago

@arminsalcin link plz..lin provided is broken

priya2212 commented 7 years ago

@arminsalcin Please share the link! I am using SIM800 module and SIM800 RX --> Arduino's TX & SIM800 TX --> Arduino's RX. I am able to publish the message with the topic but not able to subscribe. Please help if anyone finds a solution.

shijinjose commented 7 years ago

@nithinkurian @solankigithub @arminsalcin Hi am using SIM800 with ATmega328p with seial on (2,3)

I have changed the software serrial and hardware serial and also renamed the serialEvent to serialEvent1. But am getting response upto AT+CIPSTART. after sending connect request, am not getting any response

Here is my serial terminal output. can u please help me to solve this issue..?

AT

OK ATE1

OK AT+CREG?

+CREG: 0,2

OK AT+CREG?

+CREG: 0,1 -5þAT+CIPMUX=0

OK AT+CIPMODE=1

OK AT+CGATT?

+CGATT: 1 -5þAT+CIPSTATUS

OK

STATE: IP INITIAL AT+CSTT="www","",""

OK AT+CIPSTATUS

OK

STATE: IP START AT+CIICR

OK AT+CIPSTATUS

OK

STATE: IP GPRSACT AT+CIFSR

10.244.81.80 AT+CIPSTATUS

OK

STATE: IP STATUS AT+CIPSTART="TCP","192.168.2.139","1883"

OÿAT+CIPSTATUS

OK

STATE: TCP CONNECTING  CONNECT MQTT.TCP_Flag = True

arminsalcin commented 7 years ago

@shijinjose you cant use serialevent1 on arduino uno (atmega328) becouse it have only one hardware serial port and thats serial event . You can use only pins 0,1- arduino or 2,3- atmega328 directly.

coffeerr2004001 commented 6 years ago

hi, your link expired again. @arminsalcin

arminsalcin commented 6 years ago

@coffeerr2004001 MQTT.zip

abhaysbharadwaj commented 6 years ago

Tested with "Arduino Mega" and things work flawlessly. Was able to get the publish part on Arduino UNO/Nano over software serial. but Subscribe never worked.

again, everything is working flawlessly in MEGA/Serial1.

arminsalcin commented 6 years ago

@abhaysbharadwaj Can you share your code ? , what code you used ?

abhaysbharadwaj commented 6 years ago

SIM800L_MQTT.zip file is same as that given by @arminsalcin

arminsalcin commented 6 years ago

@abhaysbharadwaj

if (MQTT.available())
  {
    MQTT.subscribe(0, 0, "/topic", 1);
  }

Try to add subscribe in loop part if it works try also to put in "on connect" function play little bit with it !

abhaysbharadwaj commented 6 years ago

GSM_MQTT_Arduino_Subscribe_Publish.zip This is the file. I have modified it to work on software serial of Arduino Uno. Only publish and LWT works. Subscribe is not working.(it requires hardware serial for event generation).

abhaysbharadwaj commented 6 years ago

I have tried all this, It's not working. Tried to do subscribe in loop, in setup, in MQTT.available(). Didn't work.

arminsalcin commented 6 years ago

@abhaysbharadwaj Can you also please share connection diagram arduino - sim module

abhaysbharadwaj commented 6 years ago

SIM800L -- Arduino Uno/nano Vcc - powered by external buck converter Gnd - Gnd Tx - SoftwareSerial Rx (D5) Rx - SoftwareSerial Tx (D6)

arminsalcin commented 6 years ago

@abhaysbharadwaj Yes you can't get data from subscribe because you changed function to your internal function but it doesn't have any interrupt functions with hardware so when your data maybe come you cant read it , cause rx buffer only stays it don't interrupt any function to read .

abhaysbharadwaj commented 6 years ago

oh, then I have to see how to work around this! But I haven't changed any functions. Only Software Serial --> Hardware and Hardware --> Software Serial.

arminsalcin commented 6 years ago

@abhaysbharadwaj Try this , connect jumper from D5 to arduino serial RX pin , and change in software function "myserialevent" back as default "serialevent" . You should get and subscribe but this is hack not solution... . And yes you changed function .. screen shot 2018-02-15 at 3 05 52 pm

abhaysbharadwaj commented 6 years ago

ah! I should try this out! regarding the function, I only renamed it. I didn't think it will affect anything.

basically changes all the "Serial" to "mySerial" and vice versa and worked it around a little.

Now, what you say should work. Connecting a jumper from SIM800L Tx to Arduino Uno Hardware Rxo get the data and generate an event. I'll have to try this.

arminsalcin commented 6 years ago

yes you should stay connection also to D5 as you set in code its your rx pin , you only interrupting RX pin this way :)

serialEvent() - looks as normal function but it has actually interrupt function so whenever soem data comes to rx pin it start this function ,changing name at any kind will corrupt it .

https://www.arduino.cc/en/Tutorial/SerialEvent

abhaysbharadwaj commented 6 years ago

now I get it!! "Serial" and "serial" made me assume it was a custom function! :P

arminsalcin commented 6 years ago

@abhaysbharadwaj I'm glad you understand it now , have a nice day !

abhaysbharadwaj commented 6 years ago

Thank you very much for the insight and help. You too have a great day.

guillerone commented 6 years ago

Hi. I tried the code from @arminsalcin and @abhaysbharadwaj but MQTT.AVAILABLE() never succeeds. Can anyone help me out? I ran out of ideas.

My GSM module allows to set the communicating PINs and I set them to 2(TX) and 5 (RX), and they are wired to the MEGA's 19(RX) and 18(TX) (2 to 19 and 5 to 18). The serial seems to spit all OK messages, but it still doesn't work, it goes into a loop where it just starts all over again. Below is the console output. Any help will be deeply appreciated. Thank you!

AT

OK +++AT ATE1

OK AT+CREG?

+CREG: 0,1

OK AT+CIPMUX=0 AT+CIPMODE=1

OK AT+CGATT?

+CGATT: 1

OK AT+CIPSTATUS

OK

STATE: IP INITIAL AT+CSTT="ac.vodafone.es","vodafone","vodafone"

OK AT+CIPSTATUS

OK

STATE: IP START AT+CIICR

OK AT+CIPSTATUS

OK

STATE: IP GPRSACT AT+CIFSR

77.209.117.183 AT+CIPSTATUS

OK

STATE: IP STATUS AT+CIPSTART="TCP","io.adafruit.com","1883"

OK

CONNECT OK AT+CIPSTATUS

OK

STATE: CONNECT OK AT+CIPSHUT

SHUT OK +++AT

OK ATE1

OK AT+CREG?

+CREG: 0,1

OK AT+CIPMUX=0 AT+CIPMODE=1

OK AT+CGATT?

+CGATT: 1

OK AT+CIPSTATUS

OK

STATE: IP INITIAL AT+CSTT="ac.vodafone.es","vodafone","vodafone"

guillerone commented 6 years ago

Nevermind, I found out that if I add a small delay in SerialEvent1, it works...

void serialEvent1()
{
  while (Serial1.available())
  {
    delay(5); //Small delay to make it work
    char inChar = (char)Serial1.read();