WLED-Controller - publish von empfangenen IR-Codes über MQTT

Begonnen von TomLee, 25 Mai 2021, 11:25:07

Vorheriges Thema - Nächstes Thema

TomLee

Hallo,

hab diesen Vorschlag gefunden die ir.cpp von WLED zu ergänzen.

Bevor ich das blind ausprobiere, dacht ich mir ich frage einfach mal nach ob es hier jemanden gibt der sich mit der Programmierung des ESP auskennt und beurteilen (oder sogar helfen) kann, ob es mit dem kurzen Codeschnippsel schon zu meinem gewünschten Verhalten kommen könnte das die empfangenen IR-Codes via MQTT übertragen werden.

Gruß

Thomas

TomLee

Minimum ein graues Haar reicher, Dank Arduino IDE  ::), bin ich so weit mich zu trauen, zum jetzigen Zeitpunkt  8), zu behaupten es liegt nur noch an dieser Meldung die Firmware selbst zu kompilieren:


In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled00.ino:13:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:620:2: error: #endif without #if

  620 | #endif

      |  ^~~~~



Kann mir jemand sagen wo das if fehlt, ich nutze die .zip aus dem master-Branch, verstehe nicht das es zu der Meldung kommt.

Wenn ich die Zeile 620 mit dem #endif einfach rausnehme kommt es zu dieser Meldung:


C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:4: error: stray '#' in program

    1 | #ifndef Espalexa_h

      | ^

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.h:27,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.cpp:27:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:4: error: stray '#' in program

    1 | #ifndef Espalexa_h

      | ^

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.h:27,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX_fcn.cpp:27:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:1: error: '' does not name a type

    1 | #ifndef Espalexa_h

      | 

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:61,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.h:27,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX_fcn.cpp:27:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:28: error: 'EspalexaDevice' was not declared in this scope; did you mean 'EspalexaDevice_h'?

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                            ^~~~~~~~~~~~~~

      |                            EspalexaDevice_h

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:44: error: 'd' was not declared in this scope

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                            ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:46: error: template argument 1 is invalid

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                              ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:21:41: error: cannot convert 'std::nullptr_t' to 'DeviceCallbackFunction' {aka 'int'} in initialization

   21 |   DeviceCallbackFunction _callbackDev = nullptr;

      |                                         ^~~~~~~

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.h:27,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.cpp:27:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:1: error: '' does not name a type

    1 | #ifndef Espalexa_h

      | 

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:61,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.h:27,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\FX.cpp:27:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:28: error: 'EspalexaDevice' was not declared in this scope; did you mean 'EspalexaDevice_h'?

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                            ^~~~~~~~~~~~~~

      |                            EspalexaDevice_h

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:44: error: 'd' was not declared in this scope

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                            ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:46: error: template argument 1 is invalid

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                              ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:21:41: error: cannot convert 'std::nullptr_t' to 'DeviceCallbackFunction' {aka 'int'} in initialization

   21 |   DeviceCallbackFunction _callbackDev = nullptr;

      |                                         ^~~~~~~

"C:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\xtensa-lx106-elf-gcc\\3.0.0-newlib4.0.0-gnu23-48f7b08/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0/tools/sdk/include" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0/tools/sdk/lwip2/include" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0/tools/sdk/libc/xtensa-lx106-elf/include" "-IC:\\Users\\thoma\\AppData\\Local\\Temp\\arduino_build_351450/core" -c -w -Os -g -free -fipa-pta -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=gnu++17 -MMD -ffunction-sections -fdata-sections -fno-exceptions -DMMU_IRAM_SIZE=0x8000 -DMMU_ICACHE_SIZE=0x8000 -DNONOSDK22x_190703=1 -DF_CPU=80000000L -DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -DARDUINO=10815 -DARDUINO_ESP8266_WEMOS_D1MINI -DARDUINO_ARCH_ESP8266 "-DARDUINO_BOARD=\"ESP8266_WEMOS_D1MINI\"" -DFLASHMODE_DIO -DESP8266 "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\cores\\esp8266" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\variants\\d1_mini" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\ESP8266WiFi\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\ESP8266mDNS\\src" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\ESPAsyncTCP-master\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\LittleFS\\src" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\ESPAsyncWebServer-master\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\Hash\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\EEPROM" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\DNSServer\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\ArduinoOTA" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\ESPAsyncUDP-master\\src" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\FastLED-master\\src" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\NeoPixelBus-master\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\SPI" "-IC:\\Users\\thoma\\Documents\\Arduino\\libraries\\IRremoteESP8266-master\\src" "-IC:\\Users\\thoma\\AppData\\Local\\Arduino15\\packages\\esp8266\\hardware\\esp8266\\3.0.0\\libraries\\Wire" "C:\\Users\\thoma\\AppData\\Local\\Temp\\arduino_build_351450\\sketch\\alexa.cpp" -o "C:\\Users\\thoma\\AppData\\Local\\Temp\\arduino_build_351450\\sketch\\alexa.cpp.o"

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\alexa.cpp:1:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:4: error: stray '#' in program

    1 | #ifndef Espalexa_h

      | ^

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\alexa.cpp:1:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:1:1: error: '' does not name a type

    1 | #ifndef Espalexa_h

      | 

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:61,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\alexa.cpp:1:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:28: error: 'EspalexaDevice' was not declared in this scope; did you mean 'EspalexaDevice_h'?

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                            ^~~~~~~~~~~~~~

      |                            EspalexaDevice_h

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:44: error: 'd' was not declared in this scope

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                            ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:10:46: error: template argument 1 is invalid

   10 | typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;

      |                                              ^

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:21:41: error: cannot convert 'std::nullptr_t' to 'DeviceCallbackFunction' {aka 'int'} in initialization

   21 |   DeviceCallbackFunction _callbackDev = nullptr;

      |                                         ^~~~~~~

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\alexa.cpp: In function 'void alexaInit()':

alexa.cpp:21:64: error: invalid conversion from 'void (*)(EspalexaDevice*)' to 'DeviceCallbackFunction' {aka 'int'} [-fpermissive]

   21 |       espalexaDevice = new EspalexaDevice(alexaInvocationName, onAlexaChange, EspalexaDeviceType::extendedcolor);

      |                                                                ^~~~~~~~~~~~~

      |                                                                |

      |                                                                void (*)(EspalexaDevice*)

In file included from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\Espalexa.h:61,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\wled.h:99,

                 from C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\alexa.cpp:1:

C:\Users\thoma\Downloads\WLED-master\WLED-master\wled00\src\dependencies\espalexa\EspalexaDevice.h:36:60: note:   initializing argument 2 of 'EspalexaDevice::EspalexaDevice(String, DeviceCallbackFunction, EspalexaDeviceType, uint8_t)'

   36 |   EspalexaDevice(String deviceName, DeviceCallbackFunction dcb, EspalexaDeviceType t =EspalexaDeviceType::dimmable, uint8_t initialValue =0);

      |                                     ~~~~~~~~~~~~~~~~~~~~~~~^~~


Wo muss dann schlussfolgernd das if ergänzt werden ?






TomLee

Sry, die Espalexa.h sieht mit #endif so aus:

#ifndef Espalexa_h
#define Espalexa_h

/*
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
*
* This was put together from these two excellent projects:
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
* https://github.com/probonopd/ESP8266HueEmulator
*/
/*
* @title Espalexa library
* @version 2.7.0
* @author Christian Schwinne
* @license MIT
* @contributors d-999
*/

#include "Arduino.h"

//you can use these defines for library config in your sketch. Just use them before #include <Espalexa.h>
//#define ESPALEXA_ASYNC

//in case this is unwanted in your application (will disable the /espalexa value page)
//#define ESPALEXA_NO_SUBPAGE

#ifndef ESPALEXA_MAXDEVICES
#define ESPALEXA_MAXDEVICES 10 //this limit only has memory reasons, set it higher should you need to, max 128
#endif

//#define ESPALEXA_DEBUG

#ifdef ESPALEXA_ASYNC
#ifdef ARDUINO_ARCH_ESP32
  #include <AsyncTCP.h>
#else
  #include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#else
#ifdef ARDUINO_ARCH_ESP32
  #include <WiFi.h>
  #include <WebServer.h> //if you get an error here please update to ESP32 arduino core 1.0.0
#else
  #include <ESP8266WebServer.h>
  #include <ESP8266WiFi.h>
#endif
#endif
#include <WiFiUdp.h>
#include "../network/Network.h"

#ifdef ESPALEXA_DEBUG
#pragma message "Espalexa 2.7.0 debug mode"
#define EA_DEBUG(x)  Serial.print (x)
#define EA_DEBUGLN(x) Serial.println (x)
#else
#define EA_DEBUG(x)
#define EA_DEBUGLN(x)
#endif

#include "EspalexaDevice.h"

#define DEVICE_UNIQUE_ID_LENGTH 12

class Espalexa {
private:
  //private member vars
  #ifdef ESPALEXA_ASYNC
  AsyncWebServer* serverAsync;
  AsyncWebServerRequest* server; //this saves many #defines
  String body = "";
  #elif defined ARDUINO_ARCH_ESP32
  WebServer* server;
  #else
  ESP8266WebServer* server;
  #endif
  uint8_t currentDeviceCount = 0;
  bool discoverable = true;
  bool udpConnected = false;

  EspalexaDevice* devices[ESPALEXA_MAXDEVICES] = {};
  //Keep in mind that Device IDs go from 1 to DEVICES, cpp arrays from 0 to DEVICES-1!!
 
  WiFiUDP espalexaUdp;
  IPAddress ipMulti;
  uint32_t mac24; //bottom 24 bits of mac
  String escapedMac=""; //lowercase mac address
 
  //private member functions
  const char* modeString(EspalexaColorMode m)
  {
    if (m == EspalexaColorMode::xy) return "xy";
    if (m == EspalexaColorMode::hs) return "hs";
    return "ct";
  }
 
  const char* typeString(EspalexaDeviceType t)
  {
    switch (t)
    {
      case EspalexaDeviceType::dimmable:      return PSTR("Dimmable light");
      case EspalexaDeviceType::whitespectrum: return PSTR("Color temperature light");
      case EspalexaDeviceType::color:         return PSTR("Color light");
      case EspalexaDeviceType::extendedcolor: return PSTR("Extended color light");
      default: return "";
    }
  }
 
  const char* modelidString(EspalexaDeviceType t)
  {
    switch (t)
    {
      case EspalexaDeviceType::dimmable:      return "LWB010";
      case EspalexaDeviceType::whitespectrum: return "LWT010";
      case EspalexaDeviceType::color:         return "LST001";
      case EspalexaDeviceType::extendedcolor: return "LCT015";
      default: return "";
    }
  }
 
  void encodeLightId(uint8_t idx, char* out)
  {
    uint8_t mac[6];
    WiFi.macAddress(mac);

    sprintf_P(out, PSTR("%02X:%02X:%02X:%02X:%02X:%02X:00:11-%02X"), mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], idx);
  }

  // construct 'globally unique' Json dict key fitting into signed int
  inline int encodeLightKey(uint8_t idx)
  {
    //return idx +1;
    static_assert(ESPALEXA_MAXDEVICES <= 128, "");
    return (mac24<<7) | idx;
  }

  // get device index from Json key
  uint8_t decodeLightKey(int key)
  {
    //return key -1;
    return (((uint32_t)key>>7) == mac24) ? (key & 127U) : 255U;
  }

  //device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
  void deviceJsonString(EspalexaDevice* dev, char* buf)
  {
    char buf_lightid[27];
    encodeLightId(dev->getId() + 1, buf_lightid);
   
    char buf_col[80] = "";
    //color support
    if (static_cast<uint8_t>(dev->getType()) > 2)
      //TODO: %f is not working for some reason on ESP8266 in v0.11.0 (was fine in 0.10.2). Need to investigate
      //sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]")
      //  ,dev->getHue(), dev->getSat(), dev->getX(), dev->getY());
      sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%s,%s]"),dev->getHue(), dev->getSat(),
        ((String)dev->getX()).c_str(), ((String)dev->getY()).c_str());
     
    char buf_ct[16] = "";
    //white spectrum support
    if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color)
      sprintf(buf_ct, ",\"ct\":%u", dev->getCt());
   
    char buf_cm[20] = "";
    if (static_cast<uint8_t>(dev->getType()) > 1)
      sprintf(buf_cm,PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
   
    sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
                   "\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
                   "\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.7.0\"}")
                   
    , (dev->getValue())?"true":"false", dev->getLastValue()-1, buf_col, buf_ct, buf_cm, typeString(dev->getType()),
    dev->getName().c_str(), modelidString(dev->getType()), static_cast<uint8_t>(dev->getType()), buf_lightid);
  }
 
  //Espalexa status page /espalexa
  #ifndef ESPALEXA_NO_SUBPAGE
  void servePage()
  {
    EA_DEBUGLN("HTTP Req espalexa ...\n");
    String res = "Hello from Espalexa!\r\n\r\n";
    for (int i=0; i<currentDeviceCount; i++)
    {
      EspalexaDevice* dev = devices[i];
      res += "Value of device " + String(i+1) + " (" + dev->getName() + "): " + String(dev->getValue()) + " (" + typeString(dev->getType());
      if (static_cast<uint8_t>(dev->getType()) > 1) //color support
      {
        res += ", colormode=" + String(modeString(dev->getColorMode())) + ", r=" + String(dev->getR()) + ", g=" + String(dev->getG()) + ", b=" + String(dev->getB());
        res +=", ct=" + String(dev->getCt()) + ", hue=" + String(dev->getHue()) + ", sat=" + String(dev->getSat()) + ", x=" + String(dev->getX()) + ", y=" + String(dev->getY());
      }
      res += ")\r\n";
    }
    res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
    res += "\r\nUptime: " + (String)millis();
    res += "\r\n\r\nEspalexa library v2.7.0 by Christian Schwinne 2021";
    server->send(200, "text/plain", res);
  }
  #endif

  //not found URI (only if internal webserver is used)
  void serveNotFound()
  {
    EA_DEBUGLN("Not-Found HTTP call:");
    #ifndef ESPALEXA_ASYNC
    EA_DEBUGLN("URI: " + server->uri());
    EA_DEBUGLN("Body: " + server->arg(0));
    if(!handleAlexaApiCall(server->uri(), server->arg(0)))
    #else
    EA_DEBUGLN("URI: " + server->url());
    EA_DEBUGLN("Body: " + body);
    if(!handleAlexaApiCall(server))
    #endif
      server->send(404, "text/plain", "Not Found (espalexa)");
  }

  //send description.xml device property page
  void serveDescription()
  {
    EA_DEBUGLN("# Responding to description.xml ... #\n");
    IPAddress localIP = Network.localIP();
    char s[16];
    sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
    char buf[1024];
   
    sprintf_P(buf,PSTR("<?xml version=\"1.0\" ?>"
        "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
        "<specVersion><major>1</major><minor>0</minor></specVersion>"
        "<URLBase>http://%s:80/</URLBase>"
        "<device>"
          "<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
          "<friendlyName>Espalexa (%s:80)</friendlyName>"
          "<manufacturer>Royal Philips Electronics</manufacturer>"
          "<manufacturerURL>http://www.philips.com</manufacturerURL>"
          "<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
          "<modelName>Philips hue bridge 2012</modelName>"
          "<modelNumber>929000226503</modelNumber>"
          "<modelURL>http://www.meethue.com</modelURL>"
          "<serialNumber>%s</serialNumber>"
          "<UDN>uuid:2f402f80-da50-11e1-9b23-%s</UDN>"
          "<presentationURL>index.html</presentationURL>"
        "</device>"
        "</root>"),s,s,escapedMac.c_str(),escapedMac.c_str());
         
    server->send(200, "text/xml", buf);
   
    EA_DEBUGLN("Send setup.xml");
    EA_DEBUGLN(buf);
  }
 
  //init the server
  void startHttpServer()
  {
    #ifdef ESPALEXA_ASYNC
    if (serverAsync == nullptr) {
      serverAsync = new AsyncWebServer(80);
      serverAsync->onNotFound([=](AsyncWebServerRequest *request){server = request; serveNotFound();});
    }
   
    serverAsync->onRequestBody([=](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
      char b[len +1];
      b[len] = 0;
      memcpy(b, data, len);
      body = b; //save the body so we can use it for the API call
      EA_DEBUG("Received body: ");
      EA_DEBUGLN(body);
    });
    #ifndef ESPALEXA_NO_SUBPAGE
    serverAsync->on("/espalexa", HTTP_GET, [=](AsyncWebServerRequest *request){server = request; servePage();});
    #endif
    serverAsync->on("/description.xml", HTTP_GET, [=](AsyncWebServerRequest *request){server = request; serveDescription();});
    serverAsync->begin();
   
    #else
    if (server == nullptr) {
      #ifdef ARDUINO_ARCH_ESP32
      server = new WebServer(80);
      #else
      server = new ESP8266WebServer(80); 
      #endif
      server->onNotFound([=](){serveNotFound();});
    }

    #ifndef ESPALEXA_NO_SUBPAGE
    server->on("/espalexa", HTTP_GET, [=](){servePage();});
    #endif
    server->on("/description.xml", HTTP_GET, [=](){serveDescription();});
    server->begin();
    #endif
  }

  //respond to UDP SSDP M-SEARCH
  void respondToSearch()
  {
    IPAddress localIP = Network.localIP();
    char s[16];
    sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);

    char buf[1024];

    sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
      "EXT:\r\n"
      "CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
      "LOCATION: http://%s:80/description.xml\r\n"
      "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
      "hue-bridgeid: %s\r\n"
      "ST: urn:schemas-upnp-org:device:basic:1\r\n"  // _deviceType
      "USN: uuid:2f402f80-da50-11e1-9b23-%s::upnp:rootdevice\r\n" // _uuid::_deviceType
      "\r\n"),s,escapedMac.c_str(),escapedMac.c_str());

    espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
    #ifdef ARDUINO_ARCH_ESP32
    espalexaUdp.write((uint8_t*)buf, strlen(buf));
    #else
    espalexaUdp.write(buf);
    #endif
    espalexaUdp.endPacket();                   
  }

public:
  Espalexa(){}

  //initialize interfaces
  #ifdef ESPALEXA_ASYNC
  bool begin(AsyncWebServer* externalServer = nullptr)
  #elif defined ARDUINO_ARCH_ESP32
  bool begin(WebServer* externalServer = nullptr)
  #else
  bool begin(ESP8266WebServer* externalServer = nullptr)
  #endif
  {
    EA_DEBUGLN("Espalexa Begin...");
    EA_DEBUG("MAXDEVICES ");
    EA_DEBUGLN(ESPALEXA_MAXDEVICES);
    escapedMac = WiFi.macAddress();
    escapedMac.replace(":", "");
    escapedMac.toLowerCase();

    String macSubStr = escapedMac.substring(6, 12);
    mac24 = strtol(macSubStr.c_str(), 0, 16);

    #ifdef ESPALEXA_ASYNC
    serverAsync = externalServer;
    #else
    server = externalServer;
    #endif
    #ifdef ARDUINO_ARCH_ESP32
    udpConnected = espalexaUdp.beginMulticast(IPAddress(239, 255, 255, 250), 1900);
    #else
    udpConnected = espalexaUdp.beginMulticast(Network.localIP(), IPAddress(239, 255, 255, 250), 1900);
    #endif

    if (udpConnected){
     
      startHttpServer();
      EA_DEBUGLN("Done");
      return true;
    }
    EA_DEBUGLN("Failed");
    return false;
  }

  //service loop
  void loop() {
    #ifndef ESPALEXA_ASYNC
    if (server == nullptr) return; //only if begin() was not called
    server->handleClient();
    #endif
   
    if (!udpConnected) return;   
    int packetSize = espalexaUdp.parsePacket();   
    if (packetSize < 1) return; //no new udp packet
   
    EA_DEBUGLN("Got UDP!");

    unsigned char packetBuffer[packetSize+1]; //buffer to hold incoming udp packet
    espalexaUdp.read(packetBuffer, packetSize);
    packetBuffer[packetSize] = 0;
 
    espalexaUdp.flush();
    if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
 
    const char* request = (const char *) packetBuffer;
    if (strstr(request, "M-SEARCH") == nullptr) return;

    EA_DEBUGLN(request);
    if (strstr(request, "ssdp:disc")  != nullptr &&  //short for "ssdp:discover"
        (strstr(request, "upnp:rootd") != nullptr || //short for "upnp:rootdevice"
         strstr(request, "ssdp:all")   != nullptr ||
         strstr(request, "asic:1")     != nullptr )) //short for "device:basic:1"
    {
      EA_DEBUGLN("Responding search req...");
      respondToSearch();
    }
  }

  // returns device index or 0 on failure
  uint8_t addDevice(EspalexaDevice* d)
  {
    EA_DEBUG("Adding device ");
    EA_DEBUGLN((currentDeviceCount+1));
    if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0;
    if (d == nullptr) return 0;
    d->setId(currentDeviceCount);
    devices[currentDeviceCount] = d;
    return ++currentDeviceCount;
  }
 
  //brightness-only callback
  uint8_t addDevice(String deviceName, BrightnessCallbackFunction callback, uint8_t initialValue = 0)
  {
    EA_DEBUG("Constructing device ");
    EA_DEBUGLN((currentDeviceCount+1));
    if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0;
    EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue);
    return addDevice(d);
  }
 
  //brightness-only callback
  uint8_t addDevice(String deviceName, ColorCallbackFunction callback, uint8_t initialValue = 0)
  {
    EA_DEBUG("Constructing device ");
    EA_DEBUGLN((currentDeviceCount+1));
    if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0;
    EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue);
    return addDevice(d);
  }


  uint8_t addDevice(String deviceName, DeviceCallbackFunction callback, EspalexaDeviceType t = EspalexaDeviceType::dimmable, uint8_t initialValue = 0)
  {
    EA_DEBUG("Constructing device ");
    EA_DEBUGLN((currentDeviceCount+1));
    if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0;
    EspalexaDevice* d = new EspalexaDevice(deviceName, callback, t, initialValue);
    return addDevice(d);
  }

  void renameDevice(uint8_t id, const String& deviceName)
  {
    unsigned int index = id - 1;
    if (index < currentDeviceCount)
      devices[index]->setName(deviceName);
  }

  //basic implementation of Philips hue api functions needed for basic Alexa control
  #ifdef ESPALEXA_ASYNC
  bool handleAlexaApiCall(AsyncWebServerRequest* request)
  {
    server = request; //copy request reference
    String req = request->url(); //body from global variable
    EA_DEBUGLN(request->contentType());
    if (request->hasParam("body", true)) // This is necessary, otherwise ESP crashes if there is no body
    {
      EA_DEBUG("BodyMethod2");
      body = request->getParam("body", true)->value();
    }
    EA_DEBUG("FinalBody: ");
    EA_DEBUGLN(body);
  #else
  bool handleAlexaApiCall(String req, String body)
  { 
  #endif
    EA_DEBUG("URL: ");
    EA_DEBUGLN(req);
    EA_DEBUGLN("AlexaApiCall");
    if (req.indexOf("api") <0) return false; //return if not an API call
    EA_DEBUGLN("ok");

    if (body.indexOf("devicetype") > 0) //client wants a hue api username, we don't care and give static
    {
      EA_DEBUGLN("devType");
      body = "";
      server->send(200, "application/json", F("[{\"success\":{\"username\":\"2BLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBGr\"}}]"));
      return true;
    }

    if ((req.indexOf("state") > 0) && (body.length() > 0)) //client wants to control light
    {
      uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
      EA_DEBUG("ls"); EA_DEBUGLN(devId);
      unsigned idx = decodeLightKey(devId);
      EA_DEBUGLN(idx);
      char buf[50];
      sprintf_P(buf,PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId);
      server->send(200, "application/json", buf);
      if (idx >= currentDeviceCount) return true; //return if invalid ID
      EspalexaDevice* dev = devices[idx];
     
      dev->setPropertyChanged(EspalexaDeviceProperty::none);
     
      if (body.indexOf("false")>0) //OFF command
      {
        dev->setValue(0);
        dev->setPropertyChanged(EspalexaDeviceProperty::off);
        dev->doCallback();
        return true;
      }
     
      if (body.indexOf("true") >0) //ON command
      {
        dev->setValue(dev->getLastValue());
        dev->setPropertyChanged(EspalexaDeviceProperty::on);
      }
     
      if (body.indexOf("bri")  >0) //BRIGHTNESS command
      {
        uint8_t briL = body.substring(body.indexOf("bri") +5).toInt();
        if (briL == 255)
        {
         dev->setValue(255);
        } else {
         dev->setValue(briL+1);
        }
        dev->setPropertyChanged(EspalexaDeviceProperty::bri);
      }
     
      if (body.indexOf("xy")   >0) //COLOR command (XY mode)
      {
        dev->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat());
        dev->setPropertyChanged(EspalexaDeviceProperty::xy);
      }
     
      if (body.indexOf("hue")  >0) //COLOR command (HS mode)
      {
        dev->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt());
        dev->setPropertyChanged(EspalexaDeviceProperty::hs);
      }
     
      if (body.indexOf("ct")   >0) //COLOR TEMP command (white spectrum)
      {
        dev->setColor(body.substring(body.indexOf("ct") +4).toInt());
        dev->setPropertyChanged(EspalexaDeviceProperty::ct);
      }
     
      dev->doCallback();
     
      #ifdef ESPALEXA_DEBUG
      if (dev->getLastChangedProperty() == EspalexaDeviceProperty::none)
        EA_DEBUGLN("STATE REQ WITHOUT BODY (likely Content-Type issue #6)");
      #endif
      return true;
    }
   
    int pos = req.indexOf("lights");
    if (pos > 0) //client wants light info
    {
      int devId = req.substring(pos+7).toInt();
      EA_DEBUG("l"); EA_DEBUGLN(devId);

      if (devId == 0) //client wants all lights
      {
        EA_DEBUGLN("lAll");
        String jsonTemp = "{";
        for (int i = 0; i<currentDeviceCount; i++)
        {
          jsonTemp += '"';
          jsonTemp += encodeLightKey(i);
          jsonTemp += '"';
          jsonTemp += ':';

          char buf[512];
          deviceJsonString(devices[i], buf);
          jsonTemp += buf;
          if (i < currentDeviceCount-1) jsonTemp += ',';
        }
        jsonTemp += '}';
        server->send(200, "application/json", jsonTemp);
      } else //client wants one light (devId)
      {
        EA_DEBUGLN(devId);
        unsigned int idx = decodeLightKey(devId);

        if (idx >= currentDeviceCount) idx = 0; //send first device if invalid
        if (currentDeviceCount == 0) {
          server->send(200, "application/json", "{}");
          return true;
        }
        char buf[512];
        deviceJsonString(devices[idx], buf);
        server->send(200, "application/json", buf);
      }
     
      return true;
    }

    //we don't care about other api commands at this time and send empty JSON
    server->send(200, "application/json", "{}");
    return true;
  }
 
  //set whether Alexa can discover any devices
  void setDiscoverable(bool d)
  {
    discoverable = d;
  }
 
  //get EspalexaDevice at specific index
  EspalexaDevice* getDevice(uint8_t index)
  {
    if (index >= currentDeviceCount) return nullptr;
    return devices[index];
  }
 
  //is an unique device ID
  String getEscapedMac()
  {
    return escapedMac;
  }
 
  //convert brightness (0-255) to percentage
  uint8_t toPercent(uint8_t bri)
  {
    uint16_t perc = bri * 100;
    return perc / 255;
  }
 
  ~Espalexa(){} //note: Espalexa is NOT meant to be destructed
};

#endif



TomLee

#3
Hat irgendwer schon mal einen TSOP an einen WLED-Controller angeschlossen und empfängt die IR-Signale einer Fernbedienung ?

Ich habs jetzt geschafft den Sketch mit dem Source-Code des letzten Release zu kompilieren.
Mit der oben verlinkten Erweiterung und auch ohne, sehe ich im seriellen Monitor keine empfangenen IR-Codes.
Auch, zum Test, mit der vorherigen, fertigen .bin v0.11.1 sehe ich keinen Empfang im seriellen Monitor.

Edit: Hab bisher keine LEDs angeschlossen.

Der Data-Pin des TSOP ist an D2 (GPIO4), eines Wemos D1 mini, wie im Wiki zu WLED beschrieben angeschlossen, der TSOP ist ein 1838, habs mit 3,3V und auch 5V getestet.
Die Funktion des TSOP hab ich mit dem IrecvDumpV2-Sketch geprüft, damit klappt der Empfang einwandfrei.

Ich würde gerne kontrollieren welcher Pin wirklich als Data-Pin definiert ist und zum Test mal einen anderen definieren.
In der ir.cpp steht in Zeile 11-12
IRrecv* irrecv;
//change pin in NpbWrapper.h


Ich finde nirgendwo die File NpbWrapper.h.

Hat irgendwer eventuell noch einen Tipp ?

TomLee

Yes, habs.

Codes werden empfangen und via MQTT übertragen. Das Problem war das mit der neuesten Version 0.12.0 kein IR-Pin per default festgelegt ist.
Die Pins kann man jetzt in den Einstellungen festlegen. Unter LED Preferences, da muss man auch erstmal drauf kommen.

Allerdings werden ständig irgendwelche IR-Codes empfangen, auch wenn ich den TSOP ab/zudecke.

Hat jemand dazu eine Idee warum das so ist, wie man das bändigen könnte ?


TomLee

#5
Führe meinen Monolog mal fort.

Mit einem anderen TSOP gibts keine Probleme, es klappt jetzt alles wie ich es mir vorgestellt hatte.

Für die die einen WLED-Controller mit implementierten "IR-Gatway" auch toll finden hab ich zum testen ein .bin für den ESP8266 (getestet) und den ESP32 (ungetestet) angehangen.
Ich hab keinen ESP32, in der Arduino IDE hab ich einfach ESP32 Dev Module ausgewählt, der Sketch war beim kompilieren zu groß (101 %), warum auch immer, für ein Board mit Flash Size 4MB (32Mb), daraufhin hab ich einfach 8MB (64Mb) ausgewählt und unter Partition Scheme 8M Flash (3MB APP/1.5MB FAT).


Man muss unter LED Preferences/Hardware setup/IR pin einen Pin definieren, default ist -1, also keiner.
Das die IR-Codes auch per MQTT übertragen werden muss irgendeine FB unter Sync Interfaces/Sync setup/Button setup/Infrared Remote ausgewählt werden.

Zitatdefmod MQTT2_WLED_TV MQTT2_DEVICE WLED_538e36
attr MQTT2_WLED_TV userattr lightSceneParamsToSave lightSceneRestoreOnlyIfChanged:1,0
attr MQTT2_WLED_TV IODev MQTT2_Server
attr MQTT2_WLED_TV alexaName streifen
attr MQTT2_WLED_TV comment "http://".internalval($name,'cid','0')."\
effect:selectnumbers,0,1,115,0,lin wled/538e36/api FX=$EVTPART1
attr MQTT2_WLED_TV devStateIcon {Color::devStateIcon( $name, "rgb", "rgb", "brightness", "state" )}
attr MQTT2_WLED_TV event-on-change-reading brightness,effect,intensity,palette,rgb,speed,state,effectname,effectnumber,ircode
attr MQTT2_WLED_TV event-on-update-reading ircode
attr MQTT2_WLED_TV eventMap /effect 0:Solid/effect 2:Breathe/effect 63:Pride/loadPreset 1:Fire/
attr MQTT2_WLED_TV genericDeviceType light
attr MQTT2_WLED_TV group Wohnzimmer
attr MQTT2_WLED_TV homebridgeMapping Brightness=brightness::brightness,maxValue=100,factor=0.39216,delay=true
attr MQTT2_WLED_TV icon hue_filled_iris
attr MQTT2_WLED_TV model wled_controller
attr MQTT2_WLED_TV readingList wled/538e36/status:.* LWT\
  wled/538e36/g:.* brightness\
  wled/538e36/g:.* { $EVENT ? {"state"=>"on"} : {"state"=>"off"} }\
  wled/538e36/c:.* { {"rgb"=>substr("$EVENT",1,6)} }\
  wled/538e36/v:.* api\
  wled/538e36/v:.* { $EVENT =~ m,(?<=<sx>)([\d]+)(?=<\/sx>), ? $1 eq ReadingsVal($NAME,"speed","unknown") ? return : {"speed"=>$1} : return;; }\
  wled/538e36/v:.* {$EVENT =~ m,(?<=<ix>)([\d]+)(?=<\/ix>), ? $1 eq ReadingsVal($NAME,"intensity","unknown") ? return : {"intensity"=>$1} : return }\
  wled/538e36/v:.* {$EVENT =~ m,(?<=<fp>)([\d]+)(?=<\/fp>), ? $1 eq ReadingsVal($NAME,"palette","unknown") ? return : {"palette"=>$1} : return }\
  wled/538e36/v:.* {$EVENT =~ m,(?<=<fx>)([\d]+)(?=<\/fx>), ? $1 eq ReadingsVal($NAME,"effect","unknown") ? return :{"effect"=>"$1"} : return }\
WLED_538e36:wled/538e36/ircode:.* ircode
attr MQTT2_WLED_TV room MQTT2_DEVICE,Wohnzimmer
attr MQTT2_WLED_TV setList on:noArg wled/538e36 on\
  off:noArg wled/538e36 off\
  toggle:noArg wled/538e36 t\
  rgb:colorpicker,RGB wled/538e36/col #$EVTPART1\
  brightness:colorpicker,BRI,0,1,255 wled/538e36\
  speed:colorpicker,BRI,0,1,255 wled/538e36/api SX=$EVTPART1\
  intensity:colorpicker,BRI,0,1,255 wled/538e36/api IX=$EVTPART1\
  palette:selectnumbers,0,1,46,0,lin wled/538e36/api &T=1FP=$EVTPART1\
  effect:knob,min:0,max:119,width:70,height:70,step:1,lineCap:round,angleOffset:180,cursor:3,thickness:.3 wled/538e36/api FX=$EVTPART1   \
  loadPreset:selectnumbers,0,1,3,0,lin wled/538e36/api PL=$EVTPART1\
  dimup:noArg wled/538e36/api A=~10\
  dimdown:noArg wled/538e36/api A=~-10\
  flash:noArg {my $v=ReadingsVal($NAME,"rgb","FFA000");;ReadingsVal($NAME,"state","off") eq "on"?fhem("set $NAME rgb FFFFFF;;sleep 0.5;;set $NAME rgb $v"):fhem("set $NAME toggle;;set $NAME rgb FFFFFF;;sleep 0.5;;set $NAME toggle")}
attr MQTT2_WLED_TV setStateList on off toggle effect loadPreset dimdown dimup
attr MQTT2_WLED_TV userReadings effectname:effect.* {my $h="http://192.168.188.95/json";;$h=~s/_/-/g;; HttpUtils_NonblockingGet( {url=>"$h", callback=>sub($$$) { my ($hash, $err, $data) = @_;; $data =~ m,effects..\[([^[]*?)],;;my $s=$1;;$s=~s/"//g;;$s=~ s/\n//g;;my @a= split(/,/ , $s);;my $i = ReadingsNum($NAME,"effect","1");;;;my $an=@a;;$a=$a[$i];;fhem("setreading $NAME effectname $a;;setreading $NAME effectnumber $an")} }) }
attr MQTT2_WLED_TV verbose 2
attr MQTT2_WLED_TV webCmd rgb:brightness:effect:Solid:Breathe:Pride:Fire:flash

setstate MQTT2_WLED_TV on
setstate MQTT2_WLED_TV 2021-06-20 21:38:34 IODev MQTT2_Server
setstate MQTT2_WLED_TV 2021-06-23 16:39:11 LWT online
setstate MQTT2_WLED_TV 2021-06-23 16:39:11 api <?xml version="1.0" ?><vs><ac>128</ac><cl>246</cl><cl>138</cl><cl>3</cl><cs>0</cs><cs>0</cs><cs>0</cs><ns>0</ns><nr>1</nr><nl>0</nl><nf>1</nf><nd>60</nd><nt>0</nt><fx>0</fx><sx>128</sx><ix>128</ix><fp>0</fp><wv>0</wv><ws>0</ws><ps>0</ps><cy>0</cy><ds>WLED</ds><ss>0</ss></vs>
setstate MQTT2_WLED_TV 2021-06-23 16:39:11 brightness 128
setstate MQTT2_WLED_TV 2021-06-22 16:00:17 effect 0
setstate MQTT2_WLED_TV 2021-06-22 16:00:17 effectname Solid
setstate MQTT2_WLED_TV 2021-06-22 16:00:17 effectnumber 118
setstate MQTT2_WLED_TV 2021-06-22 15:35:38 intensity 128
setstate MQTT2_WLED_TV 2021-06-23 16:41:49 ircode 0x20df00ff
setstate MQTT2_WLED_TV 2021-05-05 13:40:52 palette 0
setstate MQTT2_WLED_TV 2021-01-05 19:03:31 pct set
setstate MQTT2_WLED_TV 2021-06-23 16:39:11 rgb F68A03
setstate MQTT2_WLED_TV 2021-04-24 22:53:07 speed 128
setstate MQTT2_WLED_TV 2021-06-23 16:39:11 state on