MqttClient.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include <MqttClient.h>
  2. #include <TokenIterator.h>
  3. #include <UrlTokenBindings.h>
  4. #include <IntParsing.h>
  5. #include <ArduinoJson.h>
  6. #include <WiFiClient.h>
  7. MqttClient::MqttClient(Settings& settings, MiLightClient*& milightClient)
  8. : milightClient(milightClient),
  9. settings(settings)
  10. {
  11. String strDomain = settings.mqttServer();
  12. this->domain = new char[strDomain.length() + 1];
  13. strcpy(this->domain, strDomain.c_str());
  14. this->mqttClient = new PubSubClient(tcpClient);
  15. }
  16. MqttClient::~MqttClient() {
  17. mqttClient->disconnect();
  18. delete this->domain;
  19. }
  20. void MqttClient::begin() {
  21. #ifdef MQTT_DEBUG
  22. printf_P(
  23. PSTR("MqttClient - Connecting to: %s\nparsed:%s:%u\n"),
  24. settings._mqttServer.c_str(),
  25. settings.mqttServer().c_str(),
  26. settings.mqttPort()
  27. );
  28. #endif
  29. mqttClient->setServer(this->domain, settings.mqttPort());
  30. mqttClient->setCallback(
  31. [this](char* topic, byte* payload, int length) {
  32. this->publishCallback(topic, payload, length);
  33. }
  34. );
  35. reconnect();
  36. }
  37. void MqttClient::reconnect() {
  38. if (! mqttClient->connected()) {
  39. #ifdef MQTT_DEBUG
  40. Serial.println("MqttClient - econnecting");
  41. #endif
  42. char nameBuffer[30];
  43. sprintf_P(nameBuffer, PSTR("milight-hub-%u"), ESP.getChipId());
  44. if (mqttClient->connect(nameBuffer)) {
  45. subscribe();
  46. } else {
  47. Serial.println(F("ERROR: Failed to connect to MQTT server"));
  48. }
  49. }
  50. }
  51. void MqttClient::handleClient() {
  52. reconnect();
  53. mqttClient->loop();
  54. }
  55. void MqttClient::subscribe() {
  56. String topic = settings.mqttTopicPattern;
  57. topic.replace(":device_id", "+");
  58. topic.replace(":group_id", "+");
  59. topic.replace(":device_type", "+");
  60. mqttClient->subscribe(topic.c_str());
  61. }
  62. void MqttClient::publishCallback(char* topic, byte* payload, int length) {
  63. uint16_t deviceId = 0;
  64. uint8_t groupId = 0;
  65. MiLightRadioConfig* config = &MilightRgbCctConfig;
  66. char cstrPayload[length + 1];
  67. cstrPayload[length] = 0;
  68. memcpy(cstrPayload, payload, sizeof(byte)*length);
  69. #ifdef MQTT_DEBUG
  70. printf_P(PSTR("MqttClient - Got message on topic: %s\n%s\n"), topic, cstrPayload);
  71. #endif
  72. char topicPattern[settings.mqttTopicPattern.length()];
  73. strcpy(topicPattern, settings.mqttTopicPattern.c_str());
  74. TokenIterator patternIterator(topicPattern, settings.mqttTopicPattern.length(), '/');
  75. TokenIterator topicIterator(topic, strlen(topic), '/');
  76. UrlTokenBindings tokenBindings(patternIterator, topicIterator);
  77. if (tokenBindings.hasBinding("device_id")) {
  78. deviceId = parseInt<uint16_t>(tokenBindings.get("device_id"));
  79. }
  80. if (tokenBindings.hasBinding("group_id")) {
  81. groupId = parseInt<uint16_t>(tokenBindings.get("group_id"));
  82. }
  83. if (tokenBindings.hasBinding("device_type")) {
  84. config = MiLightRadioConfig::fromString(tokenBindings.get("device_type"));
  85. }
  86. StaticJsonBuffer<400> buffer;
  87. JsonObject& obj = buffer.parseObject(cstrPayload);
  88. #ifdef MQTT_DEBUG
  89. printf_P(PSTR("MqttClient - device %04X, group %u\n"), deviceId, groupId);
  90. #endif
  91. milightClient->prepare(*config, deviceId, groupId);
  92. milightClient->update(obj);
  93. }