树莓派4B-使用systemctl设置开机自启oled播放服务ip地址与logo

一、目标:

开机自启oled显示服务ip与端口,并播放logo

二、过程:

1、由于执行脚本run.sh是在windows当中编写的,所以在linux上运行的时候会由于行尾的^M而无法执行。可以通过命令sed -i 's/\r$//' your_script.sh,或者使用工具dos2unix解决问题。

2、出现luma库不存在问题,修改.service文件,增加用户与用户组。在本地测试过程中可以使用python script.py执行python脚本,所以将.service文件中的用户与用户组也设置为命令行相同的用户与用户组:

重启设备发现没有自启,systemctl status bootShowIP.servicejournalctl -u bootShowIP.service获取失败日志,得知luma库不存在ModulNotFoundError: No module named 'luma'

在这里插入图片描述

通过pip show luma可以得知luma已经安装:

在这里插入图片描述

且,在命令行可以通过./run.sh的方式执行python脚本,所以自启执行失败应该与用户和用户组有关:

在这里插入图片描述

修改.service文件中用户与用户组

在这里插入图片描述

3、在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位置。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值