so, es ist mal wieder etwas weiter gegangen. Danke Sven für die Tipps.
Punkt 2. IP Adresse auflösen funktioniert so nicht im eigenen LAN. Ich hatte vorher schon einmal einen Arduino Sketch, in dem es folgendermaßen klappte:
Code: Alles auswählen
client.setServer("rasp-mosquitto", 1883);
client.setCallback(callback);
Damit funktionierte die Namensauflösung in meinem LAN. Warum das im vorliegendem Framework nicht geht, entzieht sich meiner Kenntnis. Da muss ich wohl erstmal mit der IP Adresse leben.
Das MQTT Handling habe ich jetzt in der Datei CmdTransceiverMQTT.cpp untergebracht:
Code: Alles auswählen
/*
* CmdTransceiverMQTT.cpp
*
*
* Created on: 17.06.2018
* Author: sven
* Modified on: 12.06.2019
*
*
* set/getTurnout over MQTT
*
* MQTT <=> ESP8266
*
* Protocoll:
* Befehl empfangen [setTurnout]
* XXStatus Statusabfrage Weiche XX (XX=00: broadcast)
* XXLinks Weiche XX linker Weg (Rechtsweiche: geradeaus)
* im ProgMode: 1 Step nach links
* XXRechts Weiche XX rechter Weg (Rechtsweiche: abzweigen)
* im ProgMode: 1 Step nach rechts
* XXMitte Weiche XX in Mittenstellung (für Servojustierung)
* XXProgLinksOn Weiche XX linker Weg Programmiermodus ein
* XXProgLinksOff Weiche XX linker Weg Programmiermodus aus (speichern Servowert links)
* XXProgRechtsOn Weiche XX rechter Weg Programmiermodus ein
* XXProgRechtsOff Weiche XX rechter Weg Programmiermodus aus (speichern Servowert rechts)
*
* Status/Zustand senden [getTurnout]
* XXLWlinks Linksweiche XX linker Weg (abzweigen)
* XXLWrechts Linksweiche XX rechter Weg (geradeaus)
* XXRWlinks Rechtsweiche XX linker Weg (geradeaus)
* XXRWrechts Rechtsweiche XX rechter Weg (abzweigen)
* XXLWemcyL Linksweiche XX Aufschneiden links
* XXLWemcyR Linksweiche XX Aufschneiden rechts
* XXRWemcyL Rechtsweiche XX Aufschneiden links
* XXRWemcyR Rechtsweiche XX Aufschneiden rechts
*/
#include "CmdTransceiverMQTT.h"
#include "Utils.h"
#include "Arduino.h"
#include "Controller.h"
#include "Consts.h"
#include "Logger.h"
CmdTransceiverMQTT::CmdTransceiverMQTT(Controller* c, String mqtt_server, String intopic, String outtopic, String mclient, int Addr) : CmdReceiverBase(c) {
client = new PubSubClient(espClient);
_instance = this;
this->server = mqtt_server;
this->intopic = intopic;
this->outtopic = outtopic;
this->turnoutAddr = Addr;
this->mqttclient = mclient;
}
CmdTransceiverMQTT::~CmdTransceiverMQTT() {
}
CmdTransceiverMQTT *CmdTransceiverMQTT::_instance = NULL;
void CmdTransceiverMQTT::sendStatus(String s) {
String Addr = (turnoutAddr < 10) ? '0' + String(turnoutAddr) : String(turnoutAddr);
String payload = Addr + s;
if (!(client->publish(outtopic.c_str(), payload.c_str()))) {
Serial.println("publish failed");
}
}
int CmdTransceiverMQTT::loop() {
String clientId = mqttclient;
String a = (turnoutAddr < 10) ? '0'+String(turnoutAddr) : String(turnoutAddr);
clientId += String(a);
if (initMQTT == 0) {
if (WiFi.status() != WL_CONNECTED) {
return 2000;
}
client->setCallback(mqttcallback);
Serial.println("Callback: mqttcallback");
client->setServer(server.c_str(), 1883);
Serial.println("setServer: " + server + ", Port: " + String(1883));
initMQTT = 1;
} else if (initMQTT == 1) {
if (!client->connected()) {
// try to connect / reconnect
if (client->connect(clientId.c_str())) {
Serial.println(clientId + " is trying to connect to MQTT Server...");
Serial.println(clientId + " connected");
client->subscribe(intopic.c_str(), 1);
Serial.println(clientId + " subscribed to: " + intopic);
} else {
client->loop();
}
} else {
client->loop();
}
}
return 500;
}
void mqttcallback(char* topic, byte* payload, unsigned int length) {
// Serial.print("Message arrived [");
// Serial.print(topic);
// Serial.print("] ");
payload[length] = 0;
String payloads = String((char*)payload);
// Serial.println(payloads);
CmdTransceiverMQTT::_instance->parse(payloads);
}
void CmdTransceiverMQTT::parse(String s) {
int dir = 0;
int Addr = s.toInt(); // string starts with turnoutAddr
if (Addr == 0) {
Serial.print("broadcast ");
Addr = turnoutAddr; // convert broadcast to own addr
}
// String a = (Addr < 10) ? '0'+String(Addr) : String(Addr);
if (Addr == turnoutAddr) {
String status;
if (s.substring(2) == "Links") {
dir = 1;
controller->notifyTurnout(Addr, dir, 0);
status = "Links";
} else if (s.substring(2) == "Rechts") {
dir = 0;
controller->notifyTurnout(Addr, dir, 0);
status = "Rechts";
} else if (s.substring(2) == "Mitte") {
Serial.println("cmd 'Mitte' coming soon");
status = ": n/a Mitte";
} else if (s.substring(2) == "ProgLinksOn") {
Serial.println("cmd 'ProgLinksOn' coming soon");
status = ": n/a Prog";
} else if (s.substring(2) == "ProgLinksOff") {
Serial.println("cmd 'ProgLinksOff' coming soon");
status = ": n/a Prog";
} else if (s.substring(2) == "ProgRechtsOn") {
Serial.println("cmd 'ProgRechtsOn' coming soon");
status = ": n/a Prog";
} else if (s.substring(2) == "ProgRechtsOff") {
Serial.println("cmd 'ProgRechtsOff' coming soon");
status = ": n/a Prog";
} else if (s.substring(2) == "Status") {
Serial.println("cmd 'Status' coming soon");
status = ": n/a Prog";
} else {
Serial.println("unknown cmd '" + s.substring(2) + "'");
status = ": n/a cmd: '" + s.substring(2) + "'";
}
CmdTransceiverMQTT::_instance->sendStatus(status);
}
}
dazu die Datei CmdTransceiverMQTT.h:
Code: Alles auswählen
/*
* CmdTransceiverMQTT.h
*
* Created on: 17.06.2018
* Author: sven
* Modified on: 12.06.2019
*/
#ifdef ESP8266
#include <ESP8266WiFi.h>
#elif ESP32
#include <WiFi.h>
#else
#error "This Arch is not supported"
#endif
#include <WiFiUdp.h>
#include "PubSubClient.h"
#include "CmdReceiverBase.h"
#ifndef CMDTRANSCEIVERMQTT_H_
#define CMDTRANSCEIVERMQTT_H_
class CmdTransceiverMQTT: public CmdReceiverBase {
public:
static CmdTransceiverMQTT* _instance; // Hack for access from PubSubClient
CmdTransceiverMQTT(Controller* c, String mqtt_server, String intopic, String outtopic, String mclient, int Addr);
virtual ~CmdTransceiverMQTT();
virtual int loop();
void parse(String s);
void sendStatus(String s);
private:
WiFiClient espClient;
PubSubClient* client;
String extractString(String payloads, String begin, String end);
String server;
String intopic;
String outtopic;
int initMQTT = 0;
int turnoutAddr = 0;
String mqttclient;
// bool isRighthandTurnout;
};
void mqttcallback(char* topic, byte* payload, unsigned int length);
#endif /* CMDTRANSCEIVERMQTT_H_ */
Die Daten im config.json dazu sind wie folgt:
Code: Alles auswählen
{
"m": "mqtt",
"server": "192.168.1.19",
"intopic": "setTurnout",
"outtopic": "getTurnout",
"client": "ESPTurnoutClient-"
}
Hier ist auch zusätzlich der Basisname des MQTT client angegeben. Für die Eindeutigkeit wird daran noch in CmdTransceiver.cpp die turnout Adresse angehängt. Im config.cpp werden die Parameter so übergeben:
Code: Alles auswählen
} else if (m.equals("mqtt")) {
String server = parser->getValueByKey(idx, "server");
String intopic = parser->getValueByKey(idx, "intopic");
String outtopic = parser->getValueByKey(idx, "outtopic");
String mqttclient = parser->getValueByKey(idx, "client");
controller->registerCmdReceiver(new CmdTransceiverMQTT(controller, server, intopic, outtopic, mqttclient, turnoutAddr));
}
Innerhalb der MQTT Routinen habe ich auch mein eigenes Protokoll zum Ansprechen der Weichen untergebracht. Das macht das Ganze jetzt etwas weniger generisch. Vielleicht gibt es ja noch eine Anregung, wie man das entkoppeln könnte. Funktionieren tut Senden und Empfangen über MQTT auf jeden Fall.
Etwas unglücklich bin ich noch mit der Behandlung der Porterweiterung über MCP23017. Im Moment muss ich noch überall, wo ich den Port einlesen möchte, oder etwas ausgeben möchte, den Pin deklarieren und über GPIOobj darauf zugreifen. Keine Ahnung, ob das auch besser/einfacher geht. Auf jeden Fall funktioniert es erst einmal wie gewünscht.
Beste Grüße
Lorenzo