SSブログ

Volumio2で音楽6 [Volumio]

有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きましたが、時々表示されなくなってしまうことがありました。どうもpythonの変数の使い方が間違っていて、例外が出ていたようです。 ちょっと直してみました。
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import os
import sys
import smbus
import time
import signal
import threading

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from socketIO_client import SocketIO
 
PIDFILE='/var/run/SSD1306.pid'

class SSD1306(object):

	DISPLAYOFF = 0xAE
	DISPLAYON = 0xAF
	DISPLAYALLON = 0xA5
	DISPLAYALLON_RESUME = 0xA4
	NORMALDISPLAY = 0xA6
	INVERTDISPLAY = 0xA7
	SETREMAP = 0xA0
	SETMULTIPLEX = 0xA8
	SETCONTRAST = 0x81
	CHARGEPUMP = 0x8D
	COLUMNADDR = 0x21
	COMSCANDEC = 0xC8
	COMSCANINC = 0xC0
	EXTERNALVCC = 0x1
	MEMORYMODE = 0x20
	PAGEADDR = 0x22
	SETCOMPINS = 0xDA
	SETDISPLAYCLOCKDIV = 0xD5
	SETDISPLAYOFFSET = 0xD3
	SETHIGHCOLUMN = 0x10
	SETLOWCOLUMN = 0x00
	SETPRECHARGE = 0xD9
	SETSEGMENTREMAP = 0xA1
	SETSTARTLINE = 0x40
	SETVCOMDETECT = 0xDB
	SWITCHCAPVCC = 0x2    

	OLED_WIDTH      =  128
	OLED_HEIGHT     =   64
	OLED_PAGE_COUNT =    8
	OLED_SIZE       = ( OLED_WIDTH , OLED_HEIGHT )
	
	OLED_CMDMODE    = 0x00
	OLED_DATAMODE   = 0x40

	def __init__(self,target=0x3C):
		self.OLED_TARGET = target
		self.buffer = [0] * SSD1306.OLED_PAGE_COUNT * SSD1306.OLED_WIDTH
		self.zero   = [0] * 16
		self.__bus  = smbus.SMBus(1)

	def init(self):
		self.command(
			SSD1306.DISPLAYOFF,
			SSD1306.SETDISPLAYCLOCKDIV, 0x80,
			SSD1306.SETMULTIPLEX,       0x3F,
			SSD1306.SETDISPLAYOFFSET,   0x00,
			SSD1306.SETSTARTLINE,
			SSD1306.CHARGEPUMP,         0x14,
			SSD1306.MEMORYMODE,         0x00,
			SSD1306.SETSEGMENTREMAP,
			SSD1306.COMSCANDEC,
			SSD1306.SETCOMPINS,         0x12,
			SSD1306.SETPRECHARGE,       0xF1,
			SSD1306.SETVCOMDETECT,      0x40,
			SSD1306.DISPLAYALLON_RESUME,
			SSD1306.NORMALDISPLAY)
		self.contrast(0xCF)
		self.clear()
		self.show()

	def command(self,*cmd):
		self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_CMDMODE,list(cmd))

	def contrast(self,level):
		self.command(SSD1306.SETCONTRAST,level)

	def clear(self):
		self.command(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1)
		for i in range(0, len(self.buffer), 16):
			self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.zero)

	def show(self):
		self.command(SSD1306.DISPLAYON)

	def display(self,pix):
 		index = 0
		for page in range(8):
			for x in range(128):
				bits = 0
				for bit in [0, 1, 2, 3, 4, 5, 6, 7]:
					bits = bits << 1
					bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1
				self.buffer[index] = bits
				index += 1
		
		self.command(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1)
		for i in range(0, len(self.buffer), 16):
			self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.buffer[i:i+16])

class SSD(SSD1306):
	
	def __init__(self):
		super(SSD,self).__init__()
		
		self.jpfont = ImageFont.truetype('/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf',12, index=0, encoding="unic")
		self.image = Image.new('1', (SSD1306.OLED_WIDTH, SSD1306.OLED_HEIGHT),0)
		self.draw  = ImageDraw.Draw(self.image)

	def init(self):
		super(SSD,self).init()
		
	def set(self,album,title,artist,info):
		self.clean()
		self.display(album,title,artist,info)

	def clean(self):
		self.clear()
		self.draw.rectangle((0,0,SSD1306.OLED_WIDTH-1, SSD1306.OLED_HEIGHT-1), outline=0, fill=0)
	
	def max_length(self,text):
		length = len(text)
		for i in range(0,length-1,1):
			w = self.jpfont.getsize(text[0:i])[0]
			if w > 128:
				return i - 1
		return length

	def display(self,album,title,artist,info):
		self.draw.text( (0,0), album , font=self.jpfont, fill=1 )
		width = self.jpfont.getsize(title)[0]
		if width > 128 - 1:
			length = len(title)
			first_length = self.max_length(title)
			self.draw.text( (0,12), title[0:first_length], font=self.jpfont, fill=1 )
			self.draw.text( (0,24), title[first_length:length-1], font=self.jpfont, fill=1 )
		else:
			self.draw.text( (0,12), title, font=self.jpfont, fill=1 )

		self.draw.text( (0,36), artist, font=self.jpfont, fill=1 )

		self.draw.text( (0,50), info  , font=self.jpfont, fill=1 )

		super(SSD,self).display(self.image.load())

class socketio(object):
 
	def __init__(self):
		self.ssd = SSD()
		self.ssd.init()
		self.loopFlag = True

		self.album = ''
		self.title = ''
		self.artist= ''
		self.samplerate = ''
		self.bitdepth   = ''


	def init(self):
		self.socketIO = SocketIO('localhost', 3000)
		self.socketIO.on('pushState', self.on_pushState)
	
	def on_pushState(self,args):

		s = ''
		b = ''
		i = ''

		if 'samplerate' in args :
			s = args['samplerate']
			s = str(s)
			s.strip
		else:
			s = ''
			
		if 'bitdepth' in args:
			b = args['bitdepth']
			b = str(b)
			b.strip
		else:
			b = ''
		
		if self.album == args['album'] and self.title == args['title'] and self.artist == args['artist'] and self.samplerate == s and self.bitdepth == b :
			return

		self.album = args['album']
		self.title = args['title']
		self.artist= args['artist']
		self.samplerate = s
		self.bitdepth   = b

		print(args['album'].encode('utf-8'))
		print(args['title'].encode('utf-8'))
		print(args['artist'].encode('utf-8'))
		if s =='' and b == '':
			i = 'NaN'
		else:
			i = '%s | %s' % (s,b)
		print(i)

		self.ssd.set( args['album'],args['title'],args['artist'], i )
	

	def setRandom(self):
		self.socketIO.emit('setRandom',{'value' : 'true'})
		self.socketIO.emit('getState')

	def loop(self):
		while True:
			if self.loopFlag == False:
				break
			self.socketIO.wait(seconds=1)
		
	def stop(self):
		self.loopFlag = False
 
def daemonize():

	pid = os.fork()

	if pid > 0:
		pidf = open(PIDFILE,'w')
		pidf.write(str(pid)+'\n')
		pidf.close()
		sys.exit()

	if pid == 0:

		def signal_handler(signal,handler):
			volumio.stop()
			os.remove(PIDFILE)
			sys.exit()

		signal.signal(signal.SIGINT, signal_handler)
		signal.signal(signal.SIGTERM, signal_handler)
		
		volumio = socketio()
		volumio.init()
		volumio.setRandom()
		volumio.loop()

if __name__ == '__main__':
	daemonize()


SSD1306へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
nice!(0)  コメント(2) 

nice! 0

コメント 2

T2

はじめまして。
こちらの記事を拝見して使用させていただきました。
もう完璧です。素晴らしい!
こんなによくできたコードを開示していただきありがとうございます。

by T2 (2018-04-28 00:54) 

opa-san

volumioのプラグイン化もできているのですが、置き場所をどうすればいいのか困っています。ブログ初心者なもので。
PythonもSSD1306操作するのに色々調べて書いたものなので、まだミスがあるかもしれません。なにかあればお知らせください。週末プログラマーより(^^)/
by opa-san (2018-04-28 12:41) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。