@Wal:
Das Sollwert-Blockly habe ich getestet, funktioniert. Werde ich wahrscheinlich nutzen. Verbesserung wäre in meinem Fall, ein aktualisieren des Sollwertscript's bei Sollwertänderung. Ich nutze LaCrosse Sensoren für die Temperatur, die über MQTT eingelesen werden. Um Traffic zu vermeiden, sende ich nur bei Temperaturänderung meine Werte, deshalb kann es sein, das bei Sollwertänderung die Steuerung lange braucht um sich anzupassen, da das Script nur bei Temperaturänderung greift. Habe das so mal gelöst:
Blockly.JPG `
Wie liesst du denn di Lacross Sensoren mit MQTT aus? Ich hab auch ein paar davon lese diese aber mit einem Jeelink aus
Gruss
Adrian `
Ich nutze einen Wemos mini mit einem RFM69 und einer 8-fach Relaisplatine für die Steuerung der Heizventile.
Bei interesse kann ich einen eigenen Thread erstellen.
Hardware siehe hier: https://wiki.fhem.de/wiki/LaCrosseGateway_V1.x
Software habe ich zusammenkopiert:
`#define PROGNAME "LaCrosse_MQTT.Gateway" #define PROGVERS "1.00" #define RFM1_SS 15 #define LED_PIN 16 #include <esp8266wifi.h> #include <pubsubclient.h> #include <eeprom.h> #include "Arduino.h" #include "SPI.h" #include "Wire.h" #include "RFMxx.h" #include "SensorBase.h" #include "LaCrosse.h" #include "HashMap.h" #define ENABLE_ACTIVITY_LED 1 // <n>a set to 0 if the blue LED bothers // address of PCF8574 IC #define PCF8574_ADDR (0x20) unsigned long INITIAL_FREQ = 868300; // <n>f initial frequency in kHz (5 kHz steps, 860480 ... 879515) byte TOGGLE_MODE_R1 = 3; // <n>m bits 1: 17.241 kbps, 2 : 9.579 kbps, 4 : 8.842 kbps, 8 : 20.000 kbps (for RFM #1) unsigned long DATA_RATE_R1 = 17241ul; // <n>r use one of the possible data rates (for RFM #1) uint16_t TOGGLE_INTERVAL_R1 = 0; // <n>t 0=no toggle, else interval in seconds (for RFM #1) byte spb = 0; byte tloop[50]; byte tsensor = 0; char output = 0; struct LaCrosse::Frame tframe[50]; String strTopic; String strPayload; const char* ssid = "***"; const char* wpakey = "***"; const char* mqtt_server = "***"; const char* login = "***"; const char* password = "***"; WiFiClient espClient; PubSubClient client(espClient); // --- Variables ------------------------------------------------------------------------------------------------------- String clientName; uint8_t mac[6]; unsigned long lastToggleR1 = 0; unsigned long commandData[32]; RFMxx rfm1(13, 12, 14, RFM1_SS); void SetDataRate(RFMxx *rfm, unsigned long dataRate) { if(rfm->GetDataRate() == 20000 && dataRate != 20000) { rfm->InitializeLaCrosse(); rfm->EnableReceiver(true); } rfm->SetDataRate(dataRate); } void HandleCommandI(unsigned long *commandData, byte length){ word interval = 60; if (length == 3) { interval = commandData[2]; } if (length >= 2) { RFMxx *rfm; switch (commandData[0]) { case 1: rfm = &rfm1; break; default: rfm = NULL; break; } } } // This function is for testing void HandleCommandX(byte value) { if (value == 4) { Serial.println("#1: " + (!rfm1.IsConnected() ? "---" : String(rfm1.GetDataRate()))); } } RFMxx *GetRfmForNumber(byte number) { RFMxx *result = NULL; if (number == 1) { result = &rfm1; } return result; } void HandleCommandO(byte rfmNbr, unsigned long value, unsigned long *data, byte size) { // 50305o (is 0xC481) for RFM12 or 1,4o for RFM69 RFMxx *rfm = GetRfmForNumber(rfmNbr); if (size == 1 && rfm->GetRadioType() == RFMxx::RFM12B) { rfm->SetHFParameter(value); } else if (size == 2 && rfm->GetRadioType() == RFMxx::RFM69CW) { rfm->SetHFParameter(data[0], data[1]); } } void HandleCommandV() { String result = "\n"; result += "["; result += PROGNAME; result += "."; result += PROGVERS; if (rfm1.IsConnected()) { result += " (1="; result += rfm1.GetRadioName(); result += " f:"; result += rfm1.GetFrequency(); if (rfm1.ToggleInterval) { result += " t:"; result += rfm1.ToggleInterval; result += "~"; result += rfm1.ToggleMode; } else { result += " r:"; result += rfm1.GetDataRate(); } result += ")"; } result += " {IP="; if (WiFi.status() == WL_CONNECTED) { result += WiFi.localIP().toString(); } else { result += WiFi.softAPIP().toString(); } result += "}"; result += "]"; Serial.println(result); } bool HandleReceivedData(RFMxx *rfm) { bool result = false; rfm->EnableReceiver(false); byte payload[PAYLOADSIZE]; rfm->GetPayload(payload); rfm->EnableReceiver(true); String data = ""; byte frameLength = 16; // Try LaCrosse like TX29DTH if (data.length() == 0 && LaCrosse::IsValidDataRate(rfm->GetDataRate())) { data = LaCrosse::GetFhemDataString(payload); frameLength = LaCrosse::FRAME_LENGTH; spb = 0; } if (data.length() > 0) { result = true; if (client.connected()){ switch (spb) { case 0: { byte x = 0; struct LaCrosse::Frame frame; LaCrosse::DecodeFrame(payload, &frame); for (int i = 0; i < tsensor; i++) { if (frame.ID == tloop[i]) { x = 1; if ((tframe[i].ID != frame.ID) || (tframe[i].Temperature != frame.Temperature) || (tframe[i].Humidity != frame.Humidity) || (tframe[i].WeakBatteryFlag != frame.WeakBatteryFlag) || (tframe[i].NewBatteryFlag != frame.NewBatteryFlag)) { String tID = ""; String tTemp = ""; String tHum = ""; String tsen = String(i); tID = frame.ID; tTemp = frame.Temperature; tHum = frame.Humidity; String tID0 = "/lacrosse/sensor/" + tsen + "/id/"; String tID1 = "/lacrosse/sensor/" + tsen + "/temperatur/"; String tID2 = "/lacrosse/sensor/" + tsen + "/humidity/"; String tID3 = "/lacrosse/sensor/" + tsen + "/battery/"; client.publish(tID0.c_str(), tID.c_str()); client.publish(tID1.c_str(), tTemp.c_str()); client.publish(tID2.c_str(), tHum.c_str()); if (frame.WeakBatteryFlag) { client.publish(tID3.c_str(), "Low"); } else if (frame.NewBatteryFlag) { client.publish(tID3.c_str(), "New"); } else client.publish(tID3.c_str(), "OK"); tframe[i].ID = frame.ID; tframe[i].Temperature = frame.Temperature; tframe[i].Humidity = frame.Humidity; tframe[i].WeakBatteryFlag = frame.WeakBatteryFlag; tframe[i].NewBatteryFlag = frame.NewBatteryFlag; } break; } } if (x == 0){ if (frame.NewBatteryFlag) { } else { tloop[tsensor] = frame.ID; tsensor ++; EEPROM.begin(512); EEPROM.write(tsensor, frame.ID); EEPROM.write(0, tsensor); EEPROM.commit(); Serial.println(EEPROM.read(0)); EEPROM.end(); } } } default: break; } } } return result; } void HandleDataRateToggle(RFMxx *rfm, unsigned long *lastToggle, unsigned long *dataRate) { if (rfm->ToggleInterval > 0) { // After about 50 days millis() will overflow to zero if (millis() < *lastToggle) { *lastToggle = 0; } if (millis() > *lastToggle + rfm->ToggleInterval * 1000 && rfm->ToggleMode > 0) { // Bits 1: 17.241 kbps, 2 : 9.579 kbps, 4 : 8.842 kbps, 8 : 20.000 kbps HashMap <unsigned 4/long,/unsigned="">dataRates; if (rfm->ToggleMode & 1) { dataRates.Put(17241, 17241); } if (rfm->ToggleMode & 2) { dataRates.Put(9579, 9579); if (dataRates.Size() > 0) { *dataRates.GetValuePointerAt(dataRates.Size() - 2) = 9579; } } if (rfm->ToggleMode & 4) { dataRates.Put(8842, 8842); if (dataRates.Size() > 0) { *dataRates.GetValuePointerAt(dataRates.Size() - 2) = 8842; } } if (rfm->ToggleMode & 8) { dataRates.Put(20000, 20000); if (dataRates.Size() > 0) { *dataRates.GetValuePointerAt(dataRates.Size() - 2) = 20000; } } *dataRates.GetValuePointerAt(dataRates.Size() - 1) = dataRates.GetKeyAt(0); *dataRate = dataRates.Get(rfm->GetDataRate(), 0); if (*dataRate == 0) { *dataRate = 17241; } SetDataRate(rfm, *dataRate); *lastToggle = millis(); } } } void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, wpakey); clientName += "wemos_lacrosse_"; WiFi.macAddress(mac); clientName += macToStr(mac); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } // =========================================================== // Callback Funktion von MQTT. Die Funktion wird aufgerufen // wenn ein Wert empfangen wurde. // =========================================================== void callback(char* topic, byte* payload, unsigned int length) { payload[length] = '\0'; strTopic = String((char*)topic); if (strTopic.substring(9,17) == "nathalie") { int rel = strTopic.substring(21).toInt(); String value = String((char*)payload); Serial.print(strTopic); Serial.print("="); Serial.println(value); if(value == "false") { bitSet(output, rel-1); } else { bitClear(output, rel-1); } char k = 0; // Temporere Variable fuer XOR Operation output ^= bitSet(k, rel-1); // Umschalten den gewaelten Relay mit XOR Wire.beginTransmission(PCF8574_ADDR); //Öffnen der Verbindung Wire.write(~output); // Byte Invertieren, bei "0" sind Relais an Wire.endTransmission(); // Stop-Bedingung I2C } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect((char*) clientName.c_str(), login, password)) { Serial.println("connected"); client.publish("/heizung/nathalie/rel1","false"); client.publish("/heizung/nathalie/rel2","false"); client.publish("/heizung/nathalie/rel3","false"); client.publish("/heizung/nathalie/rel4","false"); client.publish("/heizung/nathalie/rel5","false"); client.publish("/heizung/nathalie/rel6","false"); client.publish("/heizung/nathalie/rel7","false"); client.publish("/heizung/nathalie/rel8","false"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } String macToStr(const uint8_t* mac){ String result; for (int i = 0; i < 6; ++i) { result += String(mac[i], 16); if (i < 5){ result += ':'; } } return result; } void setup(void) { Serial.begin(57600); delay(1000); Serial.println(); Serial.println("Read EEprom"); EEPROM.begin(512); // for (int i = 0; i < 5; i++) { // EEPROM.write(i, 0); // } // EEPROM.commit(); tsensor = EEPROM.read(0); Serial.println(tsensor); for (int i = 0; i < tsensor; i++) { tloop[i] = EEPROM.read(i + 1); Serial.println(tloop[i]); } EEPROM.end(); Serial.println("Read EEprom ready!"); SPI.begin(); delay(250); rfm1.Begin(); rfm1.ToggleMode = TOGGLE_MODE_R1; rfm1.ToggleInterval = TOGGLE_INTERVAL_R1; lastToggleR1 = millis(); Serial.println("Searching RFMs"); if (rfm1.IsConnected()) { rfm1.InitializeLaCrosse(); rfm1.SetFrequency(INITIAL_FREQ); SetDataRate(&rfm1, DATA_RATE_R1); rfm1.EnableReceiver(true); Serial.print("Radio #1 found: "); Serial.println(rfm1.GetRadioName()); } setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); Wire.begin(); //Initialisieren der I2C Verbindung. MUSS im Setup aufgerufen werden. Wire.beginTransmission(PCF8574_ADDR); // IC-Adresse Wire.write(~output); // Byte senden Daten werden Inveriert Wire.endTransmission(); // I2C Stopbedingung delay(1000); HandleCommandV(); Serial.println("Setup completely done"); } byte HandleDataReception() { byte receivedPackets = 0; if (rfm1.IsConnected()) { rfm1.Receive(); if (rfm1.PayloadIsReady()) { if (HandleReceivedData(&rfm1)) { receivedPackets++; } } } return receivedPackets; } void HandleDataRate() { if (rfm1.IsConnected()) { HandleDataRateToggle(&rfm1, &lastToggleR1, &DATA_RATE_R1); } } // ********************************************************************** void loop(void) { if (!client.connected()) { reconnect(); } client.loop(); // Handle the data reception // ------------------------- byte receivedPackets = HandleDataReception(); // Handle the data rate // -------------------- HandleDataRate(); }</unsigned></n></n></n></n></n></eeprom.h></pubsubclient.h></esp8266wifi.h>`  [/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]