一、利用remote-ssh extension打造遠端開發環境
先前有介紹使用VS Code遠端開發Django,當時使用的方法有點土法練鋼,現在微軟提供非常簡易的remote-ssh擴充套件,可以讓VS Code很方便的與遠端樹莓派整合在一起,利用前端電腦的強大處理能力去協同開發後端樹莓派的Python應用。
在介紹紅外線的接收與發射前,讓我們先來打造一個Python遠端開發的樹莓派環境。
二、打開支援核心
現今的Linux核心已可直接支援紅外線遙控器的收發,只要將它打開即可,非常方便使用。
三、萬碼奔騰,自製編碼對應表
紅外線使用的編碼表按鍵名稱列表:https://peppe8o.com/download/txt/ir-keytable%20available%20keycodes.txt
由於遙控器的廠牌太多種類,甚至是同廠牌也有不同型號的遙控器,其編碼也不一定會完全一致,因此,學習自製編碼對應表,是常遇到的課題。
四、控制VLC播放音樂及LED閃爍
有了前面的基礎後,就可以利用python-evdev模組,來讀取遙控器資料並判斷是哪個按鈕被按下,進行相對應的程式處理。同時,由於VLC於背景播放,可使用psutil模組,來處理結束播放事宜。這二個模組功能是相當強大的,值得好好研究與學習。官網說明文件如下:
Copy # ir_read_nomessage.py
from evdev import InputDevice , list_devices , categorize , ecodes
def get_ir_device ():
devices = [ InputDevice (path) for path in list_devices () ]
for device in devices :
print (device.path, device.name, device.phys)
if 'ir_recv' in device . name :
return device
else :
device . close ()
dev = get_ir_device ()
try :
for event in dev . read_loop ():
if event . type == ecodes . EV_KEY :
if event . value == 1 :
if ecodes . KEY[event . code] == 'KEY_1' :
print ( 'press 1' )
elif ecodes . KEY[event . code] == 'KEY_2' :
print ( 'press 2' )
elif ecodes . KEY[event . code] == 'KEY_3' :
print ( 'press 3' )
dev . close ()
quit ()
except KeyboardInterrupt :
print ( 'press ctrl-c' )
dev . close ()
quit ()
Copy # vlc_id.py
import psutil
# 方法一:先取得所有的process id (PID),再找出vlc的PID,找到就kill離開
# process_ids = psutil.pids()
# for pid in process_ids:
# p = psutil.Process(pid)
# if 'vlc' in p.name():
# print(p.name())
# print(p.pid)
# p.kill()
# break
# 方法二:透過iter的方式,一個個找,找到就kill離開
for proc in psutil . process_iter ([ 'pid' , 'name' ]):
if 'vlc' in proc . info [ 'name' ]:
print (proc.info[ 'pid' ])
p = psutil . Process (proc.info[ 'pid' ])
p . kill ()
break
Copy from evdev import InputDevice , list_devices , categorize , ecodes
from gpiozero import LED
import subprocess
import psutil
led = LED ( 27 )
led_on = False
vlc_on = False
def get_ir_device ():
devices = [ InputDevice (path) for path in list_devices () ]
for device in devices :
print (device.path, device.name, device.phys)
if 'ir_recv' in device . name :
return device
else :
device . close ()
def stop_vlc ():
for proc in psutil . process_iter ([ 'pid' , 'name' ]):
if 'vlc' in proc . info [ 'name' ]:
print (proc.info[ 'pid' ])
p = psutil . Process (proc.info[ 'pid' ])
p . kill ()
return
dev = get_ir_device ()
try :
for event in dev . read_loop ():
if event . type == ecodes . EV_KEY and event . value == 1 :
if ecodes . KEY[event . code] == 'KEY_1' :
# 控制VLC播放音樂
if vlc_on :
# 利用PID停止播放
print ( '停止播放音樂' )
stop_vlc ()
else :
print ( '開始播放音樂' )
subprocess . run ([ "cvlc" , "-LZ" , "/home/pi/Music" ])
vlc_on = not vlc_on
elif ecodes . KEY[event . code] == 'KEY_2' :
# 控制LED亮與暗
if led_on :
led . off ()
else :
led . blink ()
led_on = not led_on
elif ecodes . KEY[event . code] == 'KEY_3' :
print ( '離開程式' )
dev . close ()
quit ()
except KeyboardInterrupt :
print ( '按鍵Ctrl+c中斷程式' )
dev . close ()
quit ()
五、發射紅外線訊號
先利用evtest來檢視鍵盤訊號值,再利用ir_ctl測試,依據scancode發射紅外線訊號給接收器,最後撰寫程式來完成工作。
Copy from evdev import InputDevice , list_devices , categorize , ecodes
from configparser import ConfigParser
from collections import defaultdict
from time import sleep
import os
config = ConfigParser ()
config . read (os.path. expanduser ( '~/lien.toml' ))
# 列出所有的設定section
# print(keymap.sections())
scancodes = config [ 'protocols.scancodes' ]
keymaps = defaultdict ()
# 原先格式是
# [protocols.scancodes]
# 0x41ba09 = "KEY_1"
# 轉成 "KEY_1" = 0x41ba09
# 並且將 " 字符除去(利用replace),如此才可以使用keymaps['KEY_1']
# 如果不去除,就必須要用keymaps['"KEY_1"'],此用法容易混淆
for s in scancodes :
keymaps [ scancodes [ s ]. replace ( '"' , '' )] = s
dev = InputDevice ( '/dev/input/event0' )
try :
for event in dev . read_loop ():
if event . type == ecodes . EV_KEY and event . value == 1 :
if event . code == ecodes . KEY_A :
print ( '按鍵 A' )
command = f "ir-ctl -S necx: { keymaps [ 'KEY_1' ] } -d /dev/lirc0"
os . system (command)
elif event . code == ecodes . KEY_B :
print ( '按鍵 B' )
command = f "ir-ctl -S necx: { keymaps [ 'KEY_2' ] } -d /dev/lirc0"
os . system (command)
elif event . code == ecodes . KEY_C :
print ( '結束程式' )
dev . close ()
break
except KeyboardInterrupt :
dev . close ()
quit ()