Raumgerät Light für UDP-Verbindung mit BSB-LAN Adapter

Begonnen von fabulous, 26 April 2020, 12:50:53

Vorheriges Thema - Nächstes Thema

fabulous

Moin,

in Anlehung an die "Raumgerät Light"-Variante von Andreas29 (https://forum.fhem.de/index.php/topic,91867.0.html) habe ich mir eine Lösung geschaffen, die mit dem BSB-LAN Adapter (https://forum.fhem.de/index.php/topic,29762.0.html) via UDP kommuniziert.

Grundlage ist ein Arduino Uno mit Ethernet Shield, einem 20x4 LCD sowie einem Taster als Präsenztaste.

Aus dem Arduino läuft einen eigenständiger Code; beim BSB-LAN Adapter müssen die "Custom"-Dateien entsprechend erweitert werden.

Code und Fotos stelle ich nachfolgend ein.

Gruß
Fabian

fabulous


fabulous

#2
Code RGLU.ino, v0.01


//RaumGerät Light UDP v0.01
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <LiquidCrystal_I2C.h>

//IP adress and port of RG
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 42);
unsigned int port = 28001;
//IP adress and UDP port of BSB-LAN adapter
IPAddress RxIP(192, 168, 0, 88);
unsigned int RxUDPport = 28000;
const int udp_buff_size = 16;
char RxBuffer[udp_buff_size];
unsigned long t_act, t_old;

int maxtry = 5; //maximum tries for connection etc. with BSB-LAN

struct pv_Rx {
  int par;
  int val;
};

struct pv_RG {
  double OT;  //outside temperature
  double RT;  //room temperature
  double WT;  //water temperature
  double RT_t;  //room temperature, target
  double RT_c;  //room temperature, comfort
  double RT_r;  //room temperature, reduced
  boolean presence_state;
  boolean presence_error;
  boolean water_state;
  boolean burner_state;
};

struct pv_RG dat;
struct pv_Rx pv;
unsigned int sep_pos = 5;
unsigned int TM_size = 16;
char ps[5];
char vs[10];
boolean presence_button_pressed;
boolean button_pres_stat_act;
boolean button_pres_stat_old;
boolean isconnected;
boolean wait;

EthernetUDP Udp;

LiquidCrystal_I2C LCD(39, 20,4);

byte degree[8] = {B01110, B01010, B01110, B00000, B00000, B00000, B00000, B00000};
byte sun[8] = {0b00100, 0b10101, 0b01110, 0b11011, 0b01110, 0b10101, 0b00100, 0b00000};
byte moon[8] = {0b00111, 0b01110, 0b11100, 0b11100, 0b11100, 0b01110, 0b00111, 0b00000};
byte snow[8] = {0b01010, 0b00100, 0b10101, 0b01110, 0b10101, 0b00100, 0b01010, 0b00000};
byte flame[8] = {0b00010, 0b00100, 0b01100, 0b01110, 0b01010, 0b01010, 0b00100, 0b11011};
byte water[8] = {0b00000, 0b01110, 0b00101, 0b11111, 0b10001, 0b10000, 0b00000, 0b00000};

void requestBC() {
  //sprintf(TxBuffer, "%.7s", "REQBC@1");
  Udp.beginPacket(RxIP, RxUDPport);
  //Udp.print(TxBuffer);
  Udp.print("REQBC@0000000001");
  Udp.endPacket();
}

void RxUDP() { 
  int RxPacket = Udp.parsePacket();
  if(RxPacket) {
    Udp.read(RxBuffer, udp_buff_size);
    isconnected = true;
  }
}

//determine presence state
void determine_presence_state() {
  if (dat.RT_t == dat.RT_c) {
    dat.presence_state = true;
    dat.presence_error = false;
  }
  if (dat.RT_t == dat.RT_r) {
    dat.presence_state = false;
    dat.presence_error = false;
  }
  if (dat.RT_t != dat.RT_c && dat.RT_t != dat.RT_r)
    dat.presence_error = true;
}

void get_button_state() {
  button_pres_stat_act = digitalRead(8);
  //Pin uses PULL UP resistance -> "not pressed" means HIGH
  if (button_pres_stat_act && button_pres_stat_old) { //not pressed and not pressed before
    presence_button_pressed = false; //do not detect as pressed
  }
  if (!button_pres_stat_act && !button_pres_stat_old) { //pressed and pressed before
    presence_button_pressed = false; //do not detect as pressed
  }
  if (button_pres_stat_act && !button_pres_stat_old) { //not pressed and pressed before
    presence_button_pressed = false; //do not detect as pressed
  }
  if (!button_pres_stat_act && button_pres_stat_old) { //pressed and not pressed before
    presence_button_pressed = true; //detect as pressed
    delay(100);  //debounce
  }
  button_pres_stat_old = button_pres_stat_act;
}

struct pv_Rx GetParamVal() {
  //all TM has to be:
  //[5 character]@[10 character]
  //5 character = parameter number acc. to RVS43.122, 0 at LSB if needed
  //@ = separator
  //10 character = value
  char ps[5];
  char vs[10];
  int i, j;
  struct pv_Rx pv;
  pv.par = 0;
  pv.val = 0;
  //get parameter
  j=0;
  for(i=0;i<sep_pos; i++){
    ps[j] = RxBuffer[i];
    j++;
  }
  pv.par = atoi(ps);
  //get value
  j=0;
  for(i=sep_pos+1;i<TM_size; i++){
    vs[j] = RxBuffer[i];
    j++;
  }
  vs[j]='\0'; //I don't know why this is necessary, maybe some char/pointer thing...
  pv.val = atoi(vs);
  return pv;
}

void EvalParamVal() {
  pv = GetParamVal();
  if (pv.par > 0) {
    Serial.print(pv.par);
    Serial.print("@");
    Serial.println(pv.val);
  }
  if (pv.par == 8700) //outside temperature
    dat.OT = 0.1 * pv.val;
  if (pv.par == 8740) //room temperature
    dat.RT = 0.1 * pv.val;
  if (pv.par == 8830) //water temperature
    dat.WT = 0.1 * pv.val;
  if (pv.par == 8741) //room temperature, target
    dat.RT_t = 0.1 * pv.val;
  if (pv.par == 710) //room temperature, comfort
    dat.RT_c = 0.1 * pv.val;
  if (pv.par == 712) //room temperature, reduced
    dat.RT_r = 0.1 * pv.val;
     
  if (pv.par == 8300) {//burner state
    //evaluate burner state
    if (pv.val == 1)
      dat.burner_state = true;
    else
      dat.burner_state = false;
  }
   
  if (pv.par == 8003) {//water heating state
    //evaluate TWW state
    if (pv.val == 69 || (pv.val >= 92 && pv.val <= 97))
      dat.water_state = true;
    else
      dat.water_state = false;   
  }
}

void UpdateLCD(){
  LCD.setCursor(0,0);
  LCD.print("Au\xE2");
  LCD.print("entemp: ");
  LCD.print(dat.OT);
  LCD.setCursor(15,0);
  LCD.print(char(0));
  LCD.print("C");
 
  LCD.setCursor(0,1);
  LCD.print("Raumtemp : ");
  LCD.print(dat.RT);
  LCD.setCursor(15,1);
  LCD.print(char(0));
  LCD.print("C");
 
  LCD.setCursor(0,2);
  LCD.print("TWW Temp : ");
  LCD.print(dat.WT);
  LCD.setCursor(15,2);
  LCD.print(char(0));
  LCD.print("C");

  //presence state
  if (dat.presence_state) {
    LCD.setCursor(19,0);
    LCD.print(char(1)); //sun enable
    LCD.setCursor(19,1);
    LCD.print(" "); //moon disable
  }
  else {
    LCD.setCursor(19,0);
    LCD.print(" "); //sun disable
    LCD.setCursor(19,1);
    LCD.print(char(2)); //moon enable
  }
  //presence error
  if (dat.presence_error) {
    LCD.setCursor(19,0);
    LCD.print("#"); //sun disable
    LCD.setCursor(19,1);
    LCD.print("#"); //moon disable
  }
   
  //burner state
  LCD.setCursor(19,3);
  if (dat.burner_state)
    LCD.print(char(4)); //flame enable
  else
    LCD.print(" "); //flame disable
   
  //water state
  LCD.setCursor(19,2);
  if (dat.water_state)
    LCD.print(char(5)); //water enable
  else
    LCD.print(" "); //water disable
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(8, INPUT_PULLUP);
  presence_button_pressed = false;
  button_pres_stat_act = true;
  button_pres_stat_old = true;
  isconnected = false;
  int i;

  Ethernet.begin(mac,ip);
  delay(500);
  Udp.begin(port);
  delay(500);

  Serial.begin(115200);
  delay(500);

  LCD.init();
  LCD.clear();
  LCD.backlight();
  LCD.createChar(0, degree);
  LCD.createChar(1, sun);
  LCD.createChar(2, moon);
  LCD.createChar(3, snow);
  LCD.createChar(4, flame);
  LCD.createChar(5, water);

  LCD.setCursor(0,0);
  LCD.print("Connecting...");
  delay(500);
  for (i=0; i<=maxtry; i++) {
    //request first BC to check connection
    requestBC();
    delay(1000);
    RxUDP(); //sets "isconnected" to true if UDP packet received
    Serial.println(i);
    if (isconnected)
      break;
  }
  //determine_presence_state();
  LCD.setCursor(0,0);
  if (!isconnected) {
    LCD.print("Connection failed!  ");
    LCD.setCursor(0,3);
    LCD.print("Error #503");
    delay(2000);
  }
  else {
    LCD.print("Connected!        ");
    delay(2000);
  }
  LCD.clear();

  UpdateLCD();
  t_old=millis();
}

void loop() {
  int i;
  //check for new UDP packets
  RxUDP();
  //evaluate what has been received
  EvalParamVal();
  //determine presence state based on room target temperature
  determine_presence_state();
  //check if presence button ("Präsenztaste") was pressed on RG
  get_button_state();
  if (presence_button_pressed) {
    double RT_t_old = dat.RT_t;
    LCD.setCursor(0,3);
    LCD.print("Bitte warten...");
    //transmit request to BSB_LAN for change of presence_state
    Udp.beginPacket(RxIP, RxUDPport);
    Udp.print("!PRES@0000000001");
    Udp.endPacket();
    wait = true;   
    for (i=0; i<=maxtry; i++) {
      if (RT_t_old == dat.RT_t) {//if no change
        //wait for RT_t to be updated
        RxUDP(); //sets "isconnected" to true if UDP packet received
        EvalParamVal();
        delay(2000);
      }
      else {
        wait = false;
        LCD.setCursor(0,3);
        LCD.print("               ");
        break;
      }
      //Serial.println(i);
    }
    //invert presence state
    if (!wait) {//target room teperature was changed by heating before max try was reached
      dat.presence_state = !dat.presence_state;
      //update LCD
      LCD.clear();
      LCD.setCursor(0,0);
      if (dat.presence_state && !dat.presence_error) {
        LCD.print("Pr\xE1");
        LCD.print("senz: EIN");
        LCD.setCursor(0,1);
        LCD.print("Heizen auf");
        LCD.setCursor(0,2);
        LCD.print("Komfortsollwert");
      }
      if (!dat.presence_state && !dat.presence_error) {
        LCD.print("Pr\xE1");
        LCD.print("senz: AUS");
        LCD.setCursor(0,1);
        LCD.print("Heizen auf");
        LCD.setCursor(0,2);
        LCD.print("Reduziersollwert");
      }
      delay(2000);
      //RxUDP(); //check for new values to make sure presence was really changed
      //determine_presence_state(); //update presence state
      LCD.clear();
      UpdateLCD(); //show new presence state
    }
    else { //no answer received in time from BSB-LAN
      LCD.setCursor(0,3);
      LCD.print("Error #503     ");
      delay(2000);
      LCD.setCursor(0,3);
      LCD.print("               ");
    }
  }
  t_act = millis();
  if (t_act - t_old > 5000) {
    UpdateLCD();
    t_old = t_act;
  }
  //reset Rx buffer
  sprintf(RxBuffer, "%d", 0);
}


Code BSB_lan_custom.h


//RGLU, custom code for loop function
//for RGLU v0.01

//check for new UDP packets
RxUDP();
//presence state changed in RG
if (!strcmp(RxBuffer, "!PRES@0000000001")) {
  Serial.println("Request to change presence status");
  pv.RT_t = (int)(atof(query(8741,8741,0))*10);
  pv.RT_c = (int)(atof(query(710,710,0))*10);
  pv.RT_r = (int)(atof(query(712,712,0))*10);
  if (pv.RT_t == pv.RT_c) { //if currently in comfort mode
    Serial.println("Currently, RT_t = comfort, change to reduced / 'not present'");
    set(701, "1", 1);  //set heating to "reduced"
  }
  if (pv.RT_t == pv.RT_r) { //if currently in reduced mode
    Serial.println("Currently, RT_t = reduced, change to comfort / 'present'");
    set(701, "0", 1);  //set heating to "comfort"
  }
  //delay (1);
  //send new room target temperature
  pv.RT_t = (int)(atof(query(8741,8741,0))*10);
  //Serial.print("RT_t set to :");
  //Serial.println(pv.RT_t);
  Udp.beginPacket(RxIP, RxPort);
  sprintf(TxBuffer, "%.5i@%.10i", 8741, pv.RT_t);
  Udp.print(TxBuffer);
  Udp.endPacket();
}
//broadcast request by RG
if (!strcmp(RxBuffer, "REQBC@0000000001")) {
  Serial.println("BC request ... send BC data");
  pv.RT_t = (int)(atof(query(8741,8741,0))*10);
  pv.RT_c = (int)(atof(query(710,710,0))*10);
  pv.RT_r = (int)(atof(query(712,712,0))*10);
  pv.OT = (int)(atof(query(8700,8700,0))*10);
  pv.RT = (int)(atof(query(8740,8740,0))*10);
  pv.WT = (int)(atof(query(8830,8830,0))*10);
  pv.water_state = (atoi)(query(8003,8003,0));
  pv.burner_state = (atoi)(query(8300,8300,0));
  Serial.println(pv.OT);
  //send broadcast
  TxBC();
}
//send BC data periodically every ~30 seconds
t_act = millis();
if (t_act - t_old > 30000) {
  Serial.println("Send periodic BC data");
  pv.RT_t = (int)(atof(query(8741,8741,0))*10);
  pv.RT_c = (int)(atof(query(710,710,0))*10);
  pv.RT_r = (int)(atof(query(712,712,0))*10);
  pv.OT = (int)(atof(query(8700,8700,0))*10);
  pv.RT = (int)(atof(query(8740,8740,0))*10);
  pv.WT = (int)(atof(query(8830,8830,0))*10);
  pv.water_state = (atoi)(query(8003,8003,0));
  pv.burner_state = (atoi)(query(8300,8300,0));
  //send broadcast 
  TxBC();
  t_old = t_act;
}
//reset Rx buffer
sprintf(RxBuffer, "%d", 0);


Code BSB_lan_custom_global.h


//RGLU, custom code for global section
//for RGLU v0.01

#include <stdlib.h>

//UDP port of BSB-LAN
unsigned int UDPportBSB = 28000;
//IP adress and port of RG
IPAddress RxIP(192, 168, 0, 42);
unsigned int RxPort = 28001;
const int udp_buff_size = 16;
char RxBuffer[udp_buff_size];
char TxBuffer[udp_buff_size];
unsigned long t_act, t_old;

struct pv_BSB {
  int OT;  //outside temperature
  int RT;  //room temperature
  int WT;  //water temperature
  int RT_t;  //room temperature, target
  int RT_c;  //room temperature, comfort
  int RT_r;  //room temperature, reduced
  int water_state;
  int burner_state;
};

struct pv_BSB pv;

EthernetUDP Udp;

void RxUDP() //read UDP packet

  int RxPacket = Udp.parsePacket();
  if(RxPacket) {
    Udp.read(RxBuffer, udp_buff_size);
    Serial.print("RxUDP: ");
    Serial.println(RxBuffer);
  }
}

void TxBC(){
    Serial.println("Send UDP data: ");
    //send outside temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8700, pv.OT);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send room temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8740, pv.RT);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send water temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8830, pv.WT);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send burner status
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8300, pv.burner_state);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send water status
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8003, pv.water_state);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send room target temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 8741, pv.RT_t);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send room comfort temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 710, pv.RT_c);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);
    //send room reduced temperature
    Udp.beginPacket(RxIP, RxPort);
    sprintf(TxBuffer, "%.5i@%.10i", 712, pv.RT_r);
    Serial.println(TxBuffer);
    Udp.print(TxBuffer);
    Udp.endPacket();
    delay(100);       
}


Code BSB_lan_custom_setup.h


//RGLU, custom code for setup function
//for RGLU v0.01

Udp.begin(UDPportBSB);
t_old=millis();  //counter for periodic broadcast

Schotty

Moin Fabian,
wärst du damit einverstanden, wenn ich das mit als 'Bastel'-Beispiel ins BSB-LAN-Handbuch aufnehme?
Gruß
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/


Schotty

Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

Maista

@fabulous

Jetzt fehlt nur noch die ESP-Variante ;)

Schönen Sonntag

Gerd

fabulous

#7
Moin,

hier noch ein paar erläuternde Worte:

Auf beiden Arduinos (BSB-LAN Adapter und RGLU) läuft ein UDP-Service. Damit ist es möglich, UDP-Pakete sowohl zu versenden als auch zu empfangen. Der BSB-Lan Adapter verwendet dazu Port 28000, das RGLU verwendet Port 28001. Theoretisch sind auch andere Ports möglich; ich habe welche gewählt die durch keine von mir verwendete Software benutzt werden. Siehe auch: https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports#Registrierte_Ports:_1024%E2%80%9349151

Der BSB-LAN Adapter sendet alle ca. 30 Sekunden ein Broadcast-Paket mit folgenden Parametern:
- RT_t = Parameter 8741; derzeitige Raumsolltemperatur
- RT_c = 710; Komforttemperatur
- RT_r = 712; Reduziertemperatur
- OT = 8700; Aussentemperatur
- RT = 8740; Raumtemperatur
- WT = 8830; Wassertemperatur
- water_state = 8003; Trinkwasserstatus
- burner_state = 8300; Brennerstufe 1 aktiv

Darüberhinaus reagiert der BSB-LAN Adapter auf einen Broadcast-Request (REQBC@0000000001) des RGLU sowie ein Drücken der Präsenztaste am RGLU (!PRES@0000000001).

Das RGLU prüft permanent auf empfangene UDP-Pakete und wertet diese aus. Nach der Auswertung werden die entsprechenden Infos auf dem LCD bereitgestellt. Aussentemperatur, Raumtemperatur und Wassertemperatur werden direkt angezeigt.
Der Trinkwasserstatus wird verwendet, um ein entsprechendes Symbol (Wasserhahn) anzuzeigen, wenn das Wasser gerade erwärmt wird.
"Brennerstufe 1" wird verwendet, um ein entsprechendes Symbol (Flamme) anzuzeigen, wenn der Brenner läuft.
Raumsolltemperatur, Komfortemperatur und Rediziertemperatur werden verwendet, um entsprechend das Symbol Sonne/Mond anzuzeigen.

Beim Drücken des Tasters (Präsenztaste) am RGLU wird eine UDP-Nachricht an den BSB-LAN Adapter gesendet. Dieser setzt per set(701, ...) die Heizung in den entsprechenden Modus. Anschließend wird die neue Solltemperatur (im Erfolgsfall wurde diese durch den set(701, ...) in der Heizung geändert) ans RGLU zurückgeschickt. Dort wird der neue Präsenzstatus bestimmt und entsprechend zurückgemeldet.

Es existiert nur eine minimale Fehlerbehandlung; alle Pakete verwenden den Aufbau "ppppp@vvvvvvvvvv"; also 5 Stellen für den Parameter, einen Separator (@) und 10 Stellen für den Wert.
Es werden nur Integerwerte verwendet; daher werden alle Temperaturen vor dem Senden mit dem Faktor 10 multipliziert und nach dem Empfang mit dem Faktor 0,1 multipliziert. Dadurch ist keine Verwendung von Double-Werten für die Übertragung bzw. Erkennung von Kommata etc. nötig.

Das Ganze soll noch in eine Box gepackt werden; diese soll an der Haustür platziert werden. Das Hauptaugemerk liegt in der Präsenztaste; ich habe zwar ein RGT, allerdings befindet sich das RGT im Referenzraum und dieser ist maximal weit von der Haustür entfernt. Es ist zwar möglich, ein zweites RGT zu verwenden; aber an diesem ist dann die Präsenzfunktion (soweit ich weiss) deaktiviert.

Gruß
Fabian

Schotty

Zitat von: fabulous am 26 April 2020, 14:05:02
Der BSB-LAN Adapter sendet alle ca. 30 Sekunden ein Broadcast-Paket mit folgenden Parametern:
...
Darüberhinaus reagiert der BSB-LAN Adapter auf einen Broadcast-Request (REQBC@0000000001) des RGLU sowie ein Drücken der Präsenztaste am RGLU (!PRES@0000000001).

Das RGLU prüft permanent auf empfangene UDP-Pakete und wertet diese aus.
Vorweg: Ich habe nicht alles verstanden, aber das mit den Broadcasts finde ich prinzipiell interessant und wäre evtl auch für FHEM und andere HA-Systeme nützlich, oder?
Soweit ich weiß, kann BSB-LAN ja bisher keine eigenständigen Broadcasts versenden: https://1coderookie.github.io/BSB-LPB-LAN/kap15.html#1513-kann-bspw-fhem-auf-bestimmte-broadcasts-lauschen
Könntest du das vielleicht auch nochmal im eigentlichen BSB-LAN-Thread posten? Ich könnte mir vorstellen, dass das auch für @freetz und eine etwaige generelle Implementierung in BSB-LAN interessant sein könnte?!
Gruß
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

fabulous

#9
Moin,

@Schotty:
Kannst du etwas genauer erläutern, was das Ziel ist? Ich habe noch nicht mit FHEM gearbeitet.

Der Grund, warum ich UDP verwende, ist, dass es ein sehr einfaches Protokoll ist und sich der Sender nicht wirklich darum kümmert, was mit seinem gesendeten Paket passiert - sozusagen "fire and forget".
Ich habe den Begriff "Broadcast" verwendet, weil ich im Hinterkopf habe, noch ein zweites RGLU im Badezimmer zu installieren, allerdings mit einem "TWW Push"-Button - der BSB-LAN Adapter soll nicht übermäßig belastet werden und das Paket mit den ganzen Werten nur einmal an alle Empfänger gleichzeitig senden anstatt an jeden Empfänger separat. UDP beherrscht diesen "Broadcast" theoretisch. Ich habe es aber noch nicht umgesetzt. Es wird derzeit nur an einen einzigen Empfänger gesendet.

@Maista: was meinst du in diesem Zusammenhang mit "ESP"? Hilf mir mal auf die Sprünge ...

Gruß
Fabian

Schotty

So wie ich es verstanden habe machst du im Grunde das, was auch der Heizungsregler selbst schon von Haus aus macht, nämlich bestimmte Werte/Parameter in bestimmten Intervallen einfach über den Bus schicken. Finde ich gut und ließe sich bestimmt gut nutzen, wenn man die Parameter entspr konfigurieren/definieren kann. Eine gute Lösung, um bspw nicht immer aktiv abfragen zu müssen (ob nun mit FHEM oder einer anderen HA-Lösung ist dabei ja gleichgültig) und wie du jetzt bspw ein Status-Display o.ä. damit zu basteln..
Ein bestimmtes 'Ziel hinsichtlich FHEM' habe ich da nicht im Sinn, mir ging's nur darum, dass eine solche 'broadcast'-Funktion noch nicht in BSB-LAN implementiert ist. Also bisher kann/muss man entweder aktiv pollen oder via MQTT schicken lassen.

Maista meinte mit ESP sicherlich, dass er (und bestimmt auch andere ;) ) sich diesen Code lauffähig für ESP-basierte Plattformen (Wemos D1, nodeMCU etc) wünscht, so dass man eben anstelle eines Uno+LAN-Shield einfach irgendwo im Haus eine WLAN-basierte Lösung einsetzen könnte. Hätte wirklich was.. ;)
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

fabulous

Moin,

ich verstehe.

Wenn das Zielsystem UDP-fähig ist, könnte meine Lösung entsprechend angepasst werden.

Gruß
Fabian


Schotty

Yupp,zum beispiel,andere varianten mit micro-usb-port (weils praktisch ist  ;) ) wären bspw auch 'wemos d1 mini' (gibts u.a. auch als 'pro' mit optionaler externer antenne)). Is nochmal etwas kleiner als ein nodemcu, aber bietet im grunde gleich viel.
Allen gemein ist,dass darauf ein esp8266 verbaut ist. Ist quasi der wlan-chip mit leistungsfähigem mikrocontroller. Den gibts zwar auch einzeln,is aber m.m.n. nich so praktisch benutzbar (bzgl flashen,strom etc). Die dinger sind mittlerweile in unzähligen komponenten verbaut,bspw sonoff, lampen mit wlan- anbindung und wat nich noch alles..
Haben mehr ram,flash,power etc als jeder arduino.
Werden gerne eingesetzt,wo eine relativ unkomplizierte komponentenanbindung via wlan gewünscht ist. Für nicht-programmierer mit bspw tasmota, espeasy, espurna, esphome auch relativ unkompliziert zu konfigurieren. Für programmierer aber natürlich auch mit arduino-ide o.ä. programmierbar.

Der nachfolger vom esp8266 ist der esp32, hat mehr speicher,power,bluetooth an board und noch etliches mehr. Für die 'normalen' dinge reicht der esp8266 aber i.d.r. dicke.
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

Schotty

..fällt mir gerade noch ein: pass auf bei sog. 'v3 lolin' nodemcu's,das sind wohl 'alte' varianten und außerdem sind sie größer als die v2.
Gibt aber wohl im grunde eigtl eh nur zwei 'eigentliche' nodemcu-typen,s.hier: https://www.mikrocontroller.net/topic/412609

Wemos d1 haben noch nen extra 5v-pin zur spannungsversorgung von komponenten,wenn du das modul selbst per mini-usb-buchse mit strom versorgst. Der fehlt bei nodemcu (v2),aber dort kann man afaik in dem fall 'vin' zum abgreifen der 5v nutzen.

Aber achtung: die gpios des esp8266 (und aller darauf basierenden varianten, also auch wemos d1, nodemcu etc) sind laut datenblatt nur 3,3v-kompatibel! Manche vertragen mit glück auch mal 5v,aber das ist bzw kann ein glücksspiel sein. Also für 5v-signale dann lieber sicherheitshalber spannungsteiler o.ä. nutzen oder einen mehr bestellen  ;)
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/