How to display an online_image:

I am trying to define an online_image so that I can display it on ili9xxx.
After days of trial and error, I have come up with this horrendous URL:

online_image:
  - url: "http://192.168.0.204:8123/api/camera_proxy/camera.esp32_lpg_level_esp_eye?token=36e1f16ddfc907a73b33bc9eeee3820a99e1e5071c2ba8ea0ba66126c6b4a89f"
    format: png
    id: lpg_level
    resize: 80x80
    update_interval: 60s
    on_download_finished:
      component.update: tft_display

If I Ctl-Click on the URL in the .yaml, a web page with the image opens. Success…?
NO!
If I send (OTA) that code to the ESP32 driving the ili9xxx, the access token for the image changes???
Why is programming the display changing the access_token for the camera?

But anyway. Is this the best way to read an image into a display?
Regards, Martin

Try using a template for the url.

Thanks Nick,
How can I test my newly created template sensor?
Would expect this to display (in Device Info)? Or do I need to do more?
Regards, M.

This depends on how you defined the template text sensor for your URL. Specifically, is it internal? If yes and you want the URL to show in Device Info, then change it by adding name: to the text sensor.

You should be able to update the URL of the online_image component using online_image.set_url. Possibly something like:

text_sensor:
  - platform: template
    id: camera_url
    # name: Camera URL # uncomment if you want this in Device Info
    lambda: |-
      str url = <TEMPLATE_FOR_URL>;
      return url;
    update_interval: 60s
    on_value:
      - online_image.set_url:
          id: lpg_level
          url: !lambda 'return x;'
      - component.update: lpg_level

What is your code now?

Nick/John, thanks for the help.
Not making much progress on my own, so I have just copied John’s template.
One of my gaps in understanding is, how each of my devices (Home Assistant, ESPHome Camera, ESPHome Display) relate to each other.
In one of the earlier bits of advice, it was suggested that I should “have a template”. But where?
As you can see in the following yaml, I have included it in the ESPHome Display. I have also tried creating one via confiuration.yaml and in the Home Assistant UI.
The problem I see with this is that the(ever changing) access_token is in the Home Assistant.
Anyway this is my current state of play:

esphome:
  name: esp32s2-msp2807
  friendly_name: "ESP32 S2 msp2807"

esp32:
  board: lolin_s2_mini
  framework:
    type: arduino

#Non-relevent(?) code removed for brevity

display:
  - platform: ili9xxx
    model: ili9341
    id: tft_display

    cs_pin:    GPIO12 #TFT_CS (Pin 3)    
    reset_pin: GPIO37 #TFT_RST (Pin 4)
    dc_pin:    GPIO39 #TFT_D/C (Pin 5)

    rotation: 0
    lambda: |-
      //Now try and display it...
      it.image(40,220, id(lpg_level));

http_request:
  verify_ssl: false

text_sensor:
  - platform: template
    id: camera_url
    # name: Camera URL # uncomment if you want this in Device Info
    lambda: |-
      str url = "http://192.168.0.204:8123"; //This is address of my Home Assistant
      return url;
    update_interval: 60s
    on_value:
      - online_image.set_url:
          id: lpg_level
          url: !lambda 'return x;'
      - component.update: lpg_level
      
online_image:
  #I guess that the text_sensor (above) is creating the line similar to this...
  #... but with up-to-date access_token.
  #http://192.168.0.204:8123/api/camera_proxy/camera.esp32_lpg_cam_esp_eye?token=ab0f225a6b4b7d4e0c27321a8d62bc939e93196a4c805cc8dd5bc5603ebf3995
  #- url: "But what goes here?"
  #- url: id(camera_url).state #### ?
  
  #Testing that I can load/display required image
  #Camera has been set to generate a test image (test_patern: true)
  #This image is snapshot from my camera. Developer Tools | Acton | Camera: Take Snapshot
  - url: http://192.168.0.204:8123/local/image.png
  
    format: png
    id: lpg_level
    resize: 80x80
    type: RGB565
    update_interval: 10s #Can't wait to see results!
    on_download_finished:
      component.update: tft_display

Regards, M.

Try this:

substitutions:
  camera_entity_id: camera.esp32_lpg_cam_esp_eye
  ha_address: http://192.168.0.204:8123

text_sensor:
  # this will pull a partial URL with updated access token from HA
  - platform: homeassistant
    id: access_url
    entity_id: ${camera_entity_id}
    attribute: entity_picture
    on_value:
      - component.update: camera_url

  # this will only be updated when a new access_url is pulled from HA
  - platform: template
    id: camera_url
    lambda: |-
      std::string url = "${ha_address}" + id(access_url).state;
      return url;
    update_interval: never
    on_value:
      - lambda: 'id(lpg_level).set_url(x);'
      # In order to return the value x, it must be cast as a const char.
      # But doing so causes an issue when using the set_url() function
      # because it is validated as a std::string variable which it is not.
      # Thus, an error is thrown during runtime even though it compiles
      # - online_image.set_url:
          # id: lpg_level
          # url: !lambda 'return x.c_str();'
      - component.update: lpg_level

online_image:
    # the URL below doesn't really matter except on the initial update
    # which happens prior to being updated to the value of camera_url
  - url: "https://example.com/example.png"
    format: png
    id: lpg_level
    resize: 80x80
    type: RGB565
    update_interval: 10s
    on_download_finished:
      component.update: tft_display

Thank you John,
While I do not understand how the url: parameter in online_image: is populated, I though I’d compile your suggestion and hope to see in the log the contents of access_url and camera_url.
Unfortunately, it does not compile. These are the error messages it throws:

/config/esphome/esp32s2-msp2807.yaml: In lambda function:
/config/esphome/esp32s2-msp2807.yaml:163:14: error: cannot convert 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'const char*' in return
           url: !lambda 'return x;'
              ^
/config/esphome/esp32s2-msp2807.yaml: In lambda function:
/config/esphome/esp32s2-msp2807.yaml:157:7: error: 'str' was not declared in this scope
       str url = "http://192.168.0.204:8123" + id(access_url).state;
       ^~~
/config/esphome/esp32s2-msp2807.yaml:157:7: note: suggested alternative: 'std'
       str url = "http://192.168.0.204:8123" + id(access_url).state;
       ^~~
       std
/config/esphome/esp32s2-msp2807.yaml:158:14: error: 'url' was not declared in this scope
       return url;
              ^~~
/config/esphome/esp32s2-msp2807.yaml:158:14: note: suggested alternative: 'erfl'
       return url;
              ^~~
              erfl
*** [.pioenvs/esp32s2-msp2807/src/main.cpp.o] Error 1

sigh. That’s because my bring was in Python programming mode; sorry about that! I fixed the previous post (2 things).

Thank you John,
That code compiles and runs. Now, while I feel I’m getting closer, things are not quite right. Before I show the logs, can I ask how the online_image: component is updated? This is my yaml:

online_image:
   - url: http://8.8.8.8 # Will any dummy work here?
      format: png
      id: lpg_level
      resize: 80x80
      type: RGB565
      update_interval: 10s #Can't wait to see results!
      on_download_finished:
        component.update: tft_display

This is a chunk from my log output. I am wondering if the access_url should be looking for the “entity_picture” rather than a “state”?

[08:36:44][D][http_request.arduino:124]: Content-Length: 5454
[08:36:46][D][text_sensor:064]: 'camera_url': Sending state 'http://192.168.0.204:8123idle'
[08:36:47][D][http_request.arduino:124]: Content-Length: 5454
[08:36:54][D][http_request.arduino:124]: Content-Length: 5454
[08:36:56][D][text_sensor:064]: 'camera_url': Sending state 'http://192.168.0.204:8123idle'
[08:36:57][D][http_request.arduino:124]: Content-Length: 5454
[08:37:04][D][http_request.arduino:124]: Content-Length: 5454
[08:37:06][D][text_sensor:064]: 'camera_url': Sending state 'http://192.168.0.204:8123idle'
[08:37:07][D][http_request.arduino:124]: Content-Length: 5454
[08:37:14][D][http_request.arduino:124]: Content-Length: 5454
[08:37:16][D][text_sensor:064]: 'camera_url': Sending state 'http://192.168.0.204:8123idle'

… and while the above is running, this is the UI.

This looked like the address of your hass machine
http://192.168.0.204:8123 plus the state of the camera entity idle

As I understand it, I am (programmatically) looking for a string that looks like this:

http://192.168.0.204:8123/api/camera_proxy/camera.esp32_lpg_cam_esp_eye?token=ab0f225a6b4b7d4e0c27321a8d62bc939e93196a4c805cc8dd5bc5603ebf3995)

… from homeassistant. And again to programmatically update the url: parameter in the online_image: component. So…

  1. Should I be asking more of the text_sensor: access_url:
text_sensor:
  # this sensor will pull a url with an updated access token
  - platform: homeassistant
    id: access_url
    entity_id: camera.esp32_lpg_cam_esp_eye

Because, the above only returns “http://192.168.0.204:8123idle” and not the contents of the entity_picture:. How do I change the entity_id: (above) to request the attribute entity_picture, rather than asking for just the state?

  1. Hopefully, having found the string I need (from the entity_picture), it will be updated in the text_sensor: camera_url by:
text_sensor:
    #-platform: homeassistant & dependants removed for brevity
    - platform: template
    id: camera_url
    # name: Camera URL # uncomment if you want this in Device Info
    lambda: |-
      std::string url = "http://192.168.0.204:8123" + id(access_url).state;
      return url;
    update_interval: 10s
    on_value:
      then:
      - lambda: "id(lpg_level).set_url(x);"
      - component.update: lpg_level

Thus, if the above (programmatically) updates the online_image: url:, is there any need to have the correct or even any string in that line? Which is why I added the dummy “- url: http://8.8.8.8” earlier.

Add attribute: entity_picture to the template sensor homeassistant sensor

At the risk of irritating you both even more! Can I ask you how!
Not been able to find any documentation, but several hours hunting these fora only shows me “dot naming”. But…

Your help is appreciated - I realty hate giving up.

Sorry about that. It’s the homeassistant sensor where you add attribute: entity_picture

Wow! Where did that come from? Should I have a HomeAssistent sensor?
As noted waaaaay back, “I can not see the wood for the trees”.
And I’m sorry if I have misunderstood the advice but this is all I have so far.

  1. An ESP-CAM.
  2. Home Assistant, in which the ESP-CAM is registered as a device.
  3. Then I have a ESP32-S2 on which I am hoping to display a snapshot from the camera every 60 second.
    All this fancy coding that you have been helping me with is in the ESPHome ESP32S2 display module.
    To-date, I have not coded anything on the Home Assistant. I guess, I should have?

I never thought to use an ESP-CAM in this way; very cool idea!

Were you able to make the code for this work?

Thanks for the enquiry John,

Long story short: Not yet. But still working on it!
Current state of play is:
I think I have the Image transport from the 1.ESP-EYE to 2.HASS to 3.ESPHome Display sorted.
The problem now is that the Display only works with PNG and the ESP-EYE only generates JPG files. The ESP-EYE & the ESPHome are not up to doing any conversion, so that is being attempted on the HASS.
I have got ImageMagick on the HASS via:

[core-ssh www] apk add --update imagemagick

Unfortunately,

[core-ssh www] magick myImage.jpg myImage.png
magick: no decode delegate for this image format 'JPEG'

… does not perform the same way on HASS as it does on my Linux Workstation?
I guess that there is some dependency required that installing this way is not meeting?

Regards, M.

I think you want

convert myImage.jpg myImage.png

Thanks,
But nop! Tried that…

[core-ssh www]$ convert myImage.jpg myImage.png
convert: no decode delegate for this image format `JPEG' @ error/constitute.c/ReadImage/746.
convert: no images defined `myImage.png' @ error/convert.c/ConvertImageCommand/3362.
[core-ssh www]$

Regards, M.