IR Receive, Send + Webservice Call

Forums (Deutsch) User Projekte IR Receive, Send + Webservice Call

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #1103
    Terra
    Participant

    Hallo Leute,

    Ich versuche jetzt seit ein paar Tagen meinem NanoESP folgendes beizubringen:

    WENN:
    – Ich 3x die “TV” Taste meiner Fernbedienung drücke

    DANN:
    – Soll sich mein Beamer ausschalten (durch 3x dasselbe IR Signal senden)
    – Mein Yamaha AV-Receiver ausschalten (durch Webservice Call auf lokale IP)

    Das ganze funktioniert getrennt schon sehr gut, ich habe ein Script das bei dreimal drücken der taste “TV” auf meiner Fernbedienung 3x das Signal zum Beamer ausschalten sendet und einmal ein weiteres Script das beim starten den WebService Call an den Yamaha AV Receiver schickt. Beides funktioniert unabhängig tadellos.

    Jetzt habe ich die beiden Scripts in ein Script gepackt und der WebService Call geht leider nicht, ich bekomme immer eine Fehlermeldung des NanoESP das der Call nicht geschickt werden kann.
    Ich vermute das der Speicher zu klein wird obwohl die GUI nichts anzeigt :/

    Ich hab schon überall probiert Speicher zu sparen, aber ich denke das Problem liegt an dem langen String den ich über den WebService schicken muss. Kann ich den irgendwie Speicherschonender zusammenbauen und übergeben?

    Relevanter Teil:

    
    #define AVRStopMessage "<?xml version=\"1.0\" encoding=\"utf-8\"?><YAMAHA_AV cmd=\"PUT\"><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>"
    
      String getRequest = "POST "+Subpage+" HTTP/1.1\r\nHost:"+Host+"\r\nContent-Type: text/xml;charset=\"UTF-8\"\r\nAccept: text/xml\r\nContent-Length: " + String(strlen(AVRStopMessage)+1) + "\r\n\r\n" + String(AVRStopMessage) + "\r\n";
    
      sendCom("AT+CIPSTART=\"TCP\",\""+Host+"\",80", "OK");
      sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
      esp8266.println(getRequest);

    Das ganze Script:

    #include <IRremote.h>
    #include <SoftwareSerial.h>
    SoftwareSerial esp8266(11, 12); // RX, TX
    
    #define SSID "*****"
    #define PASSWORD "*****"
    
    #define AVRHost "192.168.0.12"
    #define AVRSubpage "/YamahaRemoteControl/ctrl"
    
    /*
    Yamaha XML Messages
    Note!
    - AVROutputSetVolume has -39 hardcoded as defined volume
    - AVROutputHDMI1 the outputs of the Yamaha must be set via the NAMES that were assigned in 
      the configuration. My HDMI1 output is called HTPC. Default it most likely the name is HDMI1. 
      "HTPC" is hardcoded in the request!
      All of the extra ones are disabled because of space issues...
    */
    
    #define AVRStopMessage "<?xml version=\"1.0\" encoding=\"utf-8\"?><YAMAHA_AV cmd=\"PUT\"><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>"
    
    /* Some IR Codes
    TURN BEAMER ON    Value:      4CB340BF Type: 3 Length: 32
    TURN BEAMER OFF   Value:      4CB3748B Type: 3 Length: 32
    TURN RECEIVER ON/OFF Value:   7E8154AB Type: 3 Length: 32 - And add a FFFFFFFF Type 3 Length 0
    
    Type 2
    up type 2 800F041E
    down type2 800F841F
    
    */
    unsigned long timenow = 1;
    
    unsigned long receivedBeamerOnSignal1 = 0;
    unsigned long receivedBeamerOnSignal2 = 0;
    unsigned long receivedBeamerOnSignal3 = 0;
    unsigned long repeatTimeoutMillisThreshold = 1000;
    
    #define LED_WLAN 13
    #define GND 4
    #define RECV_PIN  7
    #define GND2  8
    #define VCC  9
    
    IRrecv irrecv(RECV_PIN);
    IRsend irsend;
    
    decode_results results;
    
    // Storage for the recorded code
    int codeType = -1; // The type of code
    unsigned long codeValue; // The code value if not raw
    unsigned int rawCodes[RAWBUF]; // The durations if raw
    int codeLen; // The length of the code
    
    void setup() {
    
      Serial.begin(19200);
      irrecv.enableIRIn(); // Start the receiver
      esp8266.begin(19200);
    
      //Set Pins for LED and IR Monitor
      pinMode(GND, OUTPUT);
      pinMode(GND2, OUTPUT);
      pinMode(VCC, OUTPUT);
      digitalWrite (GND, LOW);
      digitalWrite (GND2, LOW);
      digitalWrite (VCC, HIGH);
    
      if (!espConfig()) serialDebug();
      else digitalWrite(LED_WLAN, HIGH);
    
    }
    
    void loop() {
    
      //Serial.println("I am Alive!");
    
      timenow = millis();
    
      //IR RECEIVER SIGNAL
      if (irrecv.decode(&results)) {
        analyzeCode(&results);
        Serial.println("Received IR!");
        irrecv.resume();
      }
    
    }
    
    // Stores the code for later playback
    // Most of this code is just logging
    void analyzeCode(decode_results *results) {
      codeType = results->decode_type;
      int count = results->rawlen;
      String receivedSignal;
      if (codeType == UNKNOWN) {
        //Serial.println("Received unknown code, saving as raw");
        codeLen = results->rawlen - 1;
        // To store raw codes:
        // Drop first value (gap)
        // Convert from ticks to microseconds
        // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
        for (int i = 1; i <= codeLen; i++) {
          if (i % 2) {
            // Mark
            rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS;
            //Serial.print(" m");
          } 
          else {
            // Space
            rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS;
            //Serial.print(" s");
          }
          //Serial.print(rawCodes[i - 1], DEC);
        }
        //Serial.println("");
      }
      else {
        if (codeType == NEC) {
          //debug("Received NEC: ");
          if (results->value == REPEAT) {
            // Don't record a NEC repeat value as that's useless.
            //debug("repeat; ignoring.");
            return;
          }
        }
        receivedSignal = String(results->value, HEX);
        receivedSignal.toUpperCase();
    
        // So now we are listening if someone has send the BEAMER ON ir signal 3 times in a row.
        // we have three variables to store the millisecond when the signal was received.
        // the next variable iteration will be populated by the system if the last signal was send less than
        // repeatTimeoutMillis milliseconds.
        // e.g. if repeatTimeoutMillis=500 it means a signal is valid repeated when the previous signal was 
        // send not longer than half a second before! 
        // Until it reaches the third iteration where it executes the command after 3 repeats of the signal.
        // In case the previous signal was send longer than repeatTimeoutMillis ago the iteration resets and 
        // sets the newly received signal as iteration 1 to start the cyrcle with this signal again.
        //
        if(receivedSignal == "4CB340BF") {
          debug("--------Detected My Signal!");
          if(receivedBeamerOnSignal1 == 0) {
            receivedBeamerOnSignal1 = timenow;
            debug("----SET RS1");
            
          } else if(receivedBeamerOnSignal1 != 0 && receivedBeamerOnSignal2 == 0) {
            receivedBeamerOnSignal2 = timenow;
            if( receivedBeamerOnSignal2 > receivedBeamerOnSignal1+repeatTimeoutMillisThreshold ) {
              receivedBeamerOnSignal1 = timenow;
              receivedBeamerOnSignal2 = 0;
              receivedBeamerOnSignal3 = 0;
              debug("----RESET ON RS2: ");
            } else {
              debug("----SET RS2");
            }
            
          } else if(receivedBeamerOnSignal2 != 0) {
            receivedBeamerOnSignal3 = timenow;
            if( receivedBeamerOnSignal3 > receivedBeamerOnSignal2+repeatTimeoutMillisThreshold ) {
              receivedBeamerOnSignal1 = timenow;
              receivedBeamerOnSignal2 = 0;
              receivedBeamerOnSignal3 = 0;
              debug("----RESET ON RS3: ");
            } else {
              debug("----SET RS3");
    
              //esp8266.end();
              delay(200);
    
              //TURN OFF BEAMER BEGIN
              debug("--------TURN OFF BEAMER !!!");
              irsend.sendNEC(0x4CB3748B, 32);
              delay(200);
              irsend.sendNEC(0x4CB3748B, 32);
              delay(200);
              irsend.sendNEC(0x4CB3748B, 32);
              //TURN OFF BEAMER END
    
              //TURN OFF RECEIVER BEGIN
              manageAVR(AVRHost, AVRSubpage);
              //TURN OFF RECEIVER END
    
              //reenable IR receiver after sending
              irrecv.enableIRIn();
              irrecv.resume();
    
              receivedBeamerOnSignal1 = 0;
              receivedBeamerOnSignal2 = 0;
              receivedBeamerOnSignal3 = 0;
            }
          }
          
        }
        
        codeValue = results->value;
        codeLen = results->bits;
      }
    }
    
    //--------------------------------------Yamaha AVR Functions--------------------------------------
    
    void manageAVR(String Host, String Subpage)
    {
    
      String getRequest = "POST "+Subpage+" HTTP/1.1\r\nHost:"+Host+"\r\nContent-Type: text/xml;charset=\"UTF-8\"\r\nAccept: text/xml\r\nContent-Length: " + String(strlen(AVRStopMessage)+1) + "\r\n\r\n" + String(AVRStopMessage) + "\r\n";
    
      sendCom("AT+CIPSTART=\"TCP\",\""+Host+"\",80", "OK");
      sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
      esp8266.println(getRequest);
    
      //debug(getRequest);
    
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          sendCom("AT+CIPCLOSE", "OK");
        }
      }
    
    }
    
    //-----------------------------------------Config ESP8266------------------------------------
    
    boolean espConfig()
    {
      boolean succes = true;
      esp8266.setTimeout(5000);
      succes &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation(SSID, PASSWORD)) {
        succes &= true;
        debug("WLAN OK");
        debug("IP:");
        debug(sendCom("AT+CIFSR"));
      }
      else
      {
        succes &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      succes &= sendCom("AT+CIPMODE=0", "OK");
      succes &= sendCom("AT+CIPMUX=0", "OK");
    
      return succes;
    }
    
    boolean configStation(String vSSID, String vPASSWORT)
    {
      boolean succes = true;
      succes &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      succes &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return succes;
    }
    
    //-----------------------------------------------Controll ESP-----------------------------------------------------
    
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        debug("ESP ERR: " + command);
        return false;
      }
    }
    
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
    
    //-------------------------------------------------Debug Functions------------------------------------------------------
    void serialDebug() {
      while (true)
      {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
    
    void debug(String Msg)
    {
        Serial.println("FR:" + String(freeRam()) + " - " + Msg);
    }
    
    int freeRam() 
    {
      extern int __heap_start, *__brkval; 
      int v; 
      return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
    }

    lg und danke

    • This topic was modified 6 years, 8 months ago by Terra.
    • This topic was modified 6 years, 8 months ago by Terra.
    • This topic was modified 6 years, 8 months ago by Terra.
    #1107
    Terra
    Participant

    Ich hab den Fehler inzwischen gefunden, es war wie vermutet die Variable/Konstante:

    #define AVRStopMessage “<?xml version=\”1.0\” encoding=\”utf-8\”?><YAMAHA_AV cmd=\”PUT\”><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>”

    Wenn ich die Zeichenkette im obigen Programm reduziere schickt er den Webservice Call, ansonsten nicht.
    Ich hab jetzt nochmal ein paar debug ausgaben verkürzt, HTTP Header entfernt und ein paar Sachen anders gelöst oder gelöscht, jetzt klappt alles :)

    WENN:
    – Ich 3x die “TV” Taste meiner Fernbedienung drücke

    DANN:
    – Soll sich mein Beamer ausschalten (durch 3x dasselbe IR Signal senden)
    – Mein Yamaha AV-Receiver ausschalten (durch Webservice Call auf lokale IP)
    – Zusätzlich blinkt eine LED bei jedem IR Signal das er empfängt, nur damit ich sehe ob er noch zuhört.

    #include <IRremote.h>
    #include <SoftwareSerial.h>
    SoftwareSerial esp8266(11, 12); // RX, TX
    
    const char* WiFiSSID       = "*****";
    const char* WiFiPASSWORD   = "*****";
    
    const char* AVRHost    = "192.168.0.12";
    const char* AVRSubpage = "/YamahaRemoteControl/ctrl";
    
    /*
    Yamaha XML Messages
    Note!
    - AVROutputSetVolume has -39 hardcoded as defined volume
    - AVROutputHDMI1 the outputs of the Yamaha must be set via the NAMES that were assigned in 
      the configuration. My HDMI1 output is called HTPC. Default it most likely the name is HDMI1. 
      "HTPC" is hardcoded in the request!
      All of the extra ones are disabled because of space issues...
    */
    const char* AVRStopMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?><YAMAHA_AV cmd=\"PUT\"><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>";
    
    /* Some IR Codes
    TURN BEAMER ON    Value:      4CB340BF Type: 3 Length: 32
    TURN BEAMER OFF   Value:      4CB3748B Type: 3 Length: 32
    TURN RECEIVER ON/OFF Value:   7E8154AB Type: 3 Length: 32 - And add a FFFFFFFF Type 3 Length 0
    
    Type 2
    up type 2 800F041E
    down type2 800F841F
    
    */
    const char* sigBeamerOn        = "4CB340BF";
    //const char* sigBeamerOff       = "4CB3748B";
    //const char* sigAVReceiverOnOff = "7E8154AB";
    
    unsigned long timenow = 1;
    unsigned long receivedBeamerOnSignal1 = 0;
    unsigned long receivedBeamerOnSignal2 = 0;
    unsigned long receivedBeamerOnSignal3 = 0;
    const long repeatTimeoutMillisThreshold = 1000;
    
    const int LED_WLAN = 13;
    const int GND = 2;
    const int RECV_PIN = 7;
    const int GND2 = 8;
    const int VCC = 9;
    const int LED = 5;
    
    IRrecv irrecv(RECV_PIN);
    IRsend irsend;
    decode_results results;
    
    void setup() {
    
      Serial.begin(19200);
      irrecv.enableIRIn(); // Start the receiver
      esp8266.begin(19200);
    
      //Set Pins for LED and IR Monitor
      pinMode(GND, OUTPUT);
      pinMode(GND2, OUTPUT);
      pinMode(VCC, OUTPUT);
      pinMode(LED, OUTPUT);
      digitalWrite (GND, LOW);
      digitalWrite (GND2, LOW);
      digitalWrite (VCC, HIGH);
    
      if (!espConfig()) serialDebug();
      else digitalWrite(LED_WLAN, HIGH);
    
    }
    
    void loop() {
    
      //Serial.println("I am Alive!");
    
      //IR RECEIVER SIGNAL
      if (irrecv.decode(&results)) {
        timenow = millis();
        analyzeCode(&results);
        Serial.print(F("ir"));
        digitalWrite(LED, 1);
        delay(50);
        digitalWrite(LED, 0);
        irrecv.resume();
      }
    
    }
    
    void analyzeCode(decode_results *results) {
    
      results->decode_type;
      
      String receivedSignal;
      receivedSignal = String(results->value, HEX);
      receivedSignal.toUpperCase();
    
      // So now we are listening if someone has send the PROJECTOR ON ir signal 3 times in a row.
      // we have three variables to store the millisecond when the signal was received.
      // the next variable iteration will be populated by the system if the last signal was send less than
      // repeatTimeoutMillis milliseconds.
      // e.g. if repeatTimeoutMillis=500 it means a signal is valid repeated when the previous signal was 
      // send not longer than half a second before! 
      // Until it reaches the third iteration where it executes the command after 3 repeats of the signal.
      // In case the previous signal was send longer than repeatTimeoutMillis ago the iteration resets and 
      // sets the newly received signal as iteration 1 to start the cycle with this signal again.
      //
      if(receivedSignal == sigBeamerOn) {
        Serial.println(F("+")); //Detected My Signal
        if(receivedBeamerOnSignal1 == 0) {
          receivedBeamerOnSignal1 = timenow;
          Serial.println(F("1")); //Set 1
          
        } else if(receivedBeamerOnSignal1 != 0 && receivedBeamerOnSignal2 == 0) {
          receivedBeamerOnSignal2 = timenow;
          if( receivedBeamerOnSignal2 > receivedBeamerOnSignal1+repeatTimeoutMillisThreshold ) {
            receivedBeamerOnSignal1 = timenow;
            receivedBeamerOnSignal2 = 0;
            receivedBeamerOnSignal3 = 0;
            Serial.println(F("r2")); //Reset on 2
          } else {
            Serial.println(F("2")); //Set 2
          }
          
        } else if(receivedBeamerOnSignal2 != 0) {
          receivedBeamerOnSignal3 = timenow;
          if( receivedBeamerOnSignal3 > receivedBeamerOnSignal2+repeatTimeoutMillisThreshold ) {
            receivedBeamerOnSignal1 = timenow;
            receivedBeamerOnSignal2 = 0;
            receivedBeamerOnSignal3 = 0;
            Serial.println(F("r3")); //Reset on 3
          } else {
            Serial.println(F("3")); //Set 3
    
            delay(200);
    
            //TURN OFF PROJECTOR BEGIN
            Serial.println(F("xb")); //Turn off projector
            irsend.sendNEC(0x4CB3748B, 32);
            delay(200);
            irsend.sendNEC(0x4CB3748B, 32);
            delay(200);
            irsend.sendNEC(0x4CB3748B, 32);
            delay(200);
            irsend.sendNEC(0x4CB3748B, 32);
            
            //reenable IR receiver after sending
            irrecv.enableIRIn();
            //TURN OFF PROJECTOR END
    
            Serial.println(F("xr")); //Turn off AVR-Receiver
            //TURN OFF RECEIVER BEGIN
            manageAVR();
            //TURN OFF RECEIVER END
    
            receivedBeamerOnSignal1 = 0;
            receivedBeamerOnSignal2 = 0;
            receivedBeamerOnSignal3 = 0;
          }
        }
        
      }
    
    }
    
    //--------------------------------------Yamaha AVR Functions--------------------------------------
    
    void manageAVR()
    {
    
      //Usually there are more headers in the original request, but we need to save space and cannot add them
      String getRequest = "POST "+String(AVRSubpage)+" HTTP/1.1\r\nHost:"+String(AVRHost)+"\r\nContent-Length: " + String(strlen(AVRStopMessage)+1) + "\r\n\r\n" + String(AVRStopMessage) + "\r\n";
    
      sendCom("AT+CIPSTART=\"TCP\",\""+String(AVRHost)+"\",80", "OK");
      
      sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
      esp8266.println(getRequest);
    
      Serial.println(getRequest);
    
      delay(1000);
    
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          sendCom("AT+CIPCLOSE", "OK");
        }
      }
    
    }
    
    //-----------------------------------------Config ESP8266------------------------------------
    
    boolean espConfig()
    {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation()) {
        success &= true;
        Serial.println(F("WLAN OK"));
        Serial.println(F("IP:"));
        Serial.println(sendCom("AT+CIFSR"));
      }
      else
      {
        success &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      success &= sendCom("AT+CIPMODE=0", "OK");
      success &= sendCom("AT+CIPMUX=0", "OK");
    
      return success;
    }
    
    boolean configStation()
    {
      boolean success = true;
      success &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom("AT+CWJAP=\"" + String(WiFiSSID) + "\",\"" + String(WiFiPASSWORD) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
    
    //-----------------------------------------------Controll ESP-----------------------------------------------------
    
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        Serial.println("ESP ERR: " + command);
        return false;
      }
    }
    
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
    
    //-------------------------------------------------Debug Functions------------------------------------------------------
    
    void serialDebug() {
    }
    • This reply was modified 6 years, 8 months ago by Terra.
    • This reply was modified 6 years, 8 months ago by fk.
    #1698
    Puuh
    Participant

    Hi, ich programmiere auch gerade ein IR Modul und möchte meinen Yamaha Receiver steuern. Der Code 0x7E8154AB ist ja für Power. Wie hast du diesen Code ermittelt bzw. wo hast du diesen Code gefunden? Ich suche bislang vergeblich nach den Codes der gesamten RV300 Fernbedienung.
    Viele Grüße
    Puuh

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.