【IoTディスプレイ】ラズパイとDiscordBotでIoTデバイスを開発する

2024/02/21

Discord OLED ラズパイ

  • B!
サムネ
サムネ

今回は128×64のOLEDディスプレイとDscordBotを使ってIoTディスプレイを作成していきます。

今回使用するもの

  • RaspberryPi
  • OLEDディスプレイ(128×64)
  • ジャンプワイヤ
  • DiscordBot TOKEN

実現したい動き

  1. DiscordBotにコマンドを送信
  2. モーダルウィンドウでディスプレイに表示したい内容を書く
  3. ディスプレイに表示される
  4.  
  5. リセットコマンドを送信
  6. ディスプレイの内容がリセットされる

サンプルコード

ディスプレイの内容をリセットするときはコマンドを送信してボタンを押すようにします。

  1. import discord
  2. from discord.ext import commands
  3. import datetime
  4. from busio import I2C
  5. from adafruit_ssd1306 import SSD1306_I2C
  6. import board
  7. import time
  8. from PIL import Image, ImageDraw, ImageFont
  9.  
  10. intents = discord.Intents.default()
  11. intents.message_content = True
  12.  
  13. display = SSD1306_I2C(128, 64, I2C(board.SCL, board.SDA), addr=0x3c)#addr=0x3c
  14. image = Image.new("1", (display.width, display.height))
  15. draw = ImageDraw.Draw(image)
  16.  
  17. #日本語対応のフォント
  18. font_jp = ImageFont.truetype("/usr/share/fonts/truetype/ipafont-nonfree-uigothic/ipagui.ttf", 17)
  19.  
  20. bot = commands.Bot(
  21. command_prefix=commands.when_mentioned_or("!"), debug_guilds=[サーバーID], intents=intents
  22. )
  23.  
  24. @bot.event
  25. async def on_ready():
  26. print('[INFO] <' + str(datetime.datetime.now().replace(microsecond=0)) + '> Bot is active')
  27.  
  28. #モーダルを表示
  29. class sendNote(discord.ui.Modal):
  30. def __init__(self, *args, **kwargs) -> None:
  31. super().__init__(
  32. discord.ui.InputText(
  33. label="Line 1",
  34. placeholder="Write a note here",
  35. style=discord.InputTextStyle.short,
  36. ),
  37. discord.ui.InputText(
  38. label="Line 2",
  39. placeholder="Write a note here",
  40. style=discord.InputTextStyle.short,
  41. ),
  42. discord.ui.InputText(
  43. label="Line 3",
  44. placeholder="Write a note here",
  45. style=discord.InputTextStyle.short,
  46. ),
  47. *args,
  48. **kwargs,
  49. )
  50.  
  51. #モーダルの内容を取得
  52. async def callback(self, interaction: discord.Interaction):
  53. embed = discord.Embed(
  54. title="Your Request",
  55. fields=[
  56. discord.EmbedField(
  57. name="Line 1", value=self.children[0].value, inline=False
  58. ),
  59. discord.EmbedField(
  60. name="Line 2", value=self.children[1].value, inline=False
  61. ),
  62. discord.EmbedField(
  63. name="Line 3", value=self.children[2].value, inline=False
  64. ),
  65. ],
  66. color=discord.Color.from_rgb(153,170,181)
  67. )
  68. await interaction.response.defer()
  69. line_1 = self.children[0].value
  70. line_2 = self.children[1].value
  71. line_3 = self.children[2].value
  72. #print(line_1,line_2,line_3)
  73. display.fill(0)
  74. display.show()
  75. draw.rectangle((0,0,display.width,display.height), outline=0, fill=0)
  76. draw.text((0, 0), line_1, font=font_jp, fill=1)
  77. draw.text((0, 20), line_2, font=font_jp, fill=1)
  78. draw.text((0, 40), line_3, font=font_jp, fill=1)
  79. display.image(image)
  80. display.show()
  81. await interaction.followup.send(embeds=[embed])
  82.  
  83. #ディスプレイをリセットする
  84. class resetView(discord.ui.View):
  85. @discord.ui.button(label='reset', style=discord.ButtonStyle.green)
  86. async def first_button(self, button: discord.ui.Button, interaction: discord.Interaction):
  87. button.disabled = True
  88. display.fill(0)
  89. draw.rectangle((0,0,display.width,display.height), outline=0, fill=0)
  90. draw.text((39, 28), 'Empty', font=font_jp, fill=1)
  91. display.image(image)
  92. display.show()
  93. await interaction.response.edit_message(content="RESET", view=self)
  94.  
  95. @bot.slash_command(name="resetnote")
  96. async def view_test(ctx: discord.ApplicationContext):
  97. """reset"""
  98. view = resetView()
  99. await ctx.interaction.response.send_message(content="Reset Button", view=view)
  100.  
  101. @bot.slash_command(name="sendnote")
  102. async def modal_slash(ctx: discord.ApplicationContext):
  103. """OLED"""
  104. modal = sendNote(title="NOTE")
  105. await ctx.send_modal(modal)
  106.  
  107. bot.run("DiscordBot TOKEN")

実行結果

ディスプレイに表示

モーダル送信後

モーダルウィンドウ

OLEDディスプレイの様子

ディスプレイ

ディスプレイをリセット

ボタンを表示させる(押した後)

1回押すと再び押せないようになります。

ボタン

OLEDディスプレイの様子

ディスプレイ

まとめ

ディスプレイの内容が更新されると圧電ブザーなどを用いて音が鳴るようにすると良いかもしれません。

また、リセットボタンはコマンドだけでなくタクトスイッチで物理ボタン化した方がよさそうです。

長い文章を送ると画面から見切れてしまうのでスクロールさせる方法を考える必要があります。

Writer

アイコン
Python×Raspi IoTシステム・Bot・ラズパイの記録
  • プログラミング
  • IoT
  • Python
\FOLLOW ME/ 𝕏

Ranking

blogmura_pvcount

Community

Search