registerIr.py 5.9 KB

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