Volumio2で音楽6 [Volumio]
有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きましたが、時々表示されなくなってしまうことがありました。どうもpythonの変数の使い方が間違っていて、例外が出ていたようです。
ちょっと直してみました。
SSD1306へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
#!/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へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
2017-11-12 14:12
nice!(0)
コメント(2)
はじめまして。
こちらの記事を拝見して使用させていただきました。
もう完璧です。素晴らしい!
こんなによくできたコードを開示していただきありがとうございます。
by T2 (2018-04-28 00:54)
volumioのプラグイン化もできているのですが、置き場所をどうすればいいのか困っています。ブログ初心者なもので。
PythonもSSD1306操作するのに色々調べて書いたものなので、まだミスがあるかもしれません。なにかあればお知らせください。週末プログラマーより(^^)/
by opa-san (2018-04-28 12:41)