Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MyGatewayTransportMQTTClient.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * The MySensors Arduino library handles the wireless radio link and protocol
  3. * between your home built sensors/actuators and HA controller of choice.
  4. * The sensors forms a self healing radio network with optional repeaters. Each
  5. * repeater and gateway builds a routing tables in EEPROM which keeps track of the
  6. * network topology allowing messages to be routed to nodes.
  7. *
  8. * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
  9. * Copyright (C) 2013-2018 Sensnology AB
  10. * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
  11. *
  12. * Documentation: http://www.mysensors.org
  13. * Support Forum: http://forum.mysensors.org
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License
  17. * version 2 as published by the Free Software Foundation.
  18. */
  19. // Topic structure: MY_MQTT_PUBLISH_TOPIC_PREFIX/NODE-ID/SENSOR-ID/CMD-TYPE/ACK-FLAG/SUB-TYPE
  20. #include "MyGatewayTransport.h"
  21. // housekeeping, remove for 3.0.0
  22. #ifdef MY_ESP8266_SSID
  23. #warning MY_ESP8266_SSID is deprecated, use MY_WIFI_SSID instead!
  24. #define MY_WIFI_SSID MY_ESP8266_SSID
  25. #undef MY_ESP8266_SSID // cleanup
  26. #endif
  27. #ifdef MY_ESP8266_PASSWORD
  28. #warning MY_ESP8266_PASSWORD is deprecated, use MY_WIFI_PASSWORD instead!
  29. #define MY_WIFI_PASSWORD MY_ESP8266_PASSWORD
  30. #undef MY_ESP8266_PASSWORD // cleanup
  31. #endif
  32. #ifdef MY_ESP8266_BSSID
  33. #warning MY_ESP8266_BSSID is deprecated, use MY_WIFI_BSSID instead!
  34. #define MY_WIFI_BSSID MY_ESP8266_BSSID
  35. #undef MY_ESP8266_BSSID // cleanup
  36. #endif
  37. #ifdef MY_ESP8266_HOSTNAME
  38. #warning MY_ESP8266_HOSTNAME is deprecated, use MY_HOSTNAME instead!
  39. #define MY_HOSTNAME MY_ESP8266_HOSTNAME
  40. #undef MY_ESP8266_HOSTNAME // cleanup
  41. #endif
  42. #ifndef MY_WIFI_BSSID
  43. #define MY_WIFI_BSSID NULL
  44. #endif
  45. #if defined MY_CONTROLLER_IP_ADDRESS
  46. IPAddress _brokerIp(MY_CONTROLLER_IP_ADDRESS);
  47. #endif
  48. #if defined(MY_IP_ADDRESS)
  49. IPAddress _MQTT_clientIp(MY_IP_ADDRESS);
  50. #if defined(MY_IP_GATEWAY_ADDRESS)
  51. IPAddress _gatewayIp(MY_IP_GATEWAY_ADDRESS);
  52. #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
  53. // Assume the gateway will be the machine on the same network as the local IP
  54. // but with last octet being '1'
  55. IPAddress _gatewayIp(_MQTT_clientIp[0], _MQTT_clientIp[1], _MQTT_clientIp[2], 1);
  56. #endif /* End of MY_IP_GATEWAY_ADDRESS */
  57. #if defined(MY_IP_SUBNET_ADDRESS)
  58. IPAddress _subnetIp(MY_IP_SUBNET_ADDRESS);
  59. #elif defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
  60. IPAddress _subnetIp(255, 255, 255, 0);
  61. #endif /* End of MY_IP_SUBNET_ADDRESS */
  62. #endif /* End of MY_IP_ADDRESS */
  63. #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
  64. #define EthernetClient WiFiClient
  65. #elif defined(MY_GATEWAY_LINUX)
  66. // Nothing to do here
  67. #else
  68. uint8_t _MQTT_clientMAC[] = { MY_MAC_ADDRESS };
  69. #endif /* End of MY_GATEWAY_ESP8266 */
  70. #if defined(MY_GATEWAY_TINYGSM)
  71. #if defined(MY_GSM_RX) && defined(MY_GSM_TX)
  72. SoftwareSerial SerialAT(MY_GSM_RX, MY_GSM_TX);
  73. #endif
  74. static TinyGsm modem(SerialAT);
  75. static TinyGsmClient _MQTT_gsmClient(modem);
  76. static PubSubClient _MQTT_client(_MQTT_gsmClient);
  77. #if defined(MY_GSM_BAUDRATE)
  78. uint32_t rate = MY_GSM_BAUDRATE;
  79. #else /* Else part of MY_GSM_BAUDRATE */
  80. uint32_t rate = 0;
  81. #endif /* End of MY_GSM_BAUDRATE */
  82. #else /* Else part of MY_GATEWAY_TINYGSM */
  83. static EthernetClient _MQTT_ethClient;
  84. static PubSubClient _MQTT_client(_MQTT_ethClient);
  85. #endif /* End of MY_GATEWAY_TINYGSM */
  86. static bool _MQTT_connecting = true;
  87. static bool _MQTT_available = false;
  88. static MyMessage _MQTT_msg;
  89. bool gatewayTransportSend(MyMessage &message)
  90. {
  91. if (!_MQTT_client.connected()) {
  92. return false;
  93. }
  94. setIndication(INDICATION_GW_TX);
  95. char *topic = protocolFormatMQTTTopic(MY_MQTT_PUBLISH_TOPIC_PREFIX, message);
  96. GATEWAY_DEBUG(PSTR("GWT:TPS:TOPIC=%s,MSG SENT\n"), topic);
  97. #if defined(MY_MQTT_CLIENT_PUBLISH_RETAIN)
  98. bool retain = mGetCommand(message) == C_SET ||
  99. (mGetCommand(message) == C_INTERNAL && message.type == I_BATTERY_LEVEL);
  100. #else
  101. bool retain = false;
  102. #endif /* End of MY_MQTT_CLIENT_PUBLISH_RETAIN */
  103. return _MQTT_client.publish(topic, message.getString(_convBuffer), retain);
  104. }
  105. void incomingMQTT(char *topic, uint8_t *payload, unsigned int length)
  106. {
  107. GATEWAY_DEBUG(PSTR("GWT:IMQ:TOPIC=%s, MSG RECEIVED\n"), topic);
  108. _MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length);
  109. setIndication(INDICATION_GW_RX);
  110. }
  111. bool reconnectMQTT(void)
  112. {
  113. GATEWAY_DEBUG(PSTR("GWT:RMQ:MQTT RECONNECT\n"));
  114. // Attempt to connect
  115. if (_MQTT_client.connect(MY_MQTT_CLIENT_ID
  116. #if defined(MY_MQTT_USER) && defined(MY_MQTT_PASSWORD)
  117. , MY_MQTT_USER, MY_MQTT_PASSWORD
  118. #endif
  119. )) {
  120. GATEWAY_DEBUG(PSTR("GWT:RMQ:MQTT CONNECTED\n"));
  121. // Send presentation of locally attached sensors (and node if applicable)
  122. presentNode();
  123. // Once connected, publish an announcement...
  124. //_MQTT_client.publish("outTopic","hello world");
  125. // ... and resubscribe
  126. _MQTT_client.subscribe(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "/+/+/+/+/+");
  127. return true;
  128. }
  129. return false;
  130. }
  131. bool gatewayTransportConnect(void)
  132. {
  133. #if defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_ESP32)
  134. while (WiFi.status() != WL_CONNECTED) {
  135. wait(500);
  136. GATEWAY_DEBUG(PSTR("GWT:TPC:CONNECTING...\n"));
  137. }
  138. GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%s\n"),WiFi.localIP().toString().c_str());
  139. #elif defined(MY_GATEWAY_LINUX)
  140. #if defined(MY_IP_ADDRESS)
  141. _MQTT_ethClient.bind(_MQTT_clientIp);
  142. #endif /* End of MY_IP_ADDRESS */
  143. #elif defined(MY_GATEWAY_TINYGSM)
  144. GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%s\n"), modem.getLocalIP().c_str());
  145. #else
  146. #if defined(MY_IP_ADDRESS)
  147. Ethernet.begin(_MQTT_clientMAC, _MQTT_clientIp);
  148. #else /* Else part of MY_IP_ADDRESS */
  149. // Get IP address from DHCP
  150. if (!Ethernet.begin(_MQTT_clientMAC)) {
  151. GATEWAY_DEBUG(PSTR("!GWT:TPC:DHCP FAIL\n"));
  152. _MQTT_connecting = false;
  153. return false;
  154. }
  155. #endif /* End of MY_IP_ADDRESS */
  156. GATEWAY_DEBUG(PSTR("GWT:TPC:IP=%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "\n"),
  157. Ethernet.localIP()[0],
  158. Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]);
  159. // give the Ethernet interface a second to initialize
  160. delay(1000);
  161. #endif
  162. return true;
  163. }
  164. bool gatewayTransportInit(void)
  165. {
  166. _MQTT_connecting = true;
  167. #if defined(MY_GATEWAY_TINYGSM)
  168. #if !defined(MY_GSM_BAUDRATE)
  169. rate = TinyGsmAutoBaud(SerialAT);
  170. #endif /* End of MY_GSM_BAUDRATE */
  171. SerialAT.begin(rate);
  172. delay(3000);
  173. modem.restart();
  174. #if defined(MY_GSM_PIN) && !defined(TINY_GSM_MODEM_ESP8266)
  175. modem.simUnlock(MY_GSM_PIN);
  176. #endif /* End of MY_GSM_PIN */
  177. #ifndef TINY_GSM_MODEM_ESP8266
  178. if (!modem.waitForNetwork()) {
  179. GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n"));
  180. while (true);
  181. }
  182. GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n"));
  183. if (!modem.gprsConnect(MY_GSM_APN, MY_GSM_USR, MY_GSM_PSW)) {
  184. GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n"));
  185. while (true);
  186. }
  187. GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n"));
  188. delay(1000);
  189. #else /* Else part of TINY_GSM_MODEM_ESP8266 */
  190. if (!modem.networkConnect(MY_GSM_SSID, MY_GSM_PSW)) {
  191. GATEWAY_DEBUG(PSTR("!GWT:TIN:ETH FAIL\n"));
  192. while (true);
  193. }
  194. GATEWAY_DEBUG(PSTR("GWT:TIN:ETH OK\n"));
  195. delay(1000);
  196. #endif /* End of TINY_GSM_MODEM_ESP8266 */
  197. #endif /* End of MY_GATEWAY_TINYGSM */
  198. #if defined(MY_CONTROLLER_IP_ADDRESS)
  199. _MQTT_client.setServer(_brokerIp, MY_PORT);
  200. #else
  201. _MQTT_client.setServer(MY_CONTROLLER_URL_ADDRESS, MY_PORT);
  202. #endif /* End of MY_CONTROLLER_IP_ADDRESS */
  203. _MQTT_client.setCallback(incomingMQTT);
  204. #if defined(MY_GATEWAY_ESP8266)
  205. // Turn off access point
  206. WiFi.mode(WIFI_STA);
  207. #if defined(MY_HOSTNAME)
  208. WiFi.hostname(MY_HOSTNAME);
  209. #endif /* End of MY_ESP8266_HOSTNAME */
  210. #if defined(MY_IP_ADDRESS)
  211. WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp);
  212. #endif /* End of MY_IP_ADDRESS */
  213. #ifndef MY_WIFI_BSSID
  214. #define MY_WIFI_BSSID NULL
  215. #endif
  216. (void)WiFi.begin(MY_WIFI_SSID, MY_WIFI_PASSWORD, 0, MY_WIFI_BSSID);
  217. #elif defined(MY_GATEWAY_ESP32)
  218. // Turn off access point
  219. WiFi.mode(WIFI_STA);
  220. #if defined(MY_HOSTNAME)
  221. WiFi.setHostname(MY_HOSTNAME);
  222. #endif /* End of MY_HOSTNAME */
  223. #if defined(MY_IP_ADDRESS)
  224. WiFi.config(_MQTT_clientIp, _gatewayIp, _subnetIp);
  225. #endif /* End of MY_IP_ADDRESS */
  226. #ifndef MY_WIFI_BSSID
  227. #define MY_WIFI_BSSID NULL
  228. #endif
  229. (void)WiFi.begin(MY_WIFI_SSID, MY_WIFI_PASSWORD, 0, MY_WIFI_BSSID);
  230. #endif
  231. gatewayTransportConnect();
  232. _MQTT_connecting = false;
  233. return true;
  234. }
  235. bool gatewayTransportAvailable(void)
  236. {
  237. if (_MQTT_connecting) {
  238. return false;
  239. }
  240. //keep lease on dhcp address
  241. //Ethernet.maintain();
  242. if (!_MQTT_client.connected()) {
  243. //reinitialise client
  244. if (gatewayTransportConnect()) {
  245. reconnectMQTT();
  246. }
  247. return false;
  248. }
  249. _MQTT_client.loop();
  250. return _MQTT_available;
  251. }
  252. MyMessage & gatewayTransportReceive(void)
  253. {
  254. // Return the last parsed message
  255. _MQTT_available = false;
  256. return _MQTT_msg;
  257. }