继续树莓派4B+OLED:开机自动显示IP地址

继续树莓派4B+OLED:开机自动显示IP地址,第1张

因为有了之前(树莓派:Adafruit的I2C SSD1306 OLED驱动)那篇的基础,想干脆让它开机自动显示IP地址。

首先当然找获取IP的代码。记得前几年抄过一段,所以又找了出来:

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,
        struct.pack('256s', ifname[:15]))[20:24])

当时调用很简单,因为我是用无线的,所以历史代码调用用了这一句:
ip = get_ip_address('wlan0')

然而今天再拿出来试居然报错了。解决起来倒是非常简单,加个“b”类型前缀即可:

ip = get_ip_address(b'wlan0')

结合示例中的代码,另存了一份代码,命名为s.py,完整代码如下:

import time

import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

#import subprocess
import socket
import fcntl
import struct
#import commands

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,
        struct.pack('256s', ifname[:15]))[20:24])

ip = get_ip_address(b'wlan0')


RST = None     # on the PiOLED this pin isnt used
DC = 23
SPI_PORT = 0
SPI_DEVICE = 0

disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)


disp.begin()
disp.clear()
disp.display()

width = disp.width
height = disp.height
image = Image.new('1', (width, height))

draw = ImageDraw.Draw(image)

draw.rectangle((0,0,width,height), outline=0, fill=0)

padding = -2
top = padding
bottom = height-padding
x = 0


font = ImageFont.truetype('/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf', 14)

draw.rectangle((0,0,width,height), outline=0, fill=0)

#cmd = "hostname -I"
#IP = subprocess.check_output(cmd, shell = True )

draw.text((x, top), ip,  font=font, fill=255)
disp.image(image)
disp.display()

然后就是设置开机自动执行了。意外的,并没有想象中顺利,无论是使用/etc/rc.local还是crontab -e。没有深究,感觉是要么python相关的库调取不到,要么bash环境有问题。

最终使用systemd解决。

在/usr/lib/systemd/system下新建一个后缀为.service的文件(我用了showip-oled.service),内容如下:

[Unit]
Description=Show IP on OLED
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 -u /home/pi/Adafruit_Python_SSD1306/examples/s.py
Restart=on-failure
RestartSec=6
User=pi

[Install]
WantedBy=multi-user.target

具体含义可以参考:Systemd的使用指南 - 简书 (jianshu.com)https://www.jianshu.com/p/7fd8b6ea336e

 因为获取IP并展示在OLED屏幕上只需要在开机时执行,因此Type用了oneshot。一开始没有加Restart和RestartSec,结果测试时发现脚本运行到获取ip相关的地方会报错,因此最终还是加上了这两项。

Service文件保存(含新建、修改等)后可以执行sudo systemctl daemon-reload让系统重刷一下。然后尝试 sudo systemctl start showip-oled.service 看看是否能正常运行,并用sudo systemctl status showip-oled.service 确认。最后运行下 sudo systemctl enable showip-oled.service 使能自动运行。

最后就可以正式测试了。由于我发现树莓派关机后只要不撤电源线,OLED仍可继续显示,因此建议关机后先把电源也断开,确保OLED无任何显示,之后再给树莓派通电。正常情况下应该能显示IP地址了。如果还是不行,可以再用 sudo systemctl status showip-oled.service 看看还有啥错。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/726294.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存