helgeerbe / picframe

Picture frame viewer for raspi, controlled via mqtt and automatticly integrated as mqtt device in homeassistant.
MIT License
98 stars 28 forks source link

display_is_on and paused throw exception #319

Closed dexn closed 1 year ago

dexn commented 1 year ago

When I click pause or display_is_on I get an exception in the log. It does pause for both but display_is_on won't turn the display off.

Checking required packages...... PIL : 9.5.0 pi3d : 2.49 yaml : 6.0 paho.mqtt : 1.6.1 iptcinfo3 : 2.1.4 numpy : 1.16.2 ninepatch : installed, but no version info pi_heif : 0.11.0 defusedxml : 0.7.1

viewer:
  blur_amount: 12                         # default=12,  larger values than 12 will increase processing load quite a bit
  blur_zoom: 1.0                          # default=1.0, must be >= 1.0 which expands the backgorund to just fill the space around the image
  blur_edges: False                       # default=False, use blurred version of image to fill edges - will override FIT = False
  edge_alpha: 0.5                         # default=0.5, background colour at edge. 1.0 would show reflection of image
  fps: 20.0                               # default=20.0
  background: [0.2, 0.2, 0.3, 1.0]        # default=[0.2, 0.2, 0.3, 1.0], RGBA to fill edges when fitting
  blend_type: "blend"                     # default="blend", choices={"blend", "burn", "bump"}, type of blend the shader can do
  font_file: "/home/pi/picframe_data/data/fonts/NotoSans-Regular.ttf"
  shader: "/home/pi/picframe_data/data/shaders/blend_new"
  show_text_fm: "%b %d, %Y"               # default "%b %d, %Y", format to show date over the image
  show_text_tm: 20.0                      # default=20.0, time to show text over image with file name
  show_text_sz: 40                        # default=40, text character size
  show_text: ""  # default="title caption name date folder location", show text, include combination of words: title, caption name, date, location, folder
  text_justify: "L"                       # text justification L, C or R
  text_bkg_hgt: 0.25                      # default=0.25 (0.0-1.0), percentage of screen height for text background texture
  text_opacity: 1.0                       # default=1.0 (0.0-1.0), alpha value of text overlay
  fit: False                              # default=False, True => scale image so all visible and leave 'gaps'
                                          #                False => crop image so no 'gaps'
  kenburns: False                         # default=False, will set fit->False and blur_edges->False
  display_x: 0                            # offset from left of screen (can be negative)
  display_y: 0                            # offset from top of screen (can be negative)
  display_w: null                         # width of display surface (null->None will use max returned by hardware)
  display_h: null                         # height of display surface
  display_power: 0                        # default=0. choices={0, 1}, 0 will use legacy `vcgencmd` and 1 will use `xset` to blank the display
  use_glx: False                          # default=False. Set to True on linux with xserver running

  mat_images: 0.10                        # default=0.01, True, automatically mat all images. False, don't automatically mat any images. Real value, auto-mat all images with aspect ratio difference > than value
  mat_type: double_bevel                          # default=null, A string containing the mat types to choose from when matting images. It can consist of any or
                                          # all of 'float float_polaroid float_color_wrap single_bevel double_bevel double_flat' (null or '' will use all mat types)
  outer_mat_color: null                   # default=null, Color of the outer mat as an RGB list. null will auto-select a reasonable color based on the image.
  inner_mat_color: null                   # default=null, Color of the inner mat as an RGB list. null will auto-select a reasonable color based on the image.
  outer_mat_border: 0                    # default=75, Minimum outer mat border in pixels
  inner_mat_border: 20                    # default=40, Minimum inner mat border in pixels (for styles that use it)
  outer_mat_use_texture: True             # default=True, True uses a texture for the outer mat. False creates a solid-color outer mat.
  inner_mat_use_texture: False            # default=False, True uses a texture for the inner mat. False creates a solid-color inner mat.
  mat_resource_folder: "/home/pi/picframe_data/data/mat" # Folder containing mat image files

  show_clock: False                       # default=False, True shows clock overlay. False does not show clock overlay
  clock_justify: "R"                      # default="R", clock justification L, C, or R
  clock_text_sz: 120                      # default=120, clock character size
  clock_format: "%I:%M"                   # default="%I:%M", strftime format for clock string
  clock_opacity: 1.0                      # default=1.0 (0.0-1.0), alpha value of clock overlay

  menu_text_sz: 40                        # default=40, menu character size
  menu_autohide_tm: 10.0                  # default=10.0, time in seconds to show menu before auto hiding (0 disables auto hiding)
  geo_suppress_list: []                   # default=None, substrings to remove from the location text

model:
  pic_dir: "/home/pi/Pictures"                   # default="/home/pi/Pictures", root folder for images
  deleted_pictures: "/home/pi/DeletedPictures"   # move deleted pictures here
  follow_links: False                     # default=False, By default, picframe will not walk down into symbolic links that resolve to directories. Set follow_links to True to visit directories pointed to by symlinks, on systems that support them.
  no_files_img: "/home/pi/picframe_data/data/no_pictures.jpg" # default="PictureFrame2020img.jpg", image to show if none selected
  subdirectory: ""                        # default="", subdir of pic_dir - can be changed by MQTT"
  recent_n: 0                             # default=7 (days), when shuffling file change date more recent than this number of days play before the rest
  reshuffle_num: 1                        # default=1, times through before reshuffling
  time_delay: 13.0                       # default=200.0, time between consecutive slide starts - can be changed by MQTT
  fade_time: 2.0                         # default=10.0, change time during which slides overlap - can be changed by MQTT"
  shuffle: True                           # default=True, shuffle on reloading image files - can be changed by MQTT"
  sort_cols: 'fname ASC'                  # default='fname ASC' can be any columns in the table with optional ASC or DESC separated by commas
                                          # fname, last_modified, file_id, orientation, exif_datetime, f_number,
                                          # exposure_time, iso, focal_length, make, model, lens, rating,
                                          # latitude, longitude, width, height, title, caption, tags,
                                          # is_portrait, location
  image_attr: [                           # image attributes send by MQTT, Keys are taken from exifread library, "PICFRAME GPS" is special to retrieve GPS lon/lat, "PICFRAME LOCATION" is special to retrieve geo reverse (load_geoloc hast to be True)
    "PICFRAME GPS",
    "PICFRAME LOCATION",
    "EXIF FNumber",
    "EXIF ExposureTime",
    "EXIF ISOSpeedRatings",
    "EXIF FocalLength",
    "EXIF DateTimeOriginal",
    "Image Model",
    "Image Make",
    "IPTC Caption/Abstract",
    "IPTC Object Name",
    "IPTC Keywords"]
  load_geoloc: False                      # get location information from open street map NB if you switch this on (recommended)
  geo_key: "this_needs_to@be_changed"     # then you **MUST** change the geo_key to something unique to you
                                          # i.e. use your email address
  locale: "en_AU.UTF-8"                    # "locale -a" shows the installed locales which could used
  key_list: [
    ["tourism","amenity","isolated_dwelling"],
    ["suburb","village"],
    ["city","county"],
    ["region","state","province"],
    ["country"]]
  db_file: "/home/pi/picframe_data/data/pictureframe.db3" # database used by PictureFrame
  portrait_pairs: True
  log_level: "DEBUG"                    # default=WARNING, could beDEBUG, INFO, WARNING, ERROR, CRITICAL
  log_file: "/home/pi/picframe_data/log/log.txt"                            # default="" for debugging set this to the path to a file. NB logging messages will
                                          # appended indefinitely so don't forget this. You will need to tidy it up later

mqtt:
  use_mqtt: False                         # default=False. Set True true, to enable mqtt
  server: "your_mqtt_broker"              # No defaults for server
  port: 8883                              # default=8883 for tls, 1883 else (tls must be "" then !!!!!)
  login: "name"                           # your mqtt user
  password: "your_password"               # password for mqtt user
  tls: "/path/to/your/ca.crt"             # filename including path to your ca.crt. If not used, must be set to "" !!!!
  device_id: "picframe"                   # default="picframe" unique id of device. change if there is more than one PictureFrame
  device_url: ""                          # if use_http==True, set url to picframe config page. Must be a valid url, or "" otherwise home assistant runs in an error.

http:
  use_http: True                         # default=False. Set True to enable http NB THIS SERVER IS FOR LOCAL NETWORK AND SHOULD NOT BE EXPOSED TO EXTERNAL ACCESS
  path: "/home/pi/picframe_data/html"            # path to where html files are located
  port: 80                              # port used to serve pages by http server < 1024 requires root which is *bad* idea
  use_ssl: False
  keyfile: "path/to/key.pem"              # private-key
  certfile: "path/to/cert.pem"            # server certificate

peripherals:
  input_type: null                        # default=null, valid options: {null, "keyboard", "touch", "mouse"}
  buttons:
    pause:                                # pause/unpause the show
      enable: True                        # default=True
      label: "Pause"                      # default="Pause"
      shortcut: " "                       # default=" "
    display_off:                          # turn off the display (when off, any input from selected peripheral will turn it back on)
      enable: True                        # default=True
      label: "Display off"                # default="Display off"
      shortcut: "o"                       # default="o"
    location:                             # shows or hides location information
      enable: False                       # default=False
      label: "Location"                   # default="Location"
      shortcut: "l"                       # default="l"
    exit:                                 # exit PictureFrame
      enable: False                       # default=False
      label: "Exit"                       # default="Exit"
      shortcut: "e"                       # default="e"
    power_down:                           # power down the device, uses sudo
      enable: False                       # default=False
      label: "Power down"                 # default="Power down"
      shortcut: "p"                       # default="p"
2023-05-15 18:13:23,014 - controller.Controller - INFO - creating an instance of Controller
2023-05-15 18:13:23,576 - picframe.interface_peripherals - INFO - creating an instance of InterfacePeripherals
2023-05-15 18:13:23,577 - picframe.interface_peripherals - INFO - peripheral input is disabled
2023-05-15 18:13:23,586 - simple_server.InterfaceHttp - INFO - creating an instance of InterfaceHttp
2023-05-15 18:14:55,623 - simple_server.InterfaceHttp - INFO - {'brightness': 1.0, 'clock_is_on': False, 'date_from': -2147421600.0, 'date_to': 2145880800.0, 'display_is_on': True, 'fade_time': 2.0, 'location_filter': '', 'matting_images': 0.1, 'paused': False, 'shuffle': True, 'subdirectory': '', 'tags_filter': '', 'time_delay': 13.0}
2023-05-15 18:15:04,587 - simple_server.InterfaceHttp - INFO - {'ERROR': "Excepton:display_is_on><lambda>() missing 2 required positional arguments: 'x' and 'y';", 'display_is_on': True}
2023-05-15 18:15:17,673 - simple_server.InterfaceHttp - INFO - {'ERROR': "Excepton:display_is_on><lambda>() missing 2 required positional arguments: 'x' and 'y';", 'display_is_on': True}
2023-05-15 18:16:15,412 - simple_server.InterfaceHttp - INFO - {'ERROR': "Excepton:paused><lambda>() missing 2 required positional arguments: 'x' and 'y';", 'paused': False}
2023-05-15 18:16:23,407 - simple_server.InterfaceHttp - INFO - {'ERROR': "Excepton:paused><lambda>() missing 2 required positional arguments: 'x' and 'y';", 'paused': True}
2023-05-15 18:16:33,600 - simple_server.InterfaceHttp - INFO - {'ERROR': "Excepton:paused><lambda>() missing 2 required positional arguments: 'x' and 'y';", 'paused': False}

I've also noticed that it isn't detecting it as a Pi.

>>> import pi3d
>>> pi3d.constants.PLATFORM
3
helgeerbe commented 1 year ago

I cannot reproduce the exception:

What do you get if you call:

Should be a valid Json object

dexn commented 1 year ago

Yes I get {"paused": false} and {"display_is_on": true}.

If I call ?paused=true I get {"ERROR": "Excepton:paused><lambda>() missing 2 required positional arguments: 'x' and 'y';", "paused": true}, which does pause the frame and calling ?paused gives {"paused": true}

Calling ?display_is_on=false I get {"ERROR": "Excepton:display_is_on><lambda>() missing 2 required positional arguments: 'x' and 'y';", "display_is_on": true}, which pauses the frame but doesn't turn the display off. Calling ?display_is_on=false gives {"display_is_on": true} and ?paused gives {"paused": true}

I tried turning on "Display Blanking" and setting display_power: 1 to see if that helped but didn't with the exact same error. Running xset -display :0 dpms force off did turn the display off though. Running vcgencmd display_power 0 did so too.

I've turned off "Display Blanking" again and set it back to display_power: 0.

helgeerbe commented 1 year ago

The error is here

https://github.com/helgeerbe/picframe/blob/e37ff8634a88c19105d5059abdb67212a2cbbf06/src/picframe/interface_http.py#L92

Reading the the parameters from the browser and storing the values. But I don't understand why there are arguments missing.

@paddywwoof do you have a hint for me?

paddywwoof commented 1 year ago

I'll have a look. x and y don't sound relevant arguments for toggling on or off!

helgeerbe commented 1 year ago

@dexn do you have mqqt enabled?

The setter is calling publish_state(), which is defined as

self.publish_state = lambda x, y: None

We should call it only if mqtt is enabled. Will test this.

paddywwoof commented 1 year ago

I've also noticed that it isn't detecting it as a Pi.

@dexn the PLATFORM number 0 to indicate it's a Pi really means it's running the original Broadcom OpenGLES2 driver that worked without the X server running. 3 is really standard linux.

@helgeerbe Hmm I wonder if I remember a clash between mqqt and the http server before?

helgeerbe commented 1 year ago

@dexn I see in your config, that mqtt is disabled. I turned it off in my configuration and can now reproduce the error. Fix should be easy.

paddywwoof commented 1 year ago

Is this due to a recent change? I don't think I've ever set mqtt on. I'm not running the latest version of picframe on the wall in the kitchen. Time to upgrade it! Paddy

helgeerbe commented 1 year ago

I put the error in the code in May 2022 #267

paddywwoof commented 1 year ago

struggling to get to the point where I can see if I get the same error.

import typing
...
        model: type[Model]

seems to generate an error to the effect that type is not sub-scriptable - but it is python 3.7... Oh well, only 188 packages to upgrade!

paddywwoof commented 1 year ago

Hmm, I'm still on Buster on my RPi 3 with python 3.7.3 which I see is also the version on @dexn setup above (also still using picframe:2022.12.15). However I can't get past the type[Model] step in interface_peripherals.py. Is there something else I need to do now? Is there a minimum version of python required (type[Model] works ok on my desktop computer with python 3.10.6)? Is the 'standard' instruction not to use Buster but follow @thomasedoff instructions and go 'full fat' driver?

helgeerbe commented 1 year ago

I put a patch on the dev branch, which should solve throwing the exception. @dexn are you able to install it from a git repository, for testing? I'm not sure, if this fix the 'not blanking the screen' error.

helgeerbe commented 1 year ago

@paddywwoof 3.7.3 should work. As far as I know typ hints like the type[Model] were introduced with python 3.5 and alos buster should be fine.

The setup from @dexn works.

paddywwoof commented 1 year ago

Not sure what it is then. Certainly if I run the following with python 3.9 or 3.10 there's no error. But on python 3.7 I get the complaint about type[]. I notice that changes to the picframe file causing the crash for me were made after the version of picframe listed by @dexn

Paddy

import typing

class Test:
     a: int
     def __init__(self):
         self.a = 0

class TestType:
     b: type[Test]
     def __init__(self, b: Test):
         self.b = b

a_test = Test()
a_test_type = TestType(a_test)

error message

Traceback (most recent call last):
   File "test_typing.py", line 8, in <module>
     class TestType:
   File "test_typing.py", line 9, in TestType
     b: type[Test]
TypeError: 'type' object is not subscriptable

PS I noticed there was a typing_extensions module, which I tried installing, but it didn't fix the error (though I'm not really sure how it would disambiguate type[X] from type(X)

dexn commented 1 year ago

Won't load for me either.

~/picframe $ sudo xinit /usr/bin/python3 /home/pi/picframe_data/run_start.py /home/pi/picframe_data/config/configuration.yaml

X.Org X Server 1.20.4
X Protocol Version 11, Revision 0
Build Operating System: Linux 5.4.0-109-generic armv8l Raspbian
Current Operating System: Linux maraframe 5.10.103-v7l+ #1529 SMP Tue Mar 8 12:24:00 GMT 2022 armv7l
Kernel command line: coherent_pool=1M 8250.nr_uarts=0 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 video=HDMI-A-1:1920x1080M@60 smsc95xx.macaddr=DC:A6:32:4B:A8:31 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000  console=ttyS0,115200 console=tty1 root=PARTUUID=6f14799a-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
Build Date: 04 April 2023  07:50:56AM
xorg-server 2:1.20.4-1+rpt4+deb10u9 (https://www.debian.org/support)
Current version of pixman: 0.36.0
        Before reporting problems, check http://wiki.x.org
        to make sure that you have the latest version.
Markers: (--) probed, (**) from config file, (==) default setting,
        (++) from command line, (!!) notice, (II) informational,
        (WW) warning, (EE) error, (NI) not implemented, (??) unknown.
(==) Log file: "/var/log/Xorg.0.log", Time: Wed May 17 11:12:47 2023
(==) Using config directory: "/etc/X11/xorg.conf.d"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
(II) modeset(0): Initializing kms color map for depth 24, 8 bpc.
INFO:start.py:starting ['/home/pi/picframe_data/run_start.py', '/home/pi/picframe_data/config/configuration.yaml']
INFO:model.Model:Open config file: /home/pi/picframe_data/config/configuration.yaml:
INFO:controller.Controller:creating an instance of Controller
Traceback (most recent call last):
  File "/home/pi/picframe_data/run_start.py", line 2, in <module>
    start.main()
  File "/usr/local/lib/python3.7/dist-packages/picframe/start.py", line 136, in main
    c.start()
  File "/usr/local/lib/python3.7/dist-packages/picframe/controller.py", line 330, in start
    from picframe.interface_peripherals import InterfacePeripherals
  File "/usr/local/lib/python3.7/dist-packages/picframe/interface_peripherals.py", line 17, in <module>
    class InterfacePeripherals:
  File "/usr/local/lib/python3.7/dist-packages/picframe/interface_peripherals.py", line 29, in InterfacePeripherals
    model: type[Model],
TypeError: 'type' object is not subscriptable
helgeerbe commented 1 year ago

OK, I installed python 3.7 through miniconda and got the same error. Had to learn that the ability to use the [] operator on types for type hinting was added in 3.9. Wondering, why this wasn't observed before.

So I see two possibilities. We declare python 3.9 as minimum python release, or we remove the type hinting.

Btw. I played around to use sanic as new webserver, which also requires at least 3.9. sanic runs in a separate process, so one can use the other cores of the pi.

Not to mix up the issues, let us continue in #320 with the type error.

helgeerbe commented 1 year ago

I published 2023.05.17. So no more exceptions should be thrown, if you toggle pause and display_on in the web interface. Can you test it. Don't know if this solve your not going blank problem.

dexn commented 1 year ago

Fixed

paddywwoof commented 1 year ago

@helgeerbe As far as I can tell the 2023.05.17 version runs fine. Before upgrading I tried changing the type lines to model: Model which runs OK and I could then replicate the OP exceptions for paused and display_is_on.

I think type hinting is generally a good thing in python but it's essentially a documentation/readability feature (python not really respecting types) so maybe just having model: Model would be sufficient.

I did wonder about using the flask web server when I set up the http interface but thought it wasn't needed if the access was always local and just one simple page. In the end there were a few things that needed patching up in javascript so it might have been better to use a more sophisticated server in the first place. After reading @jamespreedy comment on #320 about upgrading python this might be a bit of an imposition for people.

helgeerbe commented 1 year ago

@paddywwoof you might be right. I did some tests, because I also tried to use vue, to get a more responsive web interface. But at the end, the old server seems to be fine enough.