registerIr.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. STR_END = ['登録完了です',\
  67. '自動的に再起動',\
  68. 'します。',\
  69. '再起動後リモコン',\
  70. 'が使えるかテスト',\
  71. 'してください',\
  72. 'SW1でいつでも',\
  73. '再登録できます',\
  74. ]
  75. LCD = None
  76. class simpleLCD():
  77. def __init__(self):
  78. spi = SPI.SpiDev(SPI_PORT, SPI_DEVICE,max_speed_hz=SPEED_HZ)
  79. self.disp = TFT.ST7735(DC, rst=RST, spi=spi)
  80. self.disp.begin()
  81. self.disp.clear((0,0,0));
  82. self.disp.display()
  83. self.draw=ImageDraw.Draw(self.disp.buffer)
  84. self.font = ImageFont.truetype(DEFAULT_FONT, FONTSIZE, encoding="unic");
  85. self.clear()
  86. def clear(self):
  87. self.disp.clear((0,0,0))
  88. def message(self, msg, y = 0, c = '#FFFFFF'):
  89. for line in msg:
  90. self.draw.text((0, y), line, font=self.font, fill=c)
  91. y += LINEHEIGHT
  92. self.disp.display()
  93. return y
  94. def receiveIr(timeout=120*1000):
  95. codes = []
  96. with subprocess.Popen(MODE2CMD, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) as proc:
  97. p = select.poll()
  98. p.register(proc.stdout)
  99. i = 0
  100. fstart = False
  101. while True:
  102. ret = p.poll(timeout)
  103. if len(ret) == 0: # timeout
  104. proc.terminate()
  105. return None
  106. line = proc.stdout.readline().strip().decode()
  107. type = line.split(' ')[0]
  108. code = line.split(' ')[1]
  109. if not fstart:
  110. if type == 'pulse':
  111. fstart = True
  112. if fstart:
  113. codes.append(code)
  114. i += 1
  115. if i >= 67:
  116. break
  117. proc.terminate()
  118. return codes
  119. def timeout():
  120. global LCD
  121. LCD.clear()
  122. LCD.message(STR_ERR, c='#FF0000')
  123. time.sleep(60)
  124. os.system('/sbin/reboot')
  125. sys.exit(1)
  126. #
  127. # Script starts here
  128. if __name__ == "__main__":
  129. # switch
  130. GPIO.setmode(GPIO.BCM)
  131. GPIO.setup(SW1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  132. sw = GPIO.input(SW1)
  133. GPIO.cleanup()
  134. if sw != GPIO.LOW:
  135. sys.exit(0)
  136. # stop service
  137. # move /sbin -> /bin ...
  138. os.system('systemctl stop lircd')
  139. os.system('systemctl stop superdac')
  140. os.system('systemctl stop mpd')
  141. time.sleep(20)
  142. #
  143. LCD = simpleLCD()
  144. LCD.message(STR_GUIDE)
  145. r = receiveIr(5*60*1000)
  146. if r is None:
  147. timeout()
  148. # Learn
  149. for item in BUTTONS:
  150. LCD.clear()
  151. y = LCD.message( [item['prompt']], c='#FF0000')
  152. LCD.message(STR_MESSAGE, y=y)
  153. r = receiveIr(2*60*1000)
  154. if r is None:
  155. timeout()
  156. item['code'] = r
  157. # config
  158. # print(BUTTONS)
  159. with open(IR_CONF, 'w') as f:
  160. print('begin remote' , file=f)
  161. print('' , file=f)
  162. print(' name remocon' , file=f)
  163. print(' flags RAW_CODES|CONST_LENGTH' , file=f)
  164. print(' eps 30' , file=f)
  165. print(' aeps 100' , file=f)
  166. print(' gap 100000' , file=f)
  167. print('' , file=f)
  168. print(' begin raw_codes' , file=f)
  169. for item in BUTTONS:
  170. code = item['code']
  171. print(' name ' + item['label'], file=f)
  172. for i in range(12):
  173. f.write(' ')
  174. for j in range(6):
  175. try:
  176. c = code.pop(0)
  177. f.write(c.rjust(8))
  178. except Exception as e:
  179. break
  180. f.write('\n')
  181. print(' end raw_codes' , file=f)
  182. print('end remote' , file=f)
  183. LCD.clear()
  184. LCD.message(STR_END)
  185. time.sleep(30)
  186. os.system('/sbin/reboot')
  187. sys.exit(0)