registerIr.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. with subprocess.Popen(MODE2CMD, stdout=subprocess.PIPE) as proc:
  96. p = select.poll()
  97. p.register(proc.stdout)
  98. codes = []
  99. i = 0
  100. while True:
  101. ret = p.poll(timeout)
  102. if len(ret) == 0: # timeout
  103. proc.terminate()
  104. return None
  105. line = proc.stdout.readline().strip().decode()
  106. if i > 2:
  107. code = line.split(' ')[1]
  108. codes.append(code)
  109. i += 1
  110. if i > 69:
  111. break
  112. proc.terminate()
  113. return codes
  114. def timeout():
  115. global LCD
  116. LCD.clear()
  117. LCD.message(STR_ERR, c='#FF0000')
  118. time.sleep(60)
  119. os.system('/sbin/reboot')
  120. sys.exit(1)
  121. #
  122. # Script starts here
  123. if __name__ == "__main__":
  124. # switch
  125. GPIO.setmode(GPIO.BCM)
  126. GPIO.setup(SW1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  127. sw = GPIO.input(SW1)
  128. GPIO.cleanup()
  129. if sw != GPIO.LOW:
  130. sys.exit(0)
  131. # stop service
  132. os.system('/sbin/systemctl stop lircd')
  133. os.system('/sbin/systemctl stop superdac')
  134. os.system('/sbin/systemctl stop mpd')
  135. time.sleep(20)
  136. #
  137. LCD = simpleLCD()
  138. LCD.message(STR_GUIDE)
  139. r = receiveIr(5*60*1000)
  140. if r is None:
  141. timeout()
  142. # Learn
  143. for item in BUTTONS:
  144. LCD.clear()
  145. y = LCD.message( [item['prompt']], c='#FF0000')
  146. LCD.message(STR_MESSAGE, y=y)
  147. r = receiveIr(2*60*1000)
  148. if r is None:
  149. timeout()
  150. item['code'] = r
  151. # config
  152. # print(BUTTONS)
  153. with open(IR_CONF, 'w') as f:
  154. print('begin remote' , file=f)
  155. print('' , file=f)
  156. print(' name remocon' , file=f)
  157. print(' flags RAW_CODES|CONST_LENGTH' , file=f)
  158. print(' eps 30' , file=f)
  159. print(' aeps 100' , file=f)
  160. print(' gap 100000' , file=f)
  161. print('' , file=f)
  162. print(' begin raw_codes' , file=f)
  163. for item in BUTTONS:
  164. code = item['code']
  165. print(' name ' + item['label'], file=f)
  166. for i in range(12):
  167. f.write(' ')
  168. for j in range(6):
  169. try:
  170. c = code.pop(0)
  171. f.write(c.rjust(8))
  172. except Exception as e:
  173. break
  174. f.write('\n')
  175. print(' end raw_codes' , file=f)
  176. print('end remote' , file=f)
  177. LCD.clear()
  178. LCD.message(STR_END)
  179. time.sleep(30)
  180. os.system('/sbin/reboot')
  181. sys.exit(0)