一、目标:
开机自启oled显示服务ip与端口,并播放logo
二、过程:
1、出现luma
库不存在问题,修改.service
文件,增加用户与用户组。在本地测试过程中可以使用python script.py
执行python脚本,所以将.service
文件中的用户与用户组也设置为命令行相同的用户与用户组:
重启设备发现没有自启,systemctl status bootShowIP.service
或journalctl -u bootShowIP.service
获取失败日志,得知luma
库不存在ModulNotFoundError: No module named 'luma'
:
通过pip show luma
可以得知luma
已经安装:
且,在命令行可以通过./run.sh
的方式执行python脚本,所以自启执行失败应该与用户和用户组有关:
修改.service
文件中用户与用户组
2、在python脚本当中使用socket
库获取ip地址失败,通过journalctl -u bootShowIP.service
可以查看得知问题,并修改为使用subprocess
库来获取网卡ip地址:
查看日志,发现socket
获取网卡ip失败:
使用subprocess
获取网卡ip:
三、实现效果:
四、所有源代码:
1、文件夹目录结构
2、font文件夹是字体文件夹:
3、logo文件夹是屏幕播放logo图片文件夹,其中空白区域用于叠加ip与端口:
以上图片获取方式:
1、画一张图;
2、编辑图片,曝光最大,另存为002.jpg;
3、重复步骤2,另存为003.jpg;
4、重复以上步骤直到图片全白;
5、结束。
效果:
4、.service文件,需要拷贝到/usr/lib/systemd/system/目录下
[Unit]
Description=My Python Script
After=network.target
[Service]
ExecStart=/home/pi/Desktop/oled/final-show-logo/run.sh -fg
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
KillMode=process
User=pi
Group=pi
[Install]
WantedBy=multi-user.target
5、run.sh脚本用于启动,不再修改.service文件
#!/bin/sh
#sleep 10
#export PYTHONPATH="$PYTHONPATH:/home/pi/.local/lib/python3.7/site-packages"
python /home/pi/Desktop/oled/final-show-logo/oled_showpic.py
6、python脚本
import os
import glob
import time
# import socket
import subprocess
import fcntl
import struct
from PIL import Image, ImageDraw, ImageFont
import luma.oled as oled
from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306
WIDTH=128
HEIGHT=64
LOCAL_PATH = "/home/pi/Desktop/oled/final-show-logo" #修改为脚本放置的目录
'''
#使用socket获取ip地址失败
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15].encode('utf-8')) # 将字符串编码为字节对象
)[20:24])
return "10.11.96.77"
'''
def get_ip_address(interface='eth0'):
result = subprocess.run(['ip', '-f', 'inet', '-o', 'addr', 'show', interface], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = result.stdout.decode()
if 'inet ' in output:
ip_info = output.split('inet ')[1].split('/')[0]
return ip_info
else:
return "x192.168.137.18" #默认返回的ip地址
def search_dir_pic(dir_name, suffix):
# 设置文件夹路径
# folder_path = os.path.join(os.getcwd(), dir_name)
folder_path = os.path.join(LOCAL_PATH, dir_name)
print("图片路径")
print(folder_path)
# 使用glob模块匹配以数字命名的文件
number_files = glob.glob(os.path.join(folder_path, '[0-9]*.'+suffix))
print('图片文件名')
print(number_files)
return sorted(number_files)
def load_device():
# 创建I2C接口对象
serial = i2c(port=1, address=0x3C) # 地址可能因显示屏型号而异
# 创建OLED设备对象
device = ssd1306(serial, WIDTH, HEIGHT)
return device
def draw_on_pic(image):
# 创建一个可以在给定图像上绘制的对象
draw = ImageDraw.Draw(image)
# font = './font/ARIALI.TTF'
font = LOCAL_PATH + '/font/ARIALI.TTF'
font_size = int(min(WIDTH, HEIGHT)/5)
font = ImageFont.truetype(font, font_size)
# 使用函数获取eth0的IP地址
ip_address = get_ip_address('eth0')
port = 80
print("local eth0 addr "+ip_address)
text = 'IP address:\n'+ip_address+'\nPort:\n'+str(port)
# 定义文本内容和位置
x_position = 0 # x坐标
y_position = 0 # y坐标
# 在图片上写字,设置文本颜色为黑色
draw.text((x_position, y_position), text, fill=0, font=font)
# image.save('your_image_with_text.jpg')
return image
# 定义一个函数来将灰度图像转换为二值图像
def convert_to_binary(image, threshold=128):
return image.point(lambda x: 0 if x < threshold else 255, '1')
def load_pic(pic_name):
# 加载图片并调整大小
print('ready show pic '+pic_name)
image = Image.open(pic_name)
image = image.resize((WIDTH, HEIGHT)).convert('L')
image = convert_to_binary(image) # 转换为二值图像(黑白)
image = draw_on_pic(image)
return image
def show(image):
# 将图片数据发送到OLED
device.display(image)
time.sleep(1/5)
if __name__=='__main__':
global device
device = load_device()
pic_group = search_dir_pic('logo', 'jpg')
while True:
for pic_file in pic_group:
image = load_pic(pic_file)
show(image)
7、辅助脚本,获取用户和用户组
whoami
echo $USER
echo $LOGNAME
8、在其他设备上部署需要修改
1:修改.service
文件中的run.sh
路径的位置;
2:修改python脚本中的当前路径LOCAL_PATH
位置。