registerIr.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import subprocess
  4. import select
  5. import signal
  6. import time
  7. import sys
  8. import os
  9. from PIL import Image
  10. from PIL import ImageDraw
  11. from PIL import ImageFont
  12. import ST7735 as TFT
  13. import Adafruit_GPIO.SPI as SPI
  14. import RPi.GPIO as GPIO
  15. # LCD spec.
  16. LCD_WIDTH = 128
  17. LCD_HEIGHT = 160
  18. SPEED_HZ = 8000000
  19. # SUPERDAC configration
  20. DC = 24
  21. RST = 23
  22. SPI_PORT = 0
  23. SPI_DEVICE = 0
  24. SW1 = 5
  25. SW2 = 6
  26. FONTSIZE=14
  27. LINEHEIGHT=16
  28. DEFAULT_FONT = '/usr/share/fonts/truetype/fonts-japanese-gothic.ttf'
  29. IR_CONF='/etc/lirc/lircd.conf.d/remocon.lircd.conf'
  30. MODE2CMD=['/usr/bin/mode2', '--device', '/dev/lirc0', '--driver','default']
  31. BUTTONS=[ {'label': 'PLAY', 'prompt': 'プレイ', 'code': None},\
  32. {'label': 'STOP', 'prompt': 'ストップ', 'code': None},\
  33. {'label': 'PAUSE', 'prompt': '一時停止', 'code': None},\
  34. {'label': 'NEXT', 'prompt': '次曲', 'code': None},\
  35. {'label': 'PREV', 'prompt': '前曲', 'code': None},\
  36. {'label': 'VOLUP', 'prompt': '音量上げ', 'code': None},\
  37. {'label': 'VOLDOWN', 'prompt': '音量下げ', 'code': None},\
  38. {'label': 'MENU', 'prompt': 'メニュー', 'code': None},\
  39. {'label': '0', 'prompt': '数字0', 'code': None},\
  40. {'label': '1', 'prompt': '数字1', 'code': None},\
  41. {'label': '2', 'prompt': '数字2', 'code': None},\
  42. {'label': '3', 'prompt': '数字3', 'code': None},\
  43. {'label': '4', 'prompt': '数字4', 'code': None},\
  44. {'label': '5', 'prompt': '数字5', 'code': None},\
  45. {'label': '6', 'prompt': '数字6', 'code': None},\
  46. {'label': '7', 'prompt': '数字7', 'code': None},\
  47. {'label': '8', 'prompt': '数字8', 'code': None},\
  48. {'label': '9', 'prompt': '数字9', 'code': None},\
  49. ]
  50. STR_GUIDE=['リモコンの登録を',\
  51. '行います。',\
  52. 'リモコンの任意の',\
  53. 'ボタンを5分以内',\
  54. 'に押してください。',\
  55. '信号を検出し',\
  56. '登録を開始します。',\
  57. ]
  58. STR_MESSAGE=['ボタンを',\
  59. '押してください。',\
  60. '(2分以内)',
  61. ]
  62. STR_ERR = ['タイムアウト',\
  63. 'リモコンの信号が',\
  64. '受信できません',\
  65. ]
  66. LCD = None
  67. class simpleLCD():
  68. def __init__(self):
  69. spi = SPI.SpiDev(SPI_PORT, SPI_DEVICE,max_speed_hz=SPEED_HZ)
  70. self.disp = TFT.ST7735(DC, rst=RST, spi=spi)
  71. self.disp.begin()
  72. self.disp.clear((0,0,0));
  73. self.disp.display()
  74. self.draw=ImageDraw.Draw(self.disp.buffer)
  75. self.font = ImageFont.truetype(DEFAULT_FONT, FONTSIZE, encoding="unic");
  76. self.clear()
  77. def clear(self):
  78. self.disp.clear((0,0,0))
  79. def message(self, msg, y = 0, c = '#FFFFFF'):
  80. for line in msg:
  81. self.draw.text((0, y), line, font=self.font, fill=c)
  82. y += LINEHEIGHT
  83. self.disp.display()
  84. return y
  85. def receiveIr(timeout=120*1000):
  86. with subprocess.Popen(MODE2CMD, stdout=subprocess.PIPE) as proc:
  87. p = select.poll()
  88. p.register(proc.stdout)
  89. codes = []
  90. i = 0
  91. while True:
  92. ret = p.poll(timeout)
  93. if len(ret) == 0: # timeout
  94. proc.terminate()
  95. return None
  96. line = proc.stdout.readline().strip().decode()
  97. if i > 2:
  98. code = line.split(' ')[1]
  99. codes.append(code)
  100. i += 1
  101. if i > 69:
  102. break
  103. proc.terminate()
  104. return codes
  105. def timeout():
  106. global LCD
  107. LCD.clear()
  108. LCD.message(STR_ERR, c='#FF0000')
  109. time.sleep(60)
  110. os.system('/sbin/reboot')
  111. sys.exit(1)
  112. #
  113. # Script starts here
  114. if __name__ == "__main__":
  115. # switch
  116. GPIO.setmode(GPIO.BCM)
  117. GPIO.setup(SW2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  118. sw = GPIO.input(SW2)
  119. GPIO.cleanup()
  120. if sw != GPIO.LOW:
  121. sys.exit(0)
  122. # stop service
  123. os.system('/sbin/systemctl stop lircd')
  124. os.system('/sbin/systemctl stop superdac')
  125. os.system('/sbin/systemctl stop mpd')
  126. time.sleep(20)
  127. #
  128. LCD = simpleLCD()
  129. LCD.message(STR_GUIDE)
  130. r = receiveIr(5*60*1000)
  131. if r is None:
  132. timeout()
  133. # Learn
  134. for item in BUTTONS:
  135. LCD.clear()
  136. y = LCD.message( [item['prompt']], c='#FF0000')
  137. LCD.message(STR_MESSAGE, y=y)
  138. r = receiveIr(2*60*1000)
  139. if r is None:
  140. timeout()
  141. item['code'] = r
  142. # config
  143. # print(BUTTONS)
  144. with open(IR_CONF, 'w') as f:
  145. print('begin remote' , file=f)
  146. print('' , file=f)
  147. print(' name remocon' , file=f)
  148. print(' flags RAW_CODES|CONST_LENGTH' , file=f)
  149. print(' eps 30' , file=f)
  150. print(' aeps 100' , file=f)
  151. print(' gap 100000' , file=f)
  152. print('' , file=f)
  153. print(' begin raw_codes' , file=f)
  154. for item in BUTTONS:
  155. code = item['code']
  156. print(' name ' + item['label'], file=f)
  157. for i in range(12):
  158. f.write(' ')
  159. for j in range(6):
  160. try:
  161. c = code.pop(0)
  162. f.write(c.rjust(8))
  163. except Exception as e:
  164. break
  165. f.write('\n')
  166. print(' end raw_codes' , file=f)
  167. print('end remote' , file=f)
  168. os.system('/sbin/reboot')
  169. sys.exit(0)