Xinyuan-LilyGO / LilyGO-T-SIM7000G

LilyGO T-SIM7000G
https://pt.aliexpress.com/item/4000542688096.html
294 stars 128 forks source link

Connecting using GSM to Azure MQTT failed #64

Closed ro85ac closed 3 years ago

ro85ac commented 4 years ago

Using a WiFi connection in this project all the messages are sent to Azure Cloud. Meanwhile using a GSM one I receive the following error. I google it, but I could not find anything useful.

Just this link but the problem is using wifi and in my project it doesn’t reproduce.

https://github.com/espressif/arduino-esp32/issues/3467

-> Info: Initializing SNTP

-> /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1442 (xQueueGenericReceive)- assert failed! -> abort() was called at PC 0x40088091 on core 1 -> Backtrace: 0x4008b764:0x3ffb1d90 0x4008b995:0x3ffb1db0 0x40088091:0x3ffb1dd0 0x4010677a:0x3ffb1e10 0x40106922:0x3ffb1e30 0x400f8d74:0x3ffb1e50 0x400f8ddd:0x3ffb1e70 0x400ffc91:0x3ffb1e90 0x400ffcb6:0x3ffb1eb0 0x400f8c0b:0x3ffb1ed0 0x400d3af5:0x3ffb1ef0 0x400d3b56:0x3ffb1f10 0x400d2c12:0x3ffb1f30 0x400d2819:0x3ffb1f70 0x400df4ab:0x3ffb1fb0 0x400883a5:0x3ffb1fd0

SIM7000G_Azure_MQTT.txt

ejri commented 3 years ago

@ro85ac were you able to find a solution to this?

I have the same issue when connected over GSM. Board connects perfectly fine with Azure over wifi, but doesn't connect over GSM. The cayanne example works over GSM though.

With Azure the last thing I see is:

Modem Connected to Rogers' LTE (channel--> 38) CAT-M (preferred network). TLE CAT-M OK

IoT Hub Info: Initializing SNTP

// This code: connecting 5 accelerometers to esp32. The processed data is sent to IoT Hub.
// IoT Hub connection, and device provisioning, etc. :

// SimpleMQTT_esp32_azure_iothub.ino
// downloads/ubc_5G/sensor_networks_azure/

// IoT Hub has to be Standard Tier, Basic Tier creates a lot of issues

// Azure ESP32 IoT DevKit Get Started
// https://docs.microsoft.com/en-us/samples/azure-samples/esp32-iot-devkit-get-started/sample/

/**
   A simple Azure IoT example for sending telemetry to Iot Hub.

  original code from:
  https://github.com/VSChina/ESP32_AzureIoT_Arduino
  se
*/

// TCA9548A I2C Switch between:
// adafruit LSM9DS1 at address, on TCA9548's channel 0
// GY521-MPU 6050 at address, on TCA9548's channel 1
// TCA9548 module I2C address:  0x70
//

//======================================================
//I2C Mutiplexing using TCA9548A at I2C address 0x70
//======================================================

// GY-521 / mpu6050 on esp32
// connections: 5v, GND, SDA, SCL, on sensor to 5v, GND, SDA, SCL on esp32 respectively

#include "Esp32MQTTClient.h"

/*
///////////////////////////MQTT device to cloud initial message setup///////
#include <ArduinoMqttClient.h>
#include <ArduinoBearSSL.h>
///////////////////////////MQTT device to cloud initial message setup///////
*/

//////////////////////////// Accelerometer ////////////////////
// Include Wire Library for I2C
#include <Wire.h>
// Amazing MPU6050 library by rfetick.
#include <MPU6050_light.h>
MPU6050 mpu(Wire);

const int MPU = 0x68;
int16_t roll1, pitch1, yaw1, roll2, pitch2, yaw2, roll3, pitch3, yaw3, roll4, pitch4, yaw4, roll5, pitch5, yaw5;
//////////////////////////// Accelerometer ////////////////////

void TCA9548A(uint8_t bus)
{
  Wire.beginTransmission(0x70);
  Wire.write(1 << bus);
  Wire.endTransmission();
}

//=============================================================================

#include "time.h"

//////////////// LTE-M connection ////////////////
#define TINY_GSM_MODEM_SIM7000

#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#define DUMP_AT_COMMANDS
#include "TinyGsmClient.h"

#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 60       /* ESP32 should sleep more seconds  (note SIM7000 needs ~20sec to turn off if sleep is activated) */
RTC_DATA_ATTR int bootCount = 0;

HardwareSerial serialGsm(1);
#define SerialAT serialGsm
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false

// rogers
const char apn[] = "ciot";
const char nbiot_apn[] = "ciot";

// 1nce
// const char apn[] = "iot.1nce.net";
// const char nbiot_apn[] = "iot.1nce.net";

#define isNBIOT false

const char user[] = "";
const char pass[] = "";

// TTGO T-SIM pin definitions
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_DTR 25

#define MODEM_TX 26
#define MODEM_RX 27

//#define I2C_SDA 21
//#define I2C_SCL 22

#define reading_samles 100

#ifdef DUMP_AT_COMMANDS
#include "StreamDebugger.h"
StreamDebugger debugger(serialGsm, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(serialGsm);
#endif

/*
///////////////////////////MQTT device to cloud initial message setup///////
/////////////////////////////////////////////////////
const char broker[]        = "<>.azure-devices.net"; // "<IoT Hub name>.azure-devices.net"
String     deviceId        = "<>"; //<device id>

#define IOT_HUB_NAME "<>"
#define DEVICE_NAME "<>"
#define SAS_TOKEN "<>"
////////////////////////////////////////////////////
const char* sslClient=
"-----BEGIN CERTIFICATE-----\n"
"<>";
///////////////////////////MQTT device to cloud initial message setup///////
*/

// Initialize GSM client
TinyGsmClient client(modem);

///////////////////////////MQTT device to cloud initial message setup///////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
///////////////////////////MQTT device to cloud initial message setup///////

// Set to true, if modem is connected
bool modemConnected = false;

void shutdown();
void wait_till_ready();
void modem_off();

void print_wakeup_reason()
{
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("Wakeup caused by external signal using RTC_IO");
      break;
    case ESP_SLEEP_WAKEUP_EXT1:
      Serial.println("Wakeup caused by external signal using RTC_CNTL");
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      Serial.println("Wakeup caused by timer");
      break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD:
      Serial.println("Wakeup caused by touchpad");
      break;
    case ESP_SLEEP_WAKEUP_ULP:
      Serial.println("Wakeup caused by ULP program");
      break;
    default:
      Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
      break;
  }
}

void modem_reset()
{
  Serial.println("Modem hardware reset");
  pinMode(MODEM_RST, OUTPUT);
  digitalWrite(MODEM_RST, LOW);
  delay(260); //Treset 252ms
  digitalWrite(MODEM_RST, HIGH);
  delay(4000); //Modem takes longer to get ready and reply after this kind of reset vs power on

  //modem.factoryDefault();
  //modem.restart(); //this results in +CGREG: 0,0
}

void modem_on()
{
  // Set-up modem  power pin
  pinMode(MODEM_PWKEY, OUTPUT);
  digitalWrite(MODEM_PWKEY, HIGH);
  delay(10);
  digitalWrite(MODEM_PWKEY, LOW);
  delay(1010); //Ton 1sec
  digitalWrite(MODEM_PWKEY, HIGH);

  //wait_till_ready();
  Serial.println("Waiting till modem ready...");
  delay(4510); //Ton uart 4.5sec but seems to need ~7sec after hard (button) reset
  //On soft-reset serial replies immediately.

}

void modem_off()
{
  //if you turn modem off while activating the fancy sleep modes it takes ~20sec, else its immediate
  Serial.println("Going to sleep now with modem turned off");
  //modem.gprsDisconnect();
  //modem.radioOff();
  modem.sleepEnable(false); // required in case sleep was activated and will apply after reboot
  modem.poweroff();
}

// fancy low power mode - while connected
void modem_sleep() // will have an effect after reboot and will replace normal power down
{
  Serial.println("Going to sleep now with modem in power save mode");
  // needs reboot to activa and takes ~20sec to sleep
  //modem.PSM_mode();    //if network supports will enter a low power sleep PCM (9uA)
  //modem.eDRX_mode14(); // https://github.com/botletics/SIM7000-LTE-Shield/wiki/Current-Consumption#e-drx-mode
  modem.sleepEnable(); //will sleep (1.7mA), needs DTR or PWRKEY to wake
  pinMode(MODEM_DTR, OUTPUT);
  digitalWrite(MODEM_DTR, HIGH);
}

void modem_wake()
{
  Serial.println("Wake up modem from sleep");
  // DTR low to wake serial
  pinMode(MODEM_DTR, OUTPUT);
  digitalWrite(MODEM_DTR, LOW);
  delay(50);
  //wait_till_ready();
}

void shutdown()
{

  //modem_sleep();
  modem_off();

  delay(1000);
  Serial.flush();
  esp_deep_sleep_start();
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush();
  esp_deep_sleep_start();
}

void wait_till_ready() // NOT WORKING - Attempt to minimize waiting time
{

  for (int8_t i = 0; i < 100; i++) //timeout 100 x 100ms = 10sec
  {
    if (modem.testAT())
    {
      //Serial.println("Wait time:%F sec\n", i/10));
      Serial.printf("Wait time: %d\n", i);
      break;
    }
    delay(100);
  }
}

//////////////// LTE-M connection ////////////////

//=============================================================================

#define INTERVAL 15000 //10seconds intervals sending messages
#define MESSAGE_MAX_LEN 400

/// Primaty Connection String///
/*String containing Hostname, Device Id & Device Key in the format:                         */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"                */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>"    */
static const char *connectionString = "";
//const char *messageData = "{\"messageId\":%d, \"Temperature\":%f, \"Humidity\":%f}";
const char *messageData = "{\"DeviceID\":\"<>\",\"TreeType\":\"Cedar\" ,\"messageId\":%d, \"roll1\":%d, \"pitch1\":%d, \"yaw1\":%d, \"roll2\":%d, \"pitch2\":%d, \"yaw2\":%d, \"roll3\":%d, \"pitch3\":%d, \"yaw3\":%d, \"roll4\":%d, \"pitch4\":%d, \"yaw4\":%d, \"roll5\":%d, \"pitch5\":%d, \"yaw5\":%d}";
static bool hasIoTHub = false;
static bool hasWifi = false;
int messageCount = 1;
static bool messageSending = true;
static uint64_t send_interval_ms;

static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result)
{
  if (result == IOTHUB_CLIENT_CONFIRMATION_OK)
  {
    Serial.println("Send Confirmation Callback finished.");
  }
}

static void MessageCallback(const char *payLoad, int size)
{
  Serial.println("Message callback:");
  Serial.println(payLoad);
}

static void DeviceTwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char *payLoad, int size)
{
  char *temp = (char *)malloc(size + 1);
  if (temp == NULL)
  {
    return;
  }
  memcpy(temp, payLoad, size);
  temp[size] = '\0';
  // Display Twin message.
  Serial.println(temp);
  free(temp);
}

static int DeviceMethodCallback(const char *methodName, const unsigned char *payload, int size, unsigned char **response, int *response_size)
{
  LogInfo("Try to invoke method %s", methodName);
  const char *responseMessage = "\"Successfully invoke device method\"";
  int result = 200;

  if (strcmp(methodName, "start") == 0)
  {
    LogInfo("Start sending MPU - DeviceID: Cedar data");
    messageSending = true;
  }
  else if (strcmp(methodName, "stop") == 0)
  {
    LogInfo("Stop sending MPU - DeviceID: Cedar data");
    messageSending = false;
  }
  else
  {
    LogInfo("No method %s found", methodName);
    responseMessage = "\"No method found\"";
    result = 404;
  }

  *response_size = strlen(responseMessage) + 1;
  *response = (unsigned char *)strdup(responseMessage);

  return result;
}

/*
//////////////////////////NTP- Time ////////////////////////
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
//////////////////////////NTP- Time ////////////////////////
*/

void setup()
{

  Serial.begin(115200);

  //// start count/// --> moved to after modemOn() function
  //send_interval_ms = millis();

  delay(10);
  Serial.println(F("Started"));
  Serial.println("ESP32 Device");
  Serial.println("Initializing...");

  Wire.begin();
  TCA9548A(3);
  mpu.begin();
  Serial.println(F("Calculating gyro offset, do not move MPU6050"));
  mpu.calcGyroOffsets(); // This does the calibration
  delay(20);

  TCA9548A(4);
  mpu.begin();
  Serial.println(F("Calculating gyro offset, do not move MPU6050"));
  mpu.calcGyroOffsets();
  delay(20);

  TCA9548A(5);
  mpu.begin();
  Serial.println(F("Calculating gyro offset, do not move MPU6050"));
  mpu.calcGyroOffsets();
  delay(20);

  TCA9548A(6);
  mpu.begin();
  Serial.println(F("Calculating gyro offset, do not move MPU6050"));
  mpu.calcGyroOffsets();
  delay(20);

  TCA9548A(7);
  mpu.begin();
  Serial.println(F("Calculating gyro offset, do not move MPU6050"));
  mpu.calcGyroOffsets();
  delay(20);

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
    First we configure the wake up source
    We set our ESP32 to wake up every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
                 " Seconds");

  // if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TIMER)
  // {
  //   modem_wake();
  // }
  // else
  {
    modem_on();
    //modem_wake();
    //modem_reset();
  }
  // Set GSM module baud rate and UART pins
  SerialAT.begin(9600, SERIAL_8N1, MODEM_TX, MODEM_RX); //reversing them
  String modemInfo = modem.getModemInfo();
  Serial.print(F("Modem: "));
  Serial.println(modemInfo);

  if (!modemConnected)
  {

    //SIM7000

    if (isNBIOT)
    {
      Serial.println("configuring NBIoT mode");
      modem.setPreferredMode(38);
      //modem.setPreferredLTEMode(2);
      //modem.setOperatingBand(20); // Required for cosmote Greece

      Serial.print(F("Waiting for network..."));
      if (!modem.waitForNetwork(60000L))
      {
        Serial.println(" fail");
        modem_reset();
        shutdown();
      }
      Serial.println("Connected to LTE Mode Only (channel--> 38).... OK");

      Serial.print("Signal quality:");
      Serial.println(modem.getSignalQuality());

      Serial.print(F("Connecting to apn:"));
      Serial.println(nbiot_apn);
      if (!modem.gprsConnect(nbiot_apn, user, pass))
      {
        Serial.println(" failed");
        modem_reset();
        shutdown();
      }

      modemConnected = true;
      Serial.println("Modem Connected (channel--> 38). OK");
    }
    else
    {
      Serial.println("configuring LTE, Cat-M mode"); // AUTO or GSM ONLY

      //2 Auto
      // 13 GSM only
      // 38 LTE only
      // 51 GSM and LTE only
      modem.setNetworkMode(38);
      //modem.setOperatingBand("CAT-M",12)
      delay(500);

      /*
          1 CAT-M
          2 NB-Iot
          3 CAT-M and NB-IoT
        * * */

      modem.setPreferredMode(3);
      delay(500);

      Serial.print(F("Waiting for network..."));
      if (!modem.waitForNetwork(60000L))
      {
        Serial.println(" fail");
        modem_reset();
        shutdown();
      }
      Serial.println(" OK");

      Serial.print("Signal quality:");
      Serial.println(modem.getSignalQuality());

      Serial.print(F("Connecting to Rogers APN at LTE Mode Only (channel--> 38): "));
      Serial.print(apn);
      if (!modem.gprsConnect(apn, user, pass))
      {
        Serial.println(" failed");
        modem_reset();
        shutdown();
      }

      modemConnected = true;
      Serial.println("Modem Connected to Rogers' LTE (channel--> 38) CAT-M (preferred network). TLE CAT-M OK");
    }
  }
//////////////////////////////////////////////////// //////////////////////////////// 
/// send an http post request to IoT HUB from the device. in order to make the modem's IP public 
// this way, when the MQTT server initiates (from the cloud to the device), it connects through the 
// the modem's public IP
//////////////////////////////// ////////////////////////////////
  // Set the username to "<broker>/<device id>/?api-version=2018-06-30" and empty password  
  /*
  String username = "<>";
  MqttClient.connect(broker, 8883);
  MqttClient.setUsernamePassword(username, "");
  connectMQTT();
  MqttClient.poll();
  publishMessage();
  */

  Serial.println(" > IoT Hub"); 
  if (!Esp32MQTTClient_Init((const uint8_t *)connectionString, true))
  {
    hasIoTHub = false;
    Serial.println("Initializing IoT hub failed.");
    modem_reset();
    shutdown();
    return;
  }
 //////////////////////////////// 
  hasIoTHub = true;
  Esp32MQTTClient_SetSendConfirmationCallback(SendConfirmationCallback);
  Esp32MQTTClient_SetMessageCallback(MessageCallback);
  Esp32MQTTClient_SetDeviceTwinCallback(DeviceTwinCallback);
  Esp32MQTTClient_SetDeviceMethodCallback(DeviceMethodCallback);
  Serial.println("Start sending events.");
  randomSeed(analogRead(0));

  send_interval_ms = millis();   // moved to after adding the accelerometer

}

void loop()
{

  delay(1000);
//  printLocalTime();

if (modemConnected && hasIoTHub)
  {
    if (messageSending &&
        (int)(millis() - send_interval_ms) >= INTERVAL)
    {

      read_MPU_1();
      read_MPU_2();
      read_MPU_3();
      read_MPU_4();
      read_MPU_5();
      delay(2000);
      ////  raw accelerometer data //////

      char messagePayload[MESSAGE_MAX_LEN];

      snprintf(messagePayload, MESSAGE_MAX_LEN, messageData, messageCount++, roll1, pitch1, yaw1, roll2, pitch2, yaw2, roll3, pitch3, yaw3, roll4, pitch4, yaw4, roll5, pitch5, yaw5);
      Serial.println(messagePayload);
      EVENT_INSTANCE *message = Esp32MQTTClient_Event_Generate(messagePayload, MESSAGE);
      Esp32MQTTClient_SendEventInstance(message);
      send_interval_ms = millis();
    }
    else
    {
      Esp32MQTTClient_Check();
    }
  }
  delay(5000);

  //delay(1000); // required - else will shutdown too early and miss last value
  shutdown();
}

void read_MPU_1()
{
  // get pitch, roll, yaw accelerometer data /////
  TCA9548A(3);
      mpu.update();
      pitch1 = mpu.getAngleX();
      roll1 = mpu.getAngleY();
      yaw1 = mpu.getAngleZ();
      Serial.print(roll1);
      Serial.print("/");
      Serial.print(pitch1);
      Serial.print("/");
      Serial.println(yaw1);
      delay(1000);
}

void read_MPU_2()
{
  TCA9548A(4);
      mpu.update();
       pitch2 = mpu.getAngleX();
       roll2 = mpu.getAngleY();
       yaw2 = mpu.getAngleZ();
      Serial.print("pitch2: ");
      Serial.println(pitch2);
      Serial.print("roll2: ");
      Serial.println(roll2);
      Serial.print("yaw2: ");
      Serial.println(yaw2);
      delay(1000);
  }

 void read_MPU_3()
{
  TCA9548A(5);
      mpu.update();
       pitch3 = mpu.getAngleX();
       roll3 = mpu.getAngleY();
       yaw3 = mpu.getAngleZ();
      Serial.print("pitch3: ");
      Serial.println(pitch3);
      Serial.print("roll3: ");
      Serial.println(roll3);
      Serial.print("yaw3: ");
      Serial.println(yaw3);
      delay(100);
}

void read_MPU_4()
{
TCA9548A(6);
      mpu.update();
       pitch4 = mpu.getAngleX();
       roll4 = mpu.getAngleY();
       yaw4 = mpu.getAngleZ();
      Serial.print("pitch4: ");
      Serial.println(pitch4);
      Serial.print("roll4: ");
      Serial.println(roll4);
      Serial.print("yaw4: ");
      Serial.println(yaw4);
      delay(100);
}

void read_MPU_5()
{
  TCA9548A(7);
      mpu.update();
       pitch5 = mpu.getAngleX();
       roll5 = mpu.getAngleY();
       yaw5 = mpu.getAngleZ();
      Serial.print("pitch5: ");
      Serial.println(pitch5);
      Serial.print("roll5: ");
      Serial.println(roll5);
      Serial.print("yaw5: ");
      Serial.println(yaw5);

      delay(2000);
}

/*
void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!MqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    Serial.println(MqttClient.connectError());
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  MqttClient.subscribe("devices/" + deviceId + "/messages/devicebound/#");
}

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  MqttClient.beginMessage("devices/" + deviceId + "/messages/events/");
  MqttClient.print("hello ");
  MqttClient.print(millis());
  MqttClient.endMessage();
}
*/
ro85ac commented 3 years ago

@ejri

  1. I don't have a solution yet.
  2. The Azure SDK (Esp32MQTTClient) calls another time library (NTP server), and it works successfully with WiFi connection.
  3. Using the GSM connection it throws an error: https://github.com/vshymanskyy/TinyGSM/issues/357
  4. The solution for the GSM connection, you need to call the Azure API , something like this: // Set the client id used for MQTT as the device id mqttClient.setId(deviceId); // Set the username to "//api-version=2018-06-30" and empty password String username = ""; // username += broker; // username += "/"; // username += deviceId; username += "/api-version=2018-06-30"; mqttClient.setUsernamePassword(username, "");
ejri commented 3 years ago

@ro85ac thank you for your reply. I was able to get it working. Check the examples section in this repo, I uploaded an Azure example there.

Basically, esp32 has a number of features, including the internal clock, that get initiated only after initiating the wifi library...

ro85ac commented 3 years ago

@ejri

But if there is no wifi connection does it work?

Which repo? Can you share a link?

Thanks?

ejri commented 3 years ago

@ro85ac Yeah, you just need to initiate the library, by calling WiFi.begin();

You don't have to have it connect to wifi. You just initiate it, with a blank ssid and password.

Link>