Snorktracker
 All Data Structures Files Functions Variables Macros Pages
Mqtt.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2018 SFini
3 
4  This program is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
24 #include <PubSubClient.h>
25 
26 #define topic_deep_sleep "/DeepSleep"
27 
28 #define topic_voltage "/Voltage"
29 #define topic_mAh "/mAh"
30 #define topic_mAhLowPower "/mAhLowPower"
31 #define topic_alive "/Alive"
32 #define topic_rssi "/RSSI"
33 
34 #define topic_power_on "/PowerOn"
35 #define topic_gps_enabled "/GpsEnabled"
36 #define topic_send_on_move_every "/SendOnMoveEverySec"
37 #define topic_send_on_non_move_every "/SendOnNonMoveEverySec"
38 #define topic_send_every "/SendEverySec"
39 
40 #define topic_temperature "/BME280/Temperature"
41 #define topic_humidity "/BME280/Humidity"
42 #define topic_pressure "/BME280/Pressure"
43 
44 #define topic_signal_quality "/Gsm/SignalQuality"
45 #define topic_batt_level "/Gsm/BattLevel"
46 #define topic_batt_volt "/Gsm/BattVolt"
47 
48 #define topic_gps "/Gps"
49 #define topic_gps_distance "/GpsDistance"
50 
51 
54 class MyMqtt : protected PubSubClient
55 {
56 protected:
58 
59 public:
60  static void mqttCallback(char* topic, byte* payload, unsigned int len);
61 
62 protected:
66 
67 protected:
68  bool mySubscribe(String subTopic);
69  bool myPublish(String subTopic, String value);
70 
71 public:
72  MyMqtt(Client &client, MyOptions &options, MyData &data);
73  ~MyMqtt();
74 
75  bool begin();
76  void handleClient();
77 
78  bool waitingForMqtt();
79 };
80 
81 /* ******************************************** */
82 
84 MyMqtt::MyMqtt(Client &client, MyOptions &options, MyData &data)
85  : PubSubClient(client)
86  , myOptions(options)
87  , myData(data)
88  , publishInProgress(false)
89 {
90  g_myOptions = &options;
91 }
92 MyMqtt::~MyMqtt()
93 {
94  g_myOptions = NULL;
95 }
96 
100 bool MyMqtt::mySubscribe(String subTopic)
101 {
102  if (!myData.isGsmActive) {
103  return false;
104  }
105 
106  String topic;
107 
108  topic = myOptions.mqttName + F("/") + myOptions.mqttId + subTopic;
109  MyDbg((String) F("MyMqtt::subscribe: [") + topic + F("]"), true);
110  return PubSubClient::subscribe(topic.c_str());
111 }
112 
116 bool MyMqtt::myPublish(String subTopic, String value)
117 {
118  if (!myData.isGsmActive) {
119  return false;
120  }
121 
122  bool ret = false;
123 
124  if (value.length() > 0) {
125  String topic;
126 
127  topic = myOptions.mqttName + F("/") + myOptions.mqttId + subTopic;
128  MyDbg((String) F("MyMqtt::publish: [") + topic + F("]=[") + value + F("]"), true);
129  ret = PubSubClient::publish(topic.c_str(), value.c_str(), true);
130  }
131  return ret;
132 }
133 
136 {
137  if (!myData.isGsmActive) {
138  return false;
139  }
140  if (publishInProgress) {
141  return true;
142  }
143  if (myData.isMoving) {
145  } else {
147  }
148  return false;
149 }
150 
153 {
154  MyDbg(F("MQTT:begin"), true);
155  PubSubClient::setServer(myOptions.mqttServer.c_str(), myOptions.mqttPort);
156  PubSubClient::setCallback(mqttCallback);
157  return true;
158 }
159 
162 {
163  if (!myData.isGsmActive) {
164  return;
165  }
166 
167  bool send = false;
168 
169  if (myData.isMoving) {
171  } else {
173  }
174  if (send && !publishInProgress) {
175  publishInProgress = true;
176  if (!PubSubClient::connected()) {
177  for (int i = 0; !PubSubClient::connected() && i < 5; i++) {
178  MyDbg(F("Attempting MQTT connection..."), true);
179  if (PubSubClient::connect(myOptions.mqttName.c_str(), myOptions.mqttUser.c_str(), myOptions.mqttPassword.c_str())) {
180  // mySubscribe(topic_deep_sleep);
181  // mySubscribe(topic_power_on);
182 #ifdef SIM808_CONNECTED
183  // mySubscribe(topic_gps_enabled);
184  // mySubscribe(topic_send_on_move_every);
185  // mySubscribe(topic_send_on_non_move_every);
186 #endif
187  MyDbg(F(" connected"), true);
188  } else {
189  MyDbg((String) F(" Mqtt failed, rc = ") + String(PubSubClient::state()), true);
190  MyDbg(F(" Try again in 5 seconds"), true);
191  MyDelay(5000);
192  MyDbg(F("."), true, false);
193  }
194  }
195  }
196  if (PubSubClient::connected()) {
197  char gpsJson[255];
198 
199  MyDbg(F("Attempting MQTT publishing"), true);
200  myPublish(topic_voltage, String(myData.voltage, 2));
204 #ifndef SIM808_CONNECTED
206 #endif
210 
211 #ifdef SIM808_CONNECTED
215 
216  if (myData.rtcData.lastGps.getAsGpsJson(gpsJson)) {
217  myPublish(topic_gps, gpsJson);
219  }
220 #endif
223  MyDbg(F("mqtt published"), true);
224  MyDelay(5000);
225  }
226  // Set time even on error
228  publishInProgress = false;
229  }
230 }
231 
233 
235 void MyMqtt::mqttCallback(char* topic, byte* payload, unsigned int len)
236 {
237  if (topic == NULL || payload == NULL || len <= 0 || len > 200) {
238  return;
239  }
240 
241  String strTopic = String((char*)topic);
242 
243  payload[len] = '\0';
244  MyDbg((String) F("Message arrived [") + strTopic + F("]:[ "), true);
245  if (len) MyDbg((char *) payload, true);
246  MyDbg(F("]"), true);
247 
248  if (MyMqtt::g_myOptions) {
249  if (strTopic == g_myOptions->mqttName + topic_deep_sleep) {
250  g_myOptions->isDeepSleepEnabled = atoi((char *) payload);
251  MyDbg(strTopic + g_myOptions->isDeepSleepEnabled ? F(" - On") : F(" - Off"), true);
252  }
253  if (strTopic == g_myOptions->mqttName + topic_power_on) {
254  g_myOptions->powerOn = atoi((char *) payload);
255  MyDbg(strTopic + g_myOptions->powerOn ? F(" - On") : F(" - Off"), true);
256  }
257  if (strTopic == g_myOptions->mqttName + topic_gps_enabled) {
258  g_myOptions->isGpsEnabled = atoi((char *) payload);
259  MyDbg(strTopic + g_myOptions->isGpsEnabled ? F(" - Enabled") : F(" - Disabled"), true);
260  }
261  if (strTopic == g_myOptions->mqttName + topic_send_on_move_every) {
262  g_myOptions->mqttSendOnMoveEverySec = atoi((char *) payload);
263  MyDbg(strTopic + " - " + String(g_myOptions->mqttSendOnMoveEverySec), true);
264  }
266  g_myOptions->mqttSendOnNonMoveEverySec = atoi((char *) payload);
267  MyDbg(strTopic + " - " + String(g_myOptions->mqttSendOnNonMoveEverySec), true);
268  }
269  if (strTopic == g_myOptions->mqttName + topic_send_every) {
270  g_myOptions->mqttSendOnNonMoveEverySec = atoi((char *)payload);
271  MyDbg(strTopic + " - " + String(g_myOptions->mqttSendOnNonMoveEverySec), true);
272  }
273  }
274 }
String formatInterval(long secs)
Definition: Utils.h:191
#define topic_power_on
switch power on/off
Definition: Mqtt.h:34
#define topic_send_on_move_every
mqtt send interval on moving
Definition: Mqtt.h:36
#define topic_deep_sleep
Deep sleep on/off.
Definition: Mqtt.h:26
#define topic_mAh
Power consumption.
Definition: Mqtt.h:29
#define topic_send_every
mqtt sending interval
Definition: Mqtt.h:38
bool isGpsEnabled
Is the gps part of the sim808 active?
Definition: Options.h:43
#define topic_send_on_non_move_every
mqtt sending interval on non moving
Definition: Mqtt.h:37
#define topic_voltage
Power supply voltage.
Definition: Mqtt.h:28
String mqttUser
MQTT user.
Definition: Options.h:59
class MyData::RtcData rtcData
Data to store in the RTC memory.
double getLowPowerPowerConsumption()
Definition: Data.h:241
MyOptions myOptions
The global options.
Definition: tracker.ino:57
Definition: Data.h:27
bool begin()
Definition: Mqtt.h:152
void MyDbg(String info, bool fromWebServer=false, bool newline=true)
Definition: Utils.h:94
long mqttLastSentTime
Last mqtt sent timestamp.
Definition: Data.h:51
bool powerOn
Is the GSM power from the DC-DC modul switched on?
Definition: Options.h:41
String mqttId
MQTT ID.
Definition: Options.h:56
double temperature
Current BME280 temperature.
Definition: Data.h:75
MyGps lastGps
Last known gps location without timeout.
Definition: Data.h:35
String mqttPassword
MQTT password.
Definition: Options.h:60
bool myPublish(String subTopic, String value)
Definition: Mqtt.h:116
MyData & myData
Reference to the data.
Definition: Mqtt.h:64
double getPowerConsumption()
Definition: Data.h:231
String WifiGetRssiAsQuality(int rssi)
Definition: Utils.h:119
Definition: Mqtt.h:54
#define topic_temperature
Temperature.
Definition: Mqtt.h:40
#define topic_batt_level
Battery level of the gsm modul.
Definition: Mqtt.h:45
void MyDelay(long millisDelay)
Definition: Utils.h:104
double pressure
Current BME280 pressure.
Definition: Data.h:77
String signalQuality
Quality of the signal.
Definition: Data.h:87
#define topic_gps
Gps longitude, latitude, altitude, moving speed.
Definition: Mqtt.h:48
static void mqttCallback(char *topic, byte *payload, unsigned int len)
Definition: Mqtt.h:235
String batteryVolt
Battery volt of the sim808 module.
Definition: Data.h:89
String mqttServer
MQTT server url.
Definition: Options.h:57
long mqttSendCount
How many time the mqtt data successfully sent.
Definition: Data.h:50
#define topic_signal_quality
Signal quality.
Definition: Mqtt.h:44
long mqttPort
MQTT server port.
Definition: Options.h:58
bool getAsGpsJson(char *gpsJson)
Definition: Gps.h:576
#define topic_mAhLowPower
Power consumption in low power.
Definition: Mqtt.h:30
void handleClient()
Definition: Mqtt.h:161
long secondsSincePowerOn()
Definition: tracker.ino:132
MyMqtt(Client &client, MyOptions &options, MyData &data)
Definition: Mqtt.h:84
bool mySubscribe(String subTopic)
Definition: Mqtt.h:100
bool isMoving
Is moving recognized.
Definition: Data.h:94
double voltage
Current supply voltage.
Definition: Data.h:74
String batteryLevel
Battery level of the sim808 module.
Definition: Data.h:88
long lastMqttPublishSec
Timestamp from the last send.
Definition: Data.h:48
MyOptions & myOptions
Reference to the options.
Definition: Mqtt.h:63
#define topic_gps_distance
Gps distance to last position.
Definition: Mqtt.h:49
String mqttName
MQTT server name.
Definition: Options.h:55
static MyOptions * g_myOptions
Static option pointer for the callback function.
Definition: Mqtt.h:57
bool isGsmActive
Is the sim808 modul connected to a gsm network?
Definition: Data.h:68
#define topic_rssi
Wifi conection quality.
Definition: Mqtt.h:32
MyTime time
The received gps utc time.
Definition: Gps.h:135
#define topic_pressure
Pressure.
Definition: Mqtt.h:42
bool waitingForMqtt()
Definition: Mqtt.h:135
bool secondsElapsed(long &lastCheckSec, const long &intervalSec)
Definition: Utils.h:52
double humidity
Current BME280 humidity.
Definition: Data.h:76
MyData myData
The global collected data.
Definition: tracker.ino:58
#define topic_humidity
Humidity.
Definition: Mqtt.h:41
#define topic_batt_volt
Battery volt of the gsm modul.
Definition: Mqtt.h:46
long mqttSendOnNonMoveEverySec
Send data interval to MQTT server on non moving.
Definition: Options.h:62
bool isDeepSleepEnabled
Should the system go into deepsleep if needed.
Definition: Options.h:49
long mqttSendOnMoveEverySec
Send data interval to MQTT server on moving.
Definition: Options.h:61
long getActiveTimeSec()
Definition: Data.h:193
#define topic_gps_enabled
switch gps on/off
Definition: Mqtt.h:35
bool publishInProgress
Are we publishing right now.
Definition: Mqtt.h:65
double movingDistance
Minimum distance for moving flag.
Definition: Data.h:95
#define topic_alive
Alive time in sec.
Definition: Mqtt.h:31