Get the delay information of the specified route from "yahoo route information" and display it on the display with GUI. You can see the operation information on your smartphone, but when you are in a hurry to leave the house, it is difficult to check. Therefore, we created a real-time operation information display to be installed at the entrance.
python 3.7.3 Raspberry pi 3B+ BeautifulSoup4 tkinter Display bracket case for Kuman 7 inch Raspberry Pi 7 inch display (7INCH_HDMI_LCD-PK)
sudo apt-get install python3-tk
sudo apt-get install python3-pil python3-pil.imagetk
# Main subject
## Get the operation status with yahoo operation information
Use requests and beautifulsoup4 to scrape the operating status of registered routes.
I referred to this site for the algorithm.
https://qiita.com/hirohiroto522/items/6ff29be1344be805ecb0
## Get an image of the operation status
Create a program that changes the icon depending on the operation status. Download the icon image from [ICOOON MONO](https://icooon-mono.com/) or [Icon is being distributed!](Http://icon.touch-slide.jp/).
Put the downloaded image in the "img" directory. The folder structure is as follows.
train_info/img
-train.png
-warning.png
train_info/train_info_gui.py
## Operation status display on tkinter
How to operate tkinter
https://python.keicode.com/advanced/tkinter.php
I think it will be helpful.
## Source code
#### **`train_info_gui.py`**
```py
from tkinter import *
import tkinter.ttk as ttk
import os
import requests
from bs4 import BeautifulSoup
from PIL import Image, ImageTk
from datetime import datetime, timedelta
import time
import textwrap
#The acquired character string is displayed as it is under the icon image
#Create main window
root = Tk()
#Main window size
root.geometry("1024x600")
#Main window title
root.title("info")
url_dict = {
"Yamanote Line": 'https://transit.yahoo.co.jp/traininfo/detail/21/0/', "center lane": 'https://transit.yahoo.co.jp/traininfo/detail/38/0/',
"Saikyo Line": 'https://transit.yahoo.co.jp/traininfo/detail/50/0/', "Shonan Shinjuku Line": 'https://transit.yahoo.co.jp/traininfo/detail/25/0/',"Choshi Electric Railway":'https://transit.yahoo.co.jp/traininfo/detail/181/0/'
}
train_list = [
"center lane", "Yamanote Line", "Saikyo Line", "Shonan Shinjuku Line","Choshi Electric Railway"
]
#MainFrame class
class MainFrame(ttk.Frame):
#constructor
def __init__(self, master=None, **kwargs):
#Call the constructor of the parent class
super().__init__(master, **kwargs)
# create_Call widgets
self.create_widgets()
#Create widget
def create_widgets(self):
#Create a frame
self.frame = Frame(self, bg="AntiqueWhite2", bd=0, height=200, relief="flat")
#Place the frame
self.frame.grid(row=0, column=0, columnspan=8, sticky="news")
#Absolute path for this script
self.scr_path = os.path.dirname(os.path.abspath(sys.argv[0]))
#Display title
self.wt=Label(self.frame, text="Route operation information", bg="AntiqueWhite2", font=("", 80))
self.wt.place(width=800, x=100, y=10)
#Operation information icon pass (dictionary)
self.icon_dict = {
"normal": Image.open(self.scr_path + "/img/train.png "), "trouble": Image.open(self.scr_path + "/img/warning.png ")
}
#Fit the icon size to the screen size (64x64)
for key, value in self.icon_dict.items():
self.icon_dict[key] = self.icon_dict[key].resize(
(64, 64), Image.ANTIALIAS)
self.icon_dict[key] = ImageTk.PhotoImage(self.icon_dict[key])
#Route list
self.wwl = [
Label(self, text="center lane", bg="red", font=("", 30, "bold")),
Label(self, text="Yamanote Line", bg="lawn green", font=("", 30, "bold")),
Label(self, text="Saikyo Line", bg="green", font=("", 30, "bold")),
Label(self, text="Shonan Shinjuku Line", bg="orange", font=("", 30, "bold")),
Label(self, text="Choshi Electric Railway", bg="DarkOrange", font=("", 30, "bold"))
]
#Place routes
for i in range(len(self.wwl)):
self.wwl[i].grid(row=1, column=i, sticky="news")
#Initial placement dictionary of operation icons
self.wwi = [
Label(self, image=self.icon_dict["normal"], bg="white"),
Label(self, image=self.icon_dict["normal"], bg="white"),
Label(self, image=self.icon_dict["normal"], bg="white"),
Label(self, image=self.icon_dict["normal"], bg="white"),
Label(self, image=self.icon_dict["normal"], bg="white")
]
#Place the operation icon
for i in range(len(self.wwi)):
self.wwi[i].grid(row=2, column=i, sticky="news")
#Driving situation
self.wwt = [
Label(self, text="0", bg="white", font=("", 20)),
Label(self, text="0", bg="white", font=("", 20)),
Label(self, text="0", bg="white", font=("", 20)),
Label(self, text="0", bg="white", font=("", 20)),
Label(self, text="0", bg="white", font=("", 20))
]
#Place driving situation
for i in range(len(self.wwt)):
self.wwt[i].grid(row=3, column=i, sticky="news")
#Layout
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.rowconfigure(2, weight=1)
self.rowconfigure(3, weight=1)
self.rowconfigure(4, weight=1)
for i in range(len(self.wwl)):
self.columnconfigure(i, weight=1)
#Place the mainframe
app = MainFrame(root)
app.pack(side=TOP, expand=1, fill=BOTH)
#Close main window
def wm_close():
root.destroy()
#Create close button
btn = Button(root, text=" X ", font=('', 16), relief=FLAT, command=wm_close)
#When the screen is resized
def change_size(event):
#Button position to the upper right
btn.place(x=root.winfo_width() - 60, y=14)
#Bind screen resizing
root.bind('<Configure>', change_size)
#Maximize the main window
#root.attributes("-zoom", "1")
root.attributes("-fullscreen", "1")
#Always in the foreground
root.attributes("-topmost", True)
def update_train_info():
count = 0
app.wt
#Get operation information of registered routes
for item in train_list:
web_requests = requests.get(url_dict[item])
#Analyze web pages with BeautifulSoup
soup = BeautifulSoup(
web_requests.text, 'html.parser')
# .Find the dd tag of the trouble class with find
if soup.find('dd', class_='normal'):
status = "normal"
trouble_text="Normal operation"
bg="green yellow"
else:
status = "trouble"
text_list=textwrap.wrap(soup.find('dd',class_='trouble').get_text(), 10)
trouble_text='\n'.join(text_list)
bg="red4"
app.wwl[count].configure(text=item) #Display of route name
#Displayed with operation information icon
app.wwi[count].configure(image=app.icon_dict[status],bg=bg)
#Display operation information
app.wwt[count].configure(text="{0}".format(trouble_text),bg="AntiqueWhite2")
#Update display counter
count += 1
root.after(300000, update_train_info)
return
#First start
update_train_info()
#Register callback function
root.after(300000, update_train_info)
#Main loop
root.mainloop()
The train icon is displayed during normal driving, and the hazard mark is displayed and information is displayed when a failure occurs. Regarding the implementation, refer to [Python] raspberry pi table clock with weather forecast added. I was allowed to. It is updated every 5 minutes. The background color is http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm I adjusted it while applying the colors listed in.
05/10 postscript
As you pointed out, it was only executed once after 5 minutes and was not a regular execution.
By adding root.after (300000, update_train_info)
to the end ofdef update_train_info ()
to make it a recursive call, it became a regular execution. Thank you very much.
Finally, I attached the stand to show it on the 7-inch display.
https://myenigma.hatenablog.com/entry/2017/09/15/150945#%E7%94%BB%E5%83%8F%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%81%A8Widget%E3%81%AE%E3%82%B0%E3%83%AA%E3%83%83%E3%83%89%E9%85%8D%E7%BD%AE https://qiita.com/nnahito/items/ad1428a30738b3d93762#%E5%9F%BA%E7%A4%8E https://qiita.com/StrayDog/items/203640d9dc7c801dad0f
Recommended Posts