我现在在建设一个All in One一体机,HomeNAS里面并没有安装桌面系统,但可以运行kodi-gbm来直接使用hdmi视频输出,这样就可以将电视盒子的功能移植到NAS上了。 我有一个接收器的遥控器,这个遥控器在操作系统启动后默认是/dev/input/event1
,我想实现的功能是,我可以按遥控器的电源键来启动kodi-gbm.service
,而这个电源键并不会触发操作系统关机。
设计操作逻辑 第一步是处理遥控器的电源键命令。在不做任何处理的情况下,电源键的处理逻辑都是关机 ,所以,我们要设计一个程序来占用遥控器这个设备,让电源键这个按键信号直接让程序 处理而不传给操作系统。当遇到电源键信号的时候,唤醒kodi-gbm.service并停止这个程序,因为接下来遥控器的信号要转交给kodi。
那么,kodi在关闭的时候,要想办法重新唤醒这个遥控器监听程序,以实现可重复操作的逻辑。
设计监听程序 那么现成的这种监听功能就是evtest
。所以,我们可以写一个systemd unit来作为kodi没有启动时的遥控器监听程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 [Unit] Description =Listen for KEY_POWER events on /dev/input/event1After =multi-user.target[Service] Type =simpleExecStart =/bin/bash -c "/usr/bin/evtest --grab /dev/input/event1 | grep --line-buffered 'KEY_POWER.*value 1' | /usr/bin/systemd-cat -t key_power_event" StandardOutput =journalStandardError =journal[Install] WantedBy =multi-user.target
这一个systemd unit会直接占用遥控器设备,处理遥控器按键信号,并将电源键信号KEY_POWER
输出到journal日志。
接下来设计一个service来监听日志,当日志中出现了关键字就启动kodi-gbm.service
。
1 2 3 4 5 6 7 8 9 10 11 12 13 [Unit] Description =Listen to key_power_event logs and restart kodi-gbm.serviceAfter =multi-user.target[Service] Type =simpleExecStart =/bin/bash -c 'journalctl -n0 -f -t key_power_event | while read -r line; do systemctl restart kodi-gbm.service; systemctl stop input-listener.service; done;' StandardOutput =journalStandardError =journal[Install] WantedBy =multi-user.target
修改kodi-gbm kodi-gbm.service
也需要修改,要让它在退出(exit/failure)的时候重启启动我们的电源键监听程序。可以利用OnFailure这个字段,但是这个字段并不能直接填input-listener.service
,是的,这就是systemd的逻辑限制,所以,我另外写一个input-listener.service
启动器服务
1 2 3 4 5 6 7 8 9 10 11 [Unit] Description =Restart the input listener serviceAfter =input-listener.service[Service] Type =on eshotExecStart =/bin/systemctl start input-listener.service [Install] WantedBy =multi-user.target
然后修改kodi-gbm.service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [Unit] Description =Kodi standalone (GBM)After =remote-fs.target systemd-user-sessions.service network-on line.target nss-lookup.target sound.target bluetooth.target polkit.service upower.service mysqld.service lircd.serviceWants =network-on line.target polkit.service upower.serviceConflicts =getty@tty1.serviceOnFailure =input-listener-restart.service [Service] User =kodiGroup =kodiEnvironmentFile =-/etc/conf.d/kodi-standaloneSupplementaryGroups =inputPAMName =loginTTYPath =/dev/tty1ExecStart =/usr/bin/kodi-standalone --audio-backend=alsaExecStop =/usr/bin/killall --exact --wait kodi.binRestart =on -abortStandardInput =ttyStandardOutput =journal[Install] Alias =display-manager.service
生效方法 命令:systemctl enalbe kodi-keypower-trigger.service --now
systemctl enable input-listener.service --now
这样就行,开机后按遥控器电源键会启动kodi-gbm
,然后input-listener.service
会被自动stop。看完影视后,在kodi里面也是可以通过电源键关闭kodi应用程序的。在关闭的时候会触发input-listener-restart.service
这个服务,这个服务是一次性的,它会启动input-listener
服务。这样就回到了开机时的状态了,可以再使用电源键打开kodi。完美闭环。(虽然是一个非常潦草没那么优雅的启动逻辑。但是够用了,给家人简单培训下也能很容易懂。)