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

2024/02/21

Discord OLED ラズパイ

  • B!

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

今回使用するもの

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

実現したい動き

DiscordBotにコマンドを送信
モーダルウィンドウでディスプレイに表示したい内容を書く
ディスプレイに表示される

リセットコマンドを送信
ディスプレイの内容がリセットされる

サンプルコード

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

import discord
from discord.ext import commands
import datetime
from busio import I2C
from adafruit_ssd1306 import SSD1306_I2C
import board
import time
from PIL import Image, ImageDraw, ImageFont

intents = discord.Intents.default()
intents.message_content = True

display = SSD1306_I2C(128, 64, I2C(board.SCL, board.SDA), addr=0x3c)#addr=0x3c
image = Image.new("1", (display.width, display.height))
draw = ImageDraw.Draw(image)

#日本語対応のフォント
font_jp = ImageFont.truetype("/usr/share/fonts/truetype/ipafont-nonfree-uigothic/ipagui.ttf", 17)

bot = commands.Bot(
    command_prefix=commands.when_mentioned_or("!"), debug_guilds=[サーバーID], intents=intents
)

@bot.event
async def on_ready():
    print('[INFO] <' + str(datetime.datetime.now().replace(microsecond=0)) + '> Bot is active')

#モーダルを表示
class sendNote(discord.ui.Modal):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(
            discord.ui.InputText(
                label="Line 1",
                placeholder="Write a note here",
                style=discord.InputTextStyle.short,
            ),
            discord.ui.InputText(
                label="Line 2",
                placeholder="Write a note here",
                style=discord.InputTextStyle.short,
            ),
            discord.ui.InputText(
                label="Line 3",
                placeholder="Write a note here",
                style=discord.InputTextStyle.short,
            ),
            *args,
            **kwargs,
        )

    #モーダルの内容を取得
    async def callback(self, interaction: discord.Interaction):
        embed = discord.Embed(
            title="Your Request",
            fields=[
                discord.EmbedField(
                    name="Line 1", value=self.children[0].value, inline=False
                ),
                discord.EmbedField(
                    name="Line 2", value=self.children[1].value, inline=False
                ),
                discord.EmbedField(
                    name="Line 3", value=self.children[2].value, inline=False
                ),
            ],
            color=discord.Color.from_rgb(153,170,181)
        )
        await interaction.response.defer()
        
        line_1 = self.children[0].value
        line_2 = self.children[1].value
        line_3 = self.children[2].value
        #print(line_1,line_2,line_3)
                
        display.fill(0)
        display.show()
        
        draw.rectangle((0,0,display.width,display.height), outline=0, fill=0)
        draw.text((0, 0), line_1, font=font_jp, fill=1)        
        draw.text((0, 20), line_2, font=font_jp, fill=1)
        draw.text((0, 40), line_3, font=font_jp, fill=1)
        
        display.image(image)
        display.show()
        
        await interaction.followup.send(embeds=[embed])

#ディスプレイをリセットする
class resetView(discord.ui.View):
    @discord.ui.button(label='reset', style=discord.ButtonStyle.green)
    async def first_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        button.disabled = True
        display.fill(0)
        draw.rectangle((0,0,display.width,display.height), outline=0, fill=0)
        draw.text((39, 28), 'Empty', font=font_jp, fill=1)
        display.image(image)
        display.show()
        await interaction.response.edit_message(content="RESET", view=self)

@bot.slash_command(name="resetnote")
async def view_test(ctx: discord.ApplicationContext):
    """reset"""
    view = resetView()
    await ctx.interaction.response.send_message(content="Reset Button", view=view)

@bot.slash_command(name="sendnote")
async def modal_slash(ctx: discord.ApplicationContext):
    """OLED"""
    modal = sendNote(title="NOTE")
    await ctx.send_modal(modal)

bot.run("DiscordBot TOKEN")

実行結果

ディスプレイに表示

モーダル送信後

OLEDディスプレイの様子

ディスプレイをリセット

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

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

OLEDディスプレイの様子

まとめ

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

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

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

Ranking

Community

Search