#include <Arduino.h>
#include <log.h>
#include <sequans_controller.h>
#include <led_ctrl.h>
#include <lte.h>
#include <mqtt_client.h>
#include <low_power.h>
#include <mcp9808.h>
#include <veml3328.h>
#include <http_client.h>
#include "config.h"
#define MQTT_ENABLED true
#define MQTT_USE_TLS false
#define MQTT_KEEPALIVE 60
#define MQTT_USE_ECC false
ResponseResult response_result;
static char response[1024] = "";
static char reason[255] = "";
static char result[1024] = "";
static char x[1024] = "";
static char message[1024] = "";
static int err;
static char *ptr;
static char deviceid[20]; // = "avr-123456789012345\0";
static char simid[21]; // = "12345678901234567890\0";
static int CESQ;
static volatile bool switchir = false;
static volatile bool pinir = false;
static bool error = true;
static float voltage;
static int temperature;
static void switchInterrupt(void) {
switchir = true;
digitalWrite(PIN_PB2, LOW); // user led on
}
static void pinInterrupt(void) {
pinir = true;
digitalWrite(PIN_PB2, LOW); // user led on
digitalWrite(PIN_PE2, HIGH); // trigger pin
}
void(* resetFunc) (void) = 0; //declare reset function @ address 0
void setup() {
Log.begin(115200);
Log.info(F("setup"));
LowPower.configurePowerDown();
SequansController.begin();
// telekom.nl sim iotcreators.com APN
response_result = SequansController.writeCommand(F("AT+CGDCONT=1,\"IPV4V6\",\"m2m.public.nl\""),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("AT+CGDCONT: %s\r\n"),response);
}
// Returns result codes in words
response_result = SequansController.writeCommand(F("ATV1"),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("ATV1: %s\r\n"),response);
}
// get deviceid
response_result = SequansController.writeCommand(F("AT+CGSN=1"),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("1AT+CGSN=1: %s\r\n"),response);
} else {
Log.infof(F("1AT+CGSN=1: %s\r\n"),response);
SequansController.writeCommand(F("AT+CGSN=1"),response,sizeof(response));
Log.infof(F("2AT+CGSN=1: %s\r\n"),response);
if (response[0] == '\0') {
response_result = SequansController.writeCommand(F("AT^RESET"),response,sizeof(response));
if (response_result == ResponseResult::OK) {
Log.infof(F("AT^RESET: %s\r\n"),response);
response_result = SequansController.writeCommand(F("AT+CGSN=1"),response,sizeof(response));
if (response_result == ResponseResult::OK) {
Log.infof(F("3AT+CGSN=1: %s\r\n"),response);
if (response[0] == '\0') {
// the response was alway incomplete or empty until here: giving up, start over
resetFunc();
}
} else {
Log.errorf(F("4AT+CGSN=1: %s\r\n"),response);
}
} else {
Log.errorf(F("AT^RESET: %s\r\n"),response);
}
} else {
ptr = strtok(response, ": \"\r\n");
if (strlen(ptr) != 15) {
SequansController.writeCommand(F("AT+CGSN=1"),response,sizeof(response));
}
}
}
// TODO: check for 2 " +CGSN: "dsadadasdasad"
Log.infof(F("AT^RESET or AT+CGSN=1: %s\r\n"),response);
ptr = strtok(response, ": \"\r\n");
// validate deviceid 15
if (strlen(ptr) != 15) {
// I hate SequansController it is just not reliable....(this was before I increased strings to 1024)
response_result = SequansController.writeCommand(F("AT+CGSN=1"),response,sizeof(response));
ptr = strtok(response, ": \"\r\n");
if (strlen(ptr) != 15) {
resetFunc();
}
}
// finaly deviceid
snprintf(deviceid, sizeof(deviceid), "avr-%s", ptr);
// start mobile connection
err = Lte.begin(60000,true);
if (err) {
Log.infof(F("lte: %d\r\n"),err);
} else {
Log.errorf(F("lte: %d\r\n"),err);
}
// get simid
response_result = SequansController.writeCommand(F("AT+SQNCCID"),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("AT+SQNCCID: %s\r\n"),response);
}
Log.infof(F("AT+SQNCCID: %s\r\n"),response);
ptr = strtok(response, "\"");
ptr = strtok(NULL, "\"");
snprintf(simid, sizeof(simid), "%s", ptr);
// get modem firmware version
response_result = SequansController.writeCommand(F("AT+CGMR"),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("AT+CGMR: %s\r\n"),response);
}
// AT+CGMR UE8.0.5.13
ptr = strtok(response, "\r\n");
strcpy(message, "{");
strcat(message, ptr);
strcat(message, ", ");
strcat(message, deviceid);
strcat(message, ", I:");
strcat(message, simid);
strcat(message, ", S:");
// get modem serial number
response_result = SequansController.writeCommand(F("ATI2"),response,sizeof(response));
if (response_result != ResponseResult::OK) {
Log.errorf(F("AT+SQNCCID: %s\r\n"),response);
}
ptr = strtok(response, ": \"\r\n");
ptr = strtok(NULL, ": \"\r\n");
strcat(message, ptr);
// get device ip at+cgpaddr
LedCtrl.begin();
if (MQTT_ENABLED) {
err = MqttClient.begin(deviceid,MQTT_BROKER,MQTT_PORT,MQTT_USE_TLS,MQTT_KEEPALIVE,MQTT_USE_ECC,MOSQUITTO_USERNAME,MOSQUITTO_PASSWORD,30000,true);
if (err) {
Log.infof(F("mqtt: %d\r\n"),err);
} else {
Log.errorf(F("mqtt: %d\r\n"),err);
}
connectToMQTT();
strcat(message, "}");
String message_to_publish = String(message);
strcpy(response, "hackster/forest/");
strcat(response, deviceid);
strcat(response, "/boot");
err = MqttClient.publish(response, message_to_publish.c_str());
Log.infof(F("publish: boot, %d %s %s"),err,response,message);
}
Mcp9808.begin();
Veml3328.begin();
Veml3328.shutdown();
// user led
pinConfigure(PIN_PB2, PIN_DIR_OUTPUT);
// pin output trigger
pinConfigure(PIN_PE2, PIN_DIR_OUTPUT);
// switchir / pinir input
pinConfigure(PIN_PD2, PIN_DIR_INPUT | PIN_PULLUP_ON); // for debugging ir with sw1
pinConfigure(PIN_PD0, PIN_DIR_INPUT | PIN_PULLUP_OFF); // for pin ir
attachInterrupt(PIN_PD2, switchInterrupt, FALLING);
attachInterrupt(PIN_PD0, pinInterrupt, RISING); // RISING FALLING
Log.infof(F("------pins: %d\r\n"), digitalRead(PIN_PD0));
// get signal strength, now that we transmitted smth.
response_result = SequansController.writeCommand(F("AT+CESQ"),response,sizeof(response));
err = SequansController.extractValueFromCommandResponse(response,5,result,sizeof(result));
if (err) {
Log.infof(F("AT+CESQ: %s; "),result);
CESQ = atoi(result)-140;
Log.infof(F("AT+CESQ: %d\r\n"),CESQ);
}
// celebrate finishing setup
LedCtrl.startupCycle();
}
void loop() {
Log.infof("- - L O O P - -\r\n");
static int i=0;
distance = 0;
i++;
strcpy(reason, "hourly");
// since we might just had finished low power mode
Mcp9808.wake();
// check if switch was pressed or interrupt on pin
if (switchir) {
Log.info(F("switchInterrupt"));
delay(1000);
digitalWrite(PIN_PB2, HIGH); // user led off
switchir = false;
strcpy(reason, "test");
}
if (pinir) {
Log.info(F("pinInterrupt"));
delay(1000);
digitalWrite(PIN_PB2, HIGH); // user led off
digitalWrite(PIN_PE2, LOW); // untrigger pin
pinir = false;
strcpy(reason, "alert");
distance = 1;
// todo: implement quite time for 15? minutes...
}
SequansController.writeCommand(F("AT+CGSN=0"),response,sizeof(response));
Log.infof(F("AT+CGSN=0: %s\r\n"),response);
connectToNetwork();
// build hourly mqtt reporting
strcpy(message, "{");
strcat(message, deviceid);
strcat(message, ", I:");
strcat(message, simid);
// dummy, since I had problems with empty+uncomplete responses
response_result = SequansController.writeCommand(F("AT+CESQ"),response,sizeof(response));
// get network operator MC/NC
response_result = SequansController.writeCommand(F("AT+COPS?"),response,sizeof(response));
if (response_result == ResponseResult::OK) {
Log.infof(F("AT+COPS?: %s\r\n"),response);
}
err = SequansController.extractValueFromCommandResponse(response,2,result,sizeof(result));
if (err) {
ptr = strtok(result, ": \"\r\n");
strcat(message, ", MC/NC:");
strcat(message, ptr);
}
// get TAC/CI
// get connection mode: LTE-M or NBIOT
response_result = SequansController.writeCommand(F("AT+CEREG?"),response,sizeof(response));
if (response_result == ResponseResult::OK) {
Log.infof(F("AT+CEREG: %s\r\n"),response);
}
err = SequansController.extractValueFromCommandResponse(response,2,result,sizeof(result));
if (err) {
ptr = strtok(result, ": \"\r\n");
strcat(message, ", TAC:");
strcat(message, ptr);
}
err = SequansController.extractValueFromCommandResponse(response,3,result,sizeof(result));
if (err) {
ptr = strtok(result, ": \"\r\n");
strcat(message, ", CI:");
strcat(message, ptr);
}
err = SequansController.extractValueFromCommandResponse(response,4,result,sizeof(result));
if (err) {
Log.infof(F("extractValueFromCommandResponse: %s\r\n"),result);
if (atoi(result) == 7) {sprintf(x, ", LTEM");}
if (atoi(result) == 9) {sprintf(x, ", NBIOT");}
}
strcat(message, x);
// get date/time
response_result = SequansController.writeCommand(F("AT+CCLK?"),response,sizeof(response));
if (response_result == ResponseResult::OK) {
Log.infof(F("AT+CCLK?: %s\r\n"),response);
}
// get voltage of battery
voltage = LowPower.getSupplyVoltage();
Log.infof(F("The voltage supplied is: %.2f\r\n"), voltage);
snprintf(response, sizeof(response), ", bat:%.2f", (double) voltage);
strcat(message, response);
// get temperature
temperature = int(Mcp9808.readTempC());
Log.infof(F("Temperature (*C): %d\r\n"), temperature);
snprintf(response, sizeof(response), ", t:%d", temperature);
strcat(message, response);
snprintf(response, sizeof(response), ", %d", CESQ);
strcat(message, response);
snprintf(response, sizeof(response), ", up:%2d", i);
strcat(message, response);
snprintf(response, sizeof(response), ", p:%d", digitalRead(PIN_PD0));
strcat(message, response);
if (MQTT_ENABLED) {
connectToMQTT();
strcat(message, "}");
String message_to_publish = String(message);
strcpy(response, "hackster/forest/");
strcat(response, deviceid);
strcat(response, "/");
strcat(response, reason);
err = MqttClient.publish(response, message_to_publish.c_str());
Log.infof(F("publish: %d %d %s %s"),i,err,response,message);
}
// get signal strength ...
response_result = SequansController.writeCommand(F("AT+CESQ"),response,sizeof(response));
err = SequansController.extractValueFromCommandResponse(response,5,result,sizeof(result));
if (err) {
Log.infof(F("AT+CESQ: %s\r\n"),result);
Log.infof(F("AT+CESQ: %d\r\n"),atoi(result)-140);
CESQ = atoi(result)-140;
}
// celebrate another loop finish
LedCtrl.startupCycle();
// go to sleep
Mcp9808.shutdown();
LowPower.powerDown(3540); // 60 min - 1 min for working through the loop ;-) - try to hit same minute every hour
//delay(600000); // 10min
}
static void connectToNetwork() {
if (!Lte.isConnected()) {
while (!Lte.begin(60000,true)) {} // hint: timesout, no danger of endless
Log.infof(F("REConnected to operator: %s\r\n"), Lte.getOperator().c_str());
}
}
static void connectToMQTT() {
int i =0;
if (Lte.isConnected()) {
if (!MqttClient.isConnected()) {
while ((i < 10) && !MqttClient.begin(deviceid,MQTT_BROKER,MQTT_PORT,MQTT_USE_TLS,MQTT_KEEPALIVE,MQTT_USE_ECC,MOSQUITTO_USERNAME,MOSQUITTO_PASSWORD,30000,true)) {
i++;
}
Log.info(F("REConnected to MqttClient"));
}
} else {
Log.error(F("no network, droping MqttClient connect"));
}
}
Comments