B4R Question Porting ESP8266 IR Remote Control Project to B4R

Discussion in 'B4R Questions' started by bdunkleysmith, Jan 9, 2019.

  1. bdunkleysmith

    bdunkleysmith Member Licensed User

    I have been working on an IR remote control project to assist my elderly father control his cable TV box and TV itself. I have a version working using a B4A kiosk mode app on a tablet connected via Bluetooth to an Arduino UNO which drives two IR emitters; one for the cable TV box and one for the TV.

    But this Talk to your CD player using Google Home project piqued my interest and I began duplicating it in B4R.

    I've created B4R code which connects the ESP8266 to my network and can drive an IR emitter to control the TV, but I'm struggling to replicate the functionality of the original Arduino code:

    Code:
    #include <Arduino.h>
    #include <IRremoteESP8266.h>
    #include <IRsend.h>
    #include <framework.h>

    #define PanasonicAddress      (0x4004)

    typedef struct {
      char 
    const * name;
      uint32_t code;
    } button_t;

    button_t buttons[] = {
      { "power", 0x0538BC81 },
      { "pause", 0x05505005 },
      { "play", 0x05505005 },
      { "next song", 0x0538526F },
      { "previous song", 0x053892AF },
      { "track 1", 0x05380835 },
      { "track 2", 0x053888B5 },
      { "track 3", 0x05384875 },
      { "track 4", 0x0538C8F5 },
      { "track 5", 0x05382815 },
      { "track 6", 0x0538A895 },
      { "track 7", 0x05386855 },
      { "track 8", 0x0538E8D5 },
      { "track 9", 0x05381825 },
      { "two digits", 0x0538211C },
      { "volume up", 0x05000401 },
      { "volume down", 0x05008481 },
      { NULL, 0x0 }
    };

    IRsend irsend(4);  // An IR LED is controlled by GPIO pin 4 (D2)

    void handleRoot(void)
    {
        String message = "";

        if (Framework::server.args() >= 1 &&
            Framework::server.argName(0) == "req") {
             
          String buttonReq = Framework::server.arg(0);    
          button_t const *p;
          for (p = buttons; p->name; p++) {
            if ( String(p->name) == buttonReq ) {
              break;
            }
          }
          if (p->name) {
              message += "Sending ";
              message += p->name;
              message += "\n\n";
              irsend.sendPanasonic(PanasonicAddress, p->code);
          } else {
              message += "'";
              message += buttonReq;
              message +="' not found\n\n";
          }
        }
        message += "Valid commands are:<ul>\n\n";
        for (button_t const *p = buttons; p->name; p++) {
          message += "<li>";
          message += "<a href=\"/ir?ir=";
          message += p->name;
          message += "\">";
          message += p->name;
          message += "</li>\n";
        }
        message += "</ul>";

        Serial.println(message);
        Framework::server.send( 200, "text/html", message );
    }


    void setup()
    {
      Framework::begin();
      Framework::server.on("/ir", handleRoot);
      Framework::server.begin();
      delay(500);  // Wait a bit for the serial connection to be establised.
      irsend.begin();

     if (!MDNS.begin("ir-interface")) {
        Serial.println("Error setting up MDNS responder!");
        while(1) {
          delay(1000);
        }
      }
      MDNS.addService("http", "tcp", 80);
     
      Serial.println("Ready");
    }

    void loop() {
      // test only
      irsend.sendPanasonic(PanasonicAddress, 0x05505005);

      Framework::handle();
    }
    particularly where it appears to set the endpoint to "ir-interface" (!MDNS.begin("ir-interface"))
    in lieu of the 192.168.0.15 assigned to the ESP8266 and handles calls to the endpoint (Framework::server.on("/ir", handleRoot).

    Below is my current code which can extract a code to trigger sending of the respective IR code via a web browser, eg. 192.168.0.15/?req=power:

    Code:
    Sub Process_Globals
        
    Private wifi As ESP8266WiFi
        
    Private server As WiFiServerSocket
        
    Private sp As Serial
        
    Private astream As AsyncStreams
        
    Private bc As ByteConverter
        
    Private irsend As IrSend
    End Sub

    Private Sub AppStart
        sp.Initialize(
    115200)
        
    Log("AppStart")
        ScanNetworks
        ConnectToNetwork
        irsend.Enable(
    438'frequency = 38khz
        server.Initialize(80"server_NewConnection")
        
    server.Listen
    End Sub

    Sub Astream_NewData (Buffer() As Byte)
        
    If bc.IndexOf(Buffer, "GET") <> -1 Then
            
    Dim command As String
            
    Dim i1 As Int = 0
            
    Dim i2 As Int = 0
            
    For Each b1() As Byte In bc.Split(Buffer, " ")
                
    If i1 = 1 Then
                    
    For Each b2() As Byte In bc.Split(b1, "=")
                        
    If i2 = 1 Then
                            command = bc.StringFromBytes(b2)
                            sendNewData(command)                      
                        
    End If
                        i2 = i2 + 
    1
                    
    Next
                
    End If
                i1 = i1 + 
    1
            
    Next
        
    Else
            CallSubPlus(
    "CloseConnection"2000)
        
    End If
    End Sub

    Private Sub CloseConnection(u As Byte)
        
    Log("close connection")
        
    If server.Socket.Connected Then
            
    server.Socket.Stream.Flush
            
    server.Socket.Close
        
    End If
    End Sub

    Sub AStream_Error
        
    Log("error")
    End Sub

    Sub Server_NewConnection (NewSocket As WiFiSocket)
        
    Log("Client connected")
        astream.Initialize(NewSocket.Stream, 
    "Astream_NewData""Astream_Error")
    End Sub

    Sub sendNewData(command As String)
        
    Select command
        
    Case "power"
            irsend.sendPanasonic(
    0x40040x100BCBD)    'Toggle TV power on/off
            Log("Sending IR code for: ", command)
        
    End Select
    End Sub

    Sub ScanNetworks
        
    Dim numberOfNetworks As Byte = wifi.Scan
        
    Log("Found ", numberOfNetworks, " networks")
        
    For c = 0 To numberOfNetworks - 1
            
    Log("SSID: ", wifi.ScannedSSID(c), "|RSSI: ", wifi.ScannedRSSI(c))
        
    Next
    End Sub

    Sub ConnectToNetwork
        
    If wifi.Connect2("SSID""password") = False Then
            
    Log("Error connecting to network")
            
    Return
        
    Else
            
    Log("Connected to network")
            
    Log("My IP address: ", wifi.LocalIp)
        
    End If
    End Sub
    but I think it's pretty clunky and it works only once, with follow-up calls ignored, because there is an error thrown as reported in the log:

    Code:
    Found 5 networks
    SSID: Telstra1943|RSSI: -
    30
    SSID: EQ|RSSI: -
    91
    SSID: DIRECT-E6-HP OfficeJet Pro 
    6970|RSSI: -50
    SSID: Fon WiFi|RSSI: -
    89
    SSID: Telstra0C3E|RSSI: -
    93
    Connected 
    to network
    My IP 
    address192.168.0.15
    Client connected
    Sending IR code 
    forpower
    close connection
    error
    close connection
    close connection
    close connection
    Any pointers or suggestions on how I should use better or other B4R code to achieve the functionality of the original Arduino project code or at least address the error which prevents follow-up calls, would be appreciated.
     
    Last edited: Jan 9, 2019
  2. Erel

    Erel Administrator Staff Member Licensed User

  3. bdunkleysmith

    bdunkleysmith Member Licensed User

    Thanks for your usual great guidance Erel.

    Apart from the problems cited above, I decided to investigate alternatives because I balked at the requirement to install a reverse-proxy and TLS-certificates on my router.

    However I've struck another issue with my chosen alternative method involving use of MQTT which I have documented here.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice