Hi all,
first of all I have to mention that I am new to rune audio (also to python and Linux) and this forum helped me a lot - thanks!
I am trying to build a music player with display and buttons, too. But instead of an LCD display, I want to use one of this nice little OLED displays. Therefore I was not able to use the code from RandyCubic (I am using a library for the SSD1306 chip I found in the web). I also was not satisfied with the power down solution, hence I designed Arduino based shut down circuit.
Somehow I managed to compile a working code (based on snippets I found: RandyCubic, hondagx35,...). But now I am stuck with a problem that I can not find a solution for: my code works fine if I start the programm manualy but when I start it via a service and a bash script it takes 2 or more iterations (Restart=on-failure) until the programm works properly.
Here is my simplified (I removed some parts of the programm that had no influence on the above mentioned problem to keep the code short for the forum - if someone is interested in the full code, just ask me) approach:
Python programm for buttons, display control remove for simplification:
#!/usr/bin/env python
#-*- coding: UTF-8 -*-
# IMPORTS
import sys, time, threading, os
import socket
import fcntl
import struct
from mpd import (MPDClient, CommandError)
from socket import error as SocketError
import RPi.GPIO as GPIO
import Queue
import psutil
from datetime import datetime
## Some functions
def mpdConnect(client, con_id):
# Simple wrapper to connect MPD.
try:
client.connect(**con_id)
except SocketError:
return False
return True
def mpdAuth(client, secret):
"""
Authenticate
"""
try:
client.password(secret)
except CommandError:
return False
return True
def find_title(s):
end = s.rfind('.')
start = s.rfind('/')
return s[start+1:end]
def convert_string(s):
s = s.replace('ü', 'ue')
s = s.replace('ö', 'oe')
s = s.replace('ä', 'ae')
s = s.replace('Ü', 'Ue')
s = s.replace('Ö', 'Oe')
s = s.replace('Ä', 'Ae')
s = s.replace('´', '\'')
s = s.replace('ß', 'ss')
return s
def my_callback(channel):
current = time.strftime("%d.%m.%Y %H:%M:%S")
#print ("{} falling edge detected on {}".format(current, channel))
time.sleep(0.01)
if not GPIO.input(channel):
queue.put(channel)
# This function allows us to grab any of our IP addresses
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])
)[20:24])
##
NextButton = 23
PrevButton = 22
PlayButton = 20
StopButton = 26
MenuButton = 24
SignOut = 12 #Client active signal for power control
HOST = 'localhost'
PORT = '6600'
PASSWORD = False
##
CON_ID = {'host':HOST, 'port':PORT}
##
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(SignOut, GPIO.OUT)
GPIO.setup(NextButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PrevButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PlayButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(StopButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(MenuButton, GPIO.IN, pull_up_down=GPIO.PUD_UP)
client = MPDClient()
queue = Queue.Queue()
def main_frontpanel():
global text_line1, text_line2, text_line3
GPIO.output(SignOut,GPIO.HIGH) #Send Boot complete signal to Arduino
print ("Start_Main")
GPIO.add_event_detect(NextButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
GPIO.add_event_detect(PrevButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
GPIO.add_event_detect(PlayButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
GPIO.add_event_detect(StopButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
GPIO.add_event_detect(MenuButton, GPIO.FALLING, callback=my_callback, bouncetime=500)
try:
IP_address = get_ip_address('wlan0') # WiFi address of WiFi adapter. NOT ETHERNET
except IOError:
try:
IP_address = get_ip_address('eth0') # WiFi address of Ethernet cable. NOT ADAPTER
except IOError:
IP_address = ('NO INTERNET!')
## MPD object instance
# client = MPDClient()
connectionCounter = 0
connectionCounterMax = 10
waitReconnect = 5
notConnected = True
while (connectionCounter < 10) and (notConnected):
connectionCounter += 1
#draw.rectangle((0,0,width,height), outline=0, fill=0)
if mpdConnect(client, CON_ID):
print('Got connected!')
print("Attempt {}" .format(connectionCounter))
notConnected = False
else:
print('failed to connect MPD server.')
print("Attempt {}" .format(connectionCounter))
time.sleep(waitReconnect)
if (connectionCounter == connectionCounterMax):
sys.exit(1)
# Auth if password is set non False
if PASSWORD:
if mpdAuth(client, PASSWORD):
print('Pass auth!')
else:
print('Error trying to pass auth.')
client.disconnect()
sys.exit(2)
last_file = ""
last_state = ""
last_title = ""
while(1):
try:
currentsong = client.currentsong()
state = client.status()
#currenttitle = client.currentsong()['title']
except:
currentsong = "" #check if this makes sense
state = "" #check if this makes sense
print ("unexpected error [0]")
try:
title = currentsong['title']
except KeyError:
try:
title = find_title(currentsong['file'])
except:
print("unexpected error:")
try:
c_file = currentsong['file']
except KeyError:
c_file = ''
if not queue.empty():
job = queue.get()
if job == NextButton:
if (int(state['song']) < (int(state['playlistlength']))-1):
if state['state'] == "stop":
print ("cmd: next(stopped)")
client.play()
client.next()
client.stop()
else:
print ("cmd: next")
client.next()
else:
print("End of Playlist")
elif job == PrevButton:
if (int(state['song']) > 0):
if state['state'] == "stop":
print ("cmd: prev(stopped)")
client.play()
client.previous()
client.stop()
else:
print ("cmd: prev")
client.previous()
else:
print("End of Playlist")
elif job == PlayButton:
if state['state'] == 'play':
print ("cmd: pause")
client.pause()
else:
print ("cmd: play")
client.play()
elif job == StopButton:
print ("cmd: stop")
client.stop()
if ((last_state != state['state']) or (c_file != last_file) or (title != last_title)):
try:
currentsong = client.currentsong()
except:
print ("unexpected error [1]")
try:
station = currentsong['name']
except KeyError:
station = ''
try:
title = currentsong['title']
except KeyError:
try:
title = find_title(currentsong['file'])
except KeyError:
title = ''
try:
artist = currentsong['artist']
except KeyError:
artist = '[no artist]'
try:
album = currentsong['album']
except KeyError:
album = '[no album]'
try:
c_file = currentsong['file']
except KeyError:
c_file = ''
if(station != ''): # webradio
print('Station = ' + station)
print('Title = ' + title)
print('Album = ' + album)
#print(state['song'] + ' / ' + state['playlistlength'])
#print(client.currentsong())
else: # file
print('Title = ' + title)
print('Artist = ' + artist)
print('Album = ' + album)
#print(state['song'] + ' / ' + state['playlistlength'])
last_state = state['state']
last_file = c_file
last_title = title
#print(menu_state)
time.sleep(.1)
## disconnect
client.disconnect()
sys.exit(0)
# Script starts here
if __name__ == "__main__":
try:
main_frontpanel()
except (KeyboardInterrupt, SystemExit):
print("\nQuit\n")
GPIO.cleanup()
For automatic start I use a startfrontpanel.service:
[Unit]
Description=Starts script to interact with front panel
Requires=
After=network.target
#After=mpd.service
[Service]
ExecStartPre=/usr/bin/sh -c "sleep 20"
ExecStart=/usr/bin/myStartBash.sh
TimeoutSec=0
Restart=on-failure
[Install]
WantedBy=multi-user.target
and a bash script:
#!/bin/bash
cd /root/ssd1306/examples
echo "Boot $(date +"%Y/%m/%d %H:%M:%S")" >> /root/shutdown.log
python2 hochri_player_v0_1_2_reduced.py >> /root/text.log 2>&1
In the log file I can see that the python script is started twice (or more often).
For shutdown I also use a service and a bash script:
[Unit]
Description=Save Off Switch Service
After=systemd-modules-load.service
[Service]
Type=simple
ExecStart=/etc/save_off_switch.sh
[Install]
WantedBy=multi-user.target
#!/bin/bash
# this is the GPIO pin receiving the shut-down signal
GPIOpin1=25
echo "$GPIOpin1" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$GPIOpin1/direction
while true; do
sleep 1
power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
if [ $power != 0 ]; then
sleep 0.1
power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
if [ $power != 0 ]; then
sleep 0.2
power=$(cat /sys/class/gpio/gpio$GPIOpin1/value)
if [ $power != 0 ]; then
mpc stop
/srv/http/command/rune_shutdown
# echo "out" > /sys/class/gpio/gpio$GPIOpin1/direction
# echo "1" > /sys/class/gpio/gpio$GPIOpin1/value
echo "Shutdown $(date +"%Y/%m/%d %H:%M:%S")" >> /root/shutdown.log
sleep 3
poweroff
fi
fi
fi
done
I realy would appreciate if you could give me any advice.
Thank you in advance!
Best regards,
Legufix