Testing Pimage for image for sucessufull load. (avoiding bad gateway 502 error crash)

edited June 2017 in Raspberry PI

I have a script that looks looks at a series of constantly updating remote .jpgs on line that are generated from cams. The script jumps into an array, pulls a random URL, and displays the .jpg located there for 10sec updating it every sec. (It's cam footage.)

The script needs to run indefinitely off a Pi. Yet it inevitably crashes after 5 mins to 5 hours (on pc, mac and pi) as it hits a 502 error. (bad gateway) I've attempted to build in an error check to preempt the drawing of a wonky (possibly unload-able) Pimage, but it doesn't seem to be working. I'm not sure if A) its my code and I'm using returnImage() wrong, or B) i'm going about solving the problem the wrong way.

Any help would be greatly appreciated.

PLEASE NOTE: the cams that supply the remote jpgs aren't finalized. They are removed from the code. The array is filled with place holders.

    PImage webImg;
    PImage testImg;

    int timer;

    String[] camlist = {

    "random_url_with_JPG_here",
    "random_url_with_JPG_here",
    "random_url_with_JPG_here"

    };

    //find length of array
    int camListLength = int(random(camlist.length));

    void setup() {

      testImg = requestImage("webImg", "jpg");

      noCursor();
      fullScreen();
      background(0);
    }


    void draw() {
      if (millis() - timer >= 10000) {
        camLoad();
        timer = millis();
      } else {
        displayWebImage();
      }
    } 


    void camLoad() {
      //find length of array
      camListLength = int(random(camlist.length));
    }


    void displayWebImage() {

      // load random cam url into 'webImg'
      webImg = loadImage(camlist[camListLength], "jpg");

      // test load
      println(testImg.width);
      if (testImg.width == 0) {
        println("Not Loaded");
      } else if (testImg.width == -1) {
        // display 'webImage'
        image(webImg, 0, 0, 800, 480);
      }

      // cache cleanup 
      g.removeCache(webImg);
      delay(1000);

      // frame count
      println(frameCount+" "+g.getCache(webImg));
    }

Just for good measure, here is the error;

java.io.IOException: Server returned HTTP response code: 502 for URL Caused by: java.io.IOException: Server returned HTTP response code: 502 for URL The file is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.

Answers

  • From this code, I don't see what line will cause the HTTP response error. I can see you are checking the dimensions of testImg but this object is only loaded in setup. Does your provided code reproduce the error?

    Kf

  • Thanks for the response.

    The error is happening on line 54. When an image that should be buffered, attempts to be drawn, but the image can't be found or isn't buffered. I guess I'm trying to tell the code to just skip attempting to draw the image if it can't be found or hasn't loaded yet.

    returned error -> "The file is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable." and "java.io.IOException: Server returned HTTP response code: 502 for URL"

    Now that I'm looking at it I think I may have forgotten to test for the third state in the requestImage()... going to add that now, and hope that solves the problem.

  • edited June 2017

    I updated the testing code, and now it never displays the image. I believe the testing code is correct, but my syntax and placement for requestImage() might be wrong.

    The image I'm testing is updating once a second, but requestImage() needs to be defined in the void setup, and will only take a string as a parameter, (not webImg which I've defined as the Pimage variable that holds the url location.)

    If I remove the test and the requestImage(), I still eventually get the 502 error...

    thanks again.

    Updated code;

        PImage webImg;
        PImage testImg;
    
        int timer;
    
        String[] camlist = {
    
        "random_url_with_JPG_here",
        "random_url_with_JPG_here",
        "random_url_with_JPG_here"
    
        };
    
        //find length of array
        int camListLength = int(random(camlist.length));
    
        void setup() {
    
          testImg = requestImage("webImg", "jpg");
    
          noCursor();
          fullScreen();
          background(0);
        }
    
    
        void draw() {
          if (millis() - timer >= 10000) {
            camLoad();
            timer = millis();
          } else {
            displayWebImage();
          }
        } 
    
    
        void camLoad() {
          //find length of array
          camListLength = int(random(camlist.length));
        }
    
    
           void displayWebImage() {
    
          // load random cam url into 'webImg'
          webImg = loadImage(camlist[camListLength], "jpg");
    
          // test load
          println(testImg.width);
          if (testImg.width == 0) {
            println("Not Loaded");
          } else if (testImg.width == -1) {
            println("random error");
          } else {
            // display 'webImage'
            image(webImg, 0, 0, 800, 480);
            // cache cleanup 
           g.removeCache(webImg);
            delay(1000);
            // frame count
            println(frameCount+" "+g.getCache(webImg));
          }
        }
    
  • edited June 2017

    that code appears to call loadImage every frame. don't do that.

    load all the images in setup. choose from your array of images, not image urls.

  • On pre-loading. It's reaching out and and grabbing a new frame from a random cam. The cams are updating a still .jpg every few milliseconds, and I'm grabbing a new frame every second. Every ten seconds I'm switching cams. So there is no way to pre-load the images in setup(), as they won't exist until the second before they are pulled down, plus this needs to run for a week at a time...

    As for your suggestion to not loadImage() every frame. I totally understand why I shouldn't load it every frame. Normally, I'd drop it above line 56 so it's only called before the image(). But, I need to test the image first, before I draw it, and I need to load what I'm testing, so i'm not sure where else to place it?

    Last, with the requestImage(). Whats the proper syntax? Is there no way to use requestImage() outside the setup()?

  • Ok, that makes more sense. Still shouldn't do it every frame though.

    That description makes me wonder whether the 502 is from trying to load a half-saved image.

    Or the usual memory problems (although that's usually a slightly more obvious error message)

  • Yup! I'm almost positive the 502 is causing a bad load, and when it tries to image() it crashes. At least based on the errors in the console scroll. (I also thought it might be memory, too, and I significantly lowered the mb available, but it didn't shorten the time before it crashed... and I have it clearing the cache just in case.)

    The real issue is this -> How do you error check loadImage() or image() with a runtime-determined remote url as it's target? requestImage() doesn't seem to be up to the task, as it's parameters can't seem to handle a dynamic variable, only a static string.

    Thanks for the response, have you, or anyone, ever bumped up against this?

  • Solved. requestImage()works fine in the draw loop, as long as it has at least half a second time to breath before getting hit with a new image.

    Here is the final script if anyone needs it;

        void displayWebImage() {
    
          // load random cam url into 'webImg'
          webImg = loadImage(camlist[camListLength], "jpg");
    
          String WebImgURL = camlist[camListLength];
          testImg = requestImage(WebImgURL, "jpg");
          delay(1000);
    
          // test load
          println(WebImgURL);
          if (testImg.width == 0) {
            println("Not Loaded");
          } else if (testImg.width == -1) {
            println("random error");
          } else {
            // display 'webImage'
            image(webImg, 0, 0, 800, 480);
            // cache cleanup 
            g.removeCache(webImg);
            // frame count
            println(frameCount+" "+g.getCache(webImg));
          }
        }
    
  • two things the documentation specifically warns you about are a) loading images in draw (or something called from draw) and b) using delay() anywhere...

  • I would prefer to send a new request only after the old request is done (by checking the image dimensions as documented in the reference of requestImage(). Another approach I would try is using threads. However, I wouldn't create new threads without any sort of restriction in draw. It is just not proper....

    Kf

Sign In or Register to comment.