Electron and Webhooks ESOCKETTIMEDOUT

Here’s the scenario.
I have 20 Electrons paired (10 pairs). A database table with the device IDs and their paired device ID. Elements for each Electron are a tactile switch and NeoPixel.
Concept is you click the switch on one, it activates the NeoPixel on the other.
There are 3 webhooks I’m using kbOn, kbReceipt, kbOff

Switch pressed, webhook “kbOn” is sent own device ID. PHP script checks database for the device ID and gets the paired ID. Script then tells the paired ID through an exposed function to turn on.

Once the on function is hit, the Electron sends own device ID to webhook kbReceipt. PHP script checks database for device and gets the paired ID. Script then tells the paired ID through an exposed function that the message was received.

Switch released, webhook “kbOff” triggered etc etc.

I’m having an issue where the actions are happening but they’re interspersed with ESOCKETTIMEDOUT. I suspect this is network connection particular to the Electron board. I had this system working successfully over the course of a few days on a pair of Photons.

I wonder if I should be looking at setting it up to maintain connection to the network to combat the issue. I’ve done enough snooping around to see that is the likeliest solution but any additional insight or direction would be greatly appreciated.

Forum Post on ESOCKETTIMEDOUT

If you only need your relay DB to pair devices, I’d load off the pairing to the devices directly and cut out the man-in-the-middle via pub/sub.

I was using the man-in-the-middle for logging as well but honestly, I’m really frustrated by quantity of communication errors going and if going direct solves the problem, I’ll try it out.

Took me all day to get this worked out. Now I have it set up to only query the DB once to get it’s paired ID. Using publish to send out the press and release events. Sends out it paired ID and any board subscribed to to events checks to see if its ID matches the one sent. If so, react.

I’m still alarmed by the slow response time and still getting the occasional ESOCKETTIMEDOUT but I guess it’s better?

Have you considered pairing the devices by device name or via a Particle.function() to store the partner ID in EEPROM?

Still not targeting the ESOCKETTIMEOUT issue tho’

For that we might need to see your code. You may be running out on free sockets on the device after a while which might be the cause - but there are also other possible reasons only the code review would reveal.

1 Like

Getting the pair id isn’t an issue. The electrons (and photons) start up, make their connections grab the ID and wait for input and they do it quickly. I’m concerned right now because I spent so much time on the hardware build that the firmware (which works consistently on the photons) is simplistic. I don’t know if I should be hitting the connection more to make sure the electrons are more responsive. What I’m noticing is a delay of up to 30 seconds at times for the device to notice.

the code is

    // This #include statement was automatically added by the Particle IDE.
    #include <neopixel.h>

    //define project pins on board
    #define BUTTON_PIN D7           //tactile switch pin
    #define LED_PIN D4              //red LED pin
    #define COLOUR_PIN D5            //ground pin for colour selection, grounded is green
    #define PIXEL_PIN D6            //neopixel pin
    //define neopixel details
    #define PIXEL_COUNT 1           //how many neoPixels
    #define PIXEL_TYPE WS2812B      //neopixel chip type
    Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
    //NOTE: these neopixels are GRB
    //strip.setPixelColor(pixelNum,strip.Color(GREEN,RED,BLUE));
    //bowtie colour controller
    int colourToggle = HIGH;
    uint32_t LEDcolour;
    //set public function
    int ledController(String command);
    #define PARTICLE_DEVICE_ID System.deviceID()
    #define TTL 60
    #define AUTH_KEY "<----redacted---->"
    String data="";
    //
    int ledOn(String command);
    int receipt(String command);
    int ledOff(String command);
    //
    bool activeLED = false;

    // Colours change in "steps" between their initial and final values
    unsigned int stepDelay = 200;  //time (in ms) between steps
    byte stepLen = 40;              //number of steps in transition
    // Colour transition variables
    byte Rnew,Gnew,Bnew;            //Colour value when sensor not activated
    //
    bool stepEnable = false;        //run the step sequence
    unsigned long stepTimer = 0;    //step timer value
    int stepCount = 0;              //step counter
    int Rcur,Rlast,Rled;            //Red previous and transition (new) values
    int Gcur,Glast,Gled;            //Green previous and transition (new) values
    int Bcur,Blast,Bled;            //Blue previous and transition (new) values

    String pairID = "null";         //to be provided by pairSetter webhook  
    int setPairing(String command);
    bool checked = false;           //boolean to determine if button requires checking.
    int pairDelay = 5000;               //wait 5 seconds to hit pairing webhook
    int pairTimer,buttonTimer,ledTimer = 0;      //initialize timers
    bool pairLoop,buttonLoop,ledLoop = false;   //initialize loop booleans
    int buttonDelay = 120;              //delay to check button
    int ledDelay = 100;

    void setup(){
        pinMode(COLOUR_PIN,INPUT_PULLUP);
        digitalWrite(COLOUR_PIN,HIGH);
        pinMode(BUTTON_PIN, INPUT_PULLUP);
        digitalWrite(BUTTON_PIN,LOW);
        //JSON object to be sent to the webhooks
        //consisting of a generated authorization key "AUTH_KEY"
        //and board's own device ID PARTICLE_DEVICE_ID
        data = "{";
        data.concat("\"auth_key\":\"");
        data.concat(AUTH_KEY);
        data.concat("\",\"");
        data.concat("device_id\":\"");
        data.concat(PARTICLE_DEVICE_ID);
        data.concat("\"}");
        //public function to set pair ID
        Particle.function("pairSetter", setPairing);
        //public variable to check correct pair ID is received.
        Particle.variable("pair_ID",pairID);
        Particle.subscribe("kbear_button_press",buttonEventPress,MY_DEVICES);
        Particle.subscribe("kbear_button_release",buttonEventRelease,MY_DEVICES);
        strip.begin();
        strip.show();
        colourToggle = digitalRead(COLOUR_PIN);
        if(colourToggle == HIGH){
            Rled = 200;
            Gled = 0;
            Bled = 0;
        }else{
            Rled = 0;
            Gled = 200;
            Bled = 0;
        }
        Rlast = 0;
        Glast = 0;
        Blast = 0;
        strip.setPixelColor(0,strip.Color(Gled,Rled,Bled));
        strip.show();
        pairLoop = true;
    }
    void loop(){
         if (pairLoop && millis() > pairTimer + pairDelay) {
            // Reset timer
            pairTimer = millis();   //set stepTimer at the end of each loop
                                //possible other timers will use it
            strip.setPixelColor(0,strip.Color(200,200,200));
            strip.show();
            //trigger the publish
            Particle.publish("kbFindPair", data, PRIVATE);
            pairLoop = false;
        }
        if(buttonLoop && millis() > buttonTimer + buttonDelay){
            buttonTimer = millis();
            buttonCheck();        
        }
          if (ledLoop && millis() > ledTimer + ledDelay) {
              // Reset timer
              ledTimer = millis();
              transitionLED();
          }
    }
    void buttonCheck(){
          if(digitalRead(BUTTON_PIN)==LOW && !checked){
              // digitalWrite(AUDIO_PIN,LOW);
              Particle.publish("kbear_button_press",pairID,TTL,PRIVATE);
              //click once. set checked to true
              //String data = String::format("{ \"device_id\": \"%s\"}", PARTICLE_DEVICE_ID);
              //Particle.publish("sendSignalOn", data, PRIVATE);
              //Particle.publish("kbOn", data, PRIVATE);
              checked=!checked;
            }else if(digitalRead(BUTTON_PIN)==HIGH && checked){
                //digitalWrite(AUDIO_PIN,HIGH);
                //check release once, set checked to false
                Particle.publish("kbear_button_release",pairID,TTL,PRIVATE);
              //Particle.publish("kbOff", data, PRIVATE);
                checked = !checked;
            }
            delay(120); 
        }
    void setLED(bool active){
        activeLED = active;
        uint32_t currentColour;
          if(activeLED){
              Rnew = Rled;
              Gnew = Gled;
              Bnew = Bled;
          }else{
              //currentColour = strip.Color(0,0,0);
              Rnew = 0;
              Gnew = 0;
              Bnew = 0;
          }
          Rlast = Rcur;
          Glast = Gcur;
          Blast = Bcur;
         // strip.setPixelColor(0,currentColour);
         // strip.show();
         ledLoop = true;
         stepCount = 0;
      }
    int setPairing(String command){
        int i = 0;
        int imax = 10;
            int r;
            int g;
            int b;
        while(i<imax){
            r = random(200);
            g = random(200);
            b = random(200);
            strip.setPixelColor(0,strip.Color(g,r,b));
            strip.show();
            delay(200);
            i++;
        }
        pairLoop = false;
        buttonLoop = true;
        pairID = command;
        Rcur = r;
        Gcur = g;
        Bcur = b;
        setLED(false);
        return 1;
    }
      void transitionLED(){
            // Assign new transition colours
            Rcur = map(stepCount,0,stepLen,Rlast,Rnew);
            Gcur = map(stepCount,0,stepLen,Glast,Gnew);
            Bcur = map(stepCount,0,stepLen,Blast,Bnew);
            strip.setPixelColor(0, strip.Color(Gcur,Rcur,Bcur));
            strip.show();
            // Increment/rollover step counter
            stepCount++;
            // Once transition is complete, set last = new
            if (stepCount > stepLen) {
                Rlast = Rcur;
                Glast = Gcur;
                Blast = Bcur;
                ledLoop = false;
                stepCount = 0;
            }
    }
    void buttonEventPress(const char *event, const char *data){
        if(strcmp(data,PARTICLE_DEVICE_ID)==0){
            //this is from my partner bear
            //change my LED
            setLED(true);
          }
    }
    void buttonEventRelease(const char *event, const char *data){
        if(strcmp(data,PARTICLE_DEVICE_ID)==0){
            //this is from my partner bear
            setLED(false);
        }
    }

OK, there isn’t really anything to see on the device’s side, but as the discussion linked in your original post suggests, the ESOCKETTIMEOUT is more likely due to the remote server being slow.
In this task the Electron (and its network connection quality) isn’t even part of the equation. Once the Particle backend has taken the webhook request (event) it’s only talking to the remote server and if that does not complete its reply within the 5 sec timeout, you’ll get the ESOCKETTIMEOUT.
How does your remote server look - how quickly does it respond when you access it directly?

i’ve set up a pair of photons with the exact same code and they work fast. we tested it via direct connect, via the particle console, and via the boards. consistently the largest discrepancy is the electrons.