helgeerbe / picframe

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

HTTP option #404

Closed meirmark closed 1 week ago

meirmark commented 1 month ago

Hello. Can someone explains how to setup the HTTP and the commands that can be used ?

Thanks.

paddywwoof commented 1 month ago

Hi, In the configuration.yaml file you need to set the line use_http: True. If you keep all the other options as default you will be able to get a super cut-down web page on your local network with the IP of the RPi and port 9000 i.e. 192.168.0.123:9000

The web page options should be self explanatory but you can also use the http interface to send instructions if you don't want to set up an MQTT server. You can then change setting with a line or two of python code, for instance to darken the screen when no movement has been detected for a while (from my PIR code):

from urllib import request

URL = "http://localhost:9000"
...
            request.urlopen(f"{URL}?display_is_on=OFF")
            request.urlopen(f"{URL}?brightness=0.0")

The code behind the HTTP interface tries to interpret the GET parameters from the request as controller methods and arguments. See here https://github.com/helgeerbe/picframe/blob/main/src/picframe/controller.py relate the source code to the snippet of code above to get the hang of how to do this. (OFF, False, NO, 0 generally are interpreted the same, as are ON, True, yes, 1).

meirmark commented 1 month ago

Thank You for your answer. What I am trying todo is making the frame display photos on a certain date (nice for birthdays, anniversaries, etc.) For example, if the software checks every time the date is changed to a new day if there is a directory for that date and displays it. The directory name contains the date for example #1002.jpg Will be displayed on 2nd October. I do not know linux and no python, can you please show a python example to change the directory? Thanks Meir.

paddywwoof commented 1 month ago

Ah yes. I will have a think about that. The database of photos just holds the exif datetime but I think a view could allow selection by month and day of month. That would be an ideal way to do what you want, but would require quite a bit of hacking. In the mean time I will post a small python script to check the date, check if there's a directory matching, and if there is send an http request to the picframe.

I have also found there is a bit of a problem sending empty strings to set the subdirectory, location_filter and tags_filter via http, so that needs to be fixed.

paddywwoof commented 1 month ago

Here's a simple python script. It assumes you have a directory named as the date i.e. for your example /home/pi/Pictures/1002/ where you will put special pictures to show on that day.

import time
import datetime
import os
from urllib import request

CHECK_TM = 600 # every ten  minutes
ROOT_DIR = "/home/pi/Pictures" # could make a sub subdirectory at extra coomplication
URL = "http://localhost:9000"

last_day = 0 # will trigger first time round loop
while True: # or should allow some way to stop this
    date_now = datetime.datetime.now()
    if date_now.day != last_day: # only do this once per day when date rolls over
        last_day = date_now.day
        subdirectory = f"{date_now.month:02}{date_now.day:02}"
        if subdirectory in os.listdir(ROOT_DIR): # there is no verification or error catching here!!
            request.urlopen(f"{URL}?subdirectory={subdirectory}")
        else:
            request.urlopen(f"{URL}?subdirectory=") # set back to all - this only works with the mod I will add to the dev branch
    time.sleep(CHECK_TM)

In order for the subdirectory to be cleared I had to fix line 121 in /home/pi/venv_picframe/lib/python3.11/site-packages/picframe/interface_http.py

                        if value != "" or key in ("subdirectory", "location_filter", "tags_filter"):  # parse_qsl can return empty string for value when just querying

I will add the fix to the dev branch then pull it into main later so you can update picframe and it should work OK.

You also need to make this python script start automatically. You should follow the same instructions for setting up picframe to start automatically. I saved the python script in /home/pi/picframe_data/check_date.py then put this in /home/pi/.config/systemd/user/check_date.service

[Unit]
Description=Check date and send message to picframe http

[Service]
ExecStart=/bin/python3 /home/pi/picframe_data/check_date.py  ### or wherever this is  
Restart=always

[Install]
WantedBy=default.target

and you have to enable the service systemctl --user enable check_date.service etc as per the picframe wiki or Wolfgang's pages

Paddy

meirmark commented 1 month ago

I thank you very much for Your help. Instead of checking every 10 minutes if the date has changed, is it possible to create a Triger with crontab at 00:01 and check if the date matches one of directories as in turning the screen off and on at certain times?

paddywwoof commented 1 month ago

Yes, I suppose you could do that. The code would be almost the same but you wouldn't need the while True: loop. Something like this (I've not tested this, though I did the previous version). You can use systemd instead of crontab, it's generally supposed to be better, but there's a lot more help online for cron as it's been around for so long!

import datetime
import os
from urllib import request

ROOT_DIR = "/home/pi/Pictures" # could make a sub subdirectory at extra coomplication
URL = "http://localhost:9000"

date_now = datetime.datetime.now()
subdirectory = f"{date_now.month:02}{date_now.day:02}"
full_url = f"{URL}?subdirectory="
if subdirectory in os.listdir(ROOT_DIR): # there is no verification or error catching here!!
    full_url += subdirectory
request.urlopen(full_url) # set back to all only works with the mod I will add to the dev branch
meirmark commented 1 month ago

Thanks. To be sure, I summarize the actions I need to perform:

  1. Create a file with type .py and copy the script you wrote into it.
  2. Correct line 121 in the "interface_http.py" file.
  3. Create a file /home/pi/.config/systemd/user/check_date.service and paste the lines you wrote for the autostart.
  4. enable the service. Is it correct ?
paddywwoof commented 1 month ago

Sounds good. Also, to be clear, my check_date.service file is based on my setup here running on RPi3, if you are running on Pi4 or 5 you might need to do a variation (i.e. possibly sudo in various places and different location) Check back to whatever instructions you originally followed! I've pushed up the mod to the picframe repo dev branch https://github.com/helgeerbe/picframe/compare/main...dev so you should be able to:

cd ~
source /home/pi/venv_picframe/bin/activate
python -m pip install git+https://github.com/helgeerbe/picframe@dev --upgrade

If you go down the cron route using the second script then you don't need to worry about setting up the systemd stuff.

Let me know how you get on.

meirmark commented 1 month ago

Thank You. My setup is also RPi3B.

meirmark commented 1 month ago

Hi I tried the first script (which checks every 10 minutes) and when I change the date manually (sudo date -s "2024-05-03 11:00:00 the directory with the pictures - 0503) the image on the screen at that moment freezes and I have to reboot the pi. Any idea why this is happening? Does changing the manual date cause this?

meirmark commented 1 month ago

I tried the same on a pi without the script and it works normal but the clock on the display did not change to the new time I set.

paddywwoof commented 1 month ago

Hmm. Worth checking for any error logging (might be messages recorded at the bottom of journalctl among much other info. I'm not sure what changing the system date back in time would do to other file checking in picframe, but the clock should change when the text version is different from whatever is being shown. So that seems odd. Did the image change and fading work OK?Try just making the folder name 0919 and see if that works. Did you run the script from command line or with systemd?Paddy

meirmark commented 1 month ago

I ran the script through systemd. The image on the screen (Not the particular photo for the date I set) freezes (also the clock on the screen) and I have to reboot the pi. I tried changing the clock on a pi without the script and it works normal but the clock on the display did not change to the new time I set.

meirmark commented 1 month ago

I tried to create a directory 0919 but it's not working I can see all the pictures and not the picture from the directory 0919.

paddywwoof commented 1 month ago

Not sure what the problem is. I would proceed in smaller steps to make sure each part works.

  1. stop and disable the systemd service for check_date, restart the RPi so picframe runs as previously
  2. change the directory with your target files to today's date
  3. at the ssd command line navigate to the folder and python3 check_date.py

see if you get any error messages or folder selection. If you get error messages they will probably inform you what's wrong. If there are no errors but the display doesn't change to the required folder then check that the http interface is working OK:

  1. at the command line find your IP address of the RPi using ifconfig
  2. on your phone browser navigate to 192.168.0.123:9000 (whatever the IP address is with :9000 on the end)
  3. assuming you get the web page correctly, in the address bar add the required command i.e. 192.168.0.123:9000?subdirectory=0919

Hopefully you will get some info from this to point you to what's not working!

If running the script works on the command line but not when you set it up in systemd then you need to debug that. I would recommend looking through journalctl (just type that at the command line then use the END key to skip to the end of the listing) first anyway as that could well have useful error messages recorded from previous runs.

Paddy

meirmark commented 1 month ago

I added two print commands to the script to see what happens and it seems to work. The strange thing is that when I select the root directory all the images are displayed including the ones in the sub-directories. when I run the following script manually I get: 0919 directory_ok so the directory name is ok and the compare is also ok.

import time import datetime import os from urllib import request

CHECK_TM = 60 # every ten minutes ROOT_DIR = "/home/pi/Pictures" # could make a sub subdirectory at extra coomplication URL = "http://localhost:9000"

last_day = 0 # will trigger first time round loop while True: # or should allow some way to stop this date_now = datetime.datetime.now() if date_now.day != last_day: # only do this once per day when date rolls over last_day = date_now.day subdirectory = f"{date_now.month:02}{date_now.day:02}" print(subdirectory) if subdirectory in os.listdir(ROOT_DIR): # there is no verification or error catching here!! print("directory_ok") request.urlopen(f"{URL}?subdirectory={subdirectory}") else: request.urlopen(f"{URL}?subdirectory=") # set back to all - this only works with the mod I will add to the dev branch time.sleep(CHECK_TM)

paddywwoof commented 1 month ago

OK, that sounds like '.. no errors but display doesn't change..' how did you get on checking the http interface? You should really make sure everything works manually before trying to automate it. Also checking messages on journalctl, anything interesting?

meirmark commented 1 month ago

Hi, thanks for your patience, I'm trying and learning along the way.

After many attempts and apparently mistakes that I made, it seems that now it works when running from crontab. The strange thing is that when the images are displayed from the pictures directory, the images from all the sub directories are also displayed, is it supposed to be like this?

paddywwoof commented 1 month ago

That's brilliant, well done. Yes, it's a kind of feature insofar as you can structure your directories to get images to show specially but, if you want, be included in a larger collection.PaddyOn 21 Sep 2024 12:43, meirmark @.***> wrote: Hi, thanks for your patience, I'm trying and learning along the way. After many attempts and apparently mistakes that I made, it seems that now it works when running from crontab. The strange thing is that when the images are displayed from the pictures directory, the images from all the sub directories are also displayed, is it supposed to be like this?

meirmark commented 1 month ago

Hi, I'm sorry to bother you, I need some more help. Changing the partitions by date works great, the problem is that when images from the root directory are displayed, images from the subdirectories are also displayed, which is not desirable. To solve the problem I created a partition called main which will contain all the images that are displayed all days instead of the root directory. In order for the images from the main directory to be displayed, I wrote a script that sends a HTTP command to change the displayed partition and it works fine.

boot_main_dir.py

import urllib.request

URL = "http://localhost:9000"
urllib.request.urlopen(f"{URL}?subdirectory=main")

The problem is that I can't run it automatically after boot. I tried to add a line in CRONTAB that will run the script 10 seconds after boot and it doesn't work.

@reboot sleep 20 && python3 /home/pi/picframe_data/boot_main_dir.py

I tried with SYSTEMD and it didn't work either.

Please if you can help.

meirmark commented 1 month ago

I do not know why is the fonts so big.

paddywwoof commented 1 month ago

Hi, asking questions isn't something you need to apologise for. From memory, you can set the subdirectory for picframe to use at startup in the configuration.yaml file. The order of things happening and which user owns which process is one of the headaches that systemd is reputed to solve, but configuration.yaml sounds the way to go.

meirmark commented 1 month ago

Thank You very much, it works, now the frame do exactly what I wanted. 20240928_141435 20240928_144344

paddywwoof commented 1 month ago

I do not know why is the fonts so big.

Hi @meirmark the strange formatting was caused by your strings ---------- and =======. Generally speaking I only use an occasional * and the back-tick or accent_grave ` (you get two of them if you press the <> in the header. If you want something to look like python you can do three back-ticks followed by the language, then a block followed by another three back-ticks ```python print("hi there") ```

meirmark commented 1 month ago

Hi. Good to know, thank you for all Your help.