Raspberry piとBluetoothスピーカでSpotifyプレーヤーをつくってみた。

今回は家にあるRaspberry pi4の活用方法を考えていましたが、IKEABluetoothスピーカーを買ったことをきっかけに音楽プレーヤーを作ってみました。

その方法をここに記したいと思います。

 

まずは、使用したもののリスト

Raspberry pi4 OS:ubuntu Server 20.04.2 LTS IKEA Bluetoothスピーカー:ENEBY30 SONY PaSoRi RC-S380  

なぜカードリーダーが使用リストに入っているのか。

それは、帰宅して玄関のリーダーにカードをかざすとSpotifyから曲が再生されるようにしたからです。(とりあえず使いたかった。)

 

さぁ、まずはじめにBluetoothスピーカーと接続します。(Raspberry piの基本的なセットアップはすでにできている程で進めます) 特筆して入れたのはneovim くらいですね。また、プログラムはpython3.8で組んでいます。   ここで参考にしたのはここです。 この記事はAmazon Echoでやっていますが、通常のBluetoothスピーカでも同じでした。

特筆すべき点として、この記事の"Amazon EchoとのBluetooth接続を維持する"の項で記されている以下のコードを修正します。 理由は、どうもエラーをはいてうまく動作していなかったからと、私のスピーカーが20分で電源が切れるので、15分程度でいいかなと思ったからです。

修正前

$ crontab -e
----- 追加 -----
*/5 * * * * /usr/bin/aplay/aplay -q -D bluealsa /home/nosound.wav >/dev/null 2>&1

修正後

$ crontab -e
----- 追加 -----
*/15 * * * * aplay -q -D bluealsa /home/nosound.wav >/dev/null 2>&1

ちなみに >/dev/null 2>&1 がどういう意味なのか興味があって調べてみると、標準出力をカットするみたいです。参考

つぎにカードリーダで学生証を読み取れるようにします。 なぜ学生証か、余ってるからです。

先に参考とした記事はこちらです。

main.py

import sys
import binascii
import nfc
import requests
import json
import demo3
import time
import subprocess

#弊学の学生証の学籍番号が格納されているサービスコード
service_code = 0x0A0B

def connected(tag):

    if isinstance(tag, nfc.tag.tt3.Type3Tag):
        try:
            #16ビットのservice_codeからservice >> 6で上位10ビットを取り出し、service_code && 0x3fで下位6ビットを取り出す
            svcd = nfc.tag.tt3.ServiceCode(service_code >> 6, service_code & 0x3f)
            #serviceはread_without_encryptionの引数service_list内でのインデックス
            blcd = nfc.tag.tt3.BlockCode(0,service=0)
            #read_without_encryptionでタグの指定した部分の情報内のブロックデータを読み取る
            block_data = tag.read_without_encryption([svcd], [blcd])
            #今回ではブロックデータの1文字目から8文字目に格納されている、それを文字列に変換しutf-8でデコード
            student_id = str(block_data[0:8].decode("utf-8"))
            print(student_id)
        except Exception as e:
            print("Error:%s" % e)
    else:
        print("Error:tag isn't Type3Tag")

    #値をTrueで返すと触れて離すまでの間、一回だけ処理を行う
    return True

clf = nfc.ContactlessFrontend('usb')

def main():
    bool = False
    while True:
        #学生証を読み取るまで待機
        clf.connect(rdwr={'on-connect': connected,})
        send.send_message(bool)
        if bool == True: # Falseは出勤、Trueは帰宅
    print("帰宅")
            demo3.play()
            bool = True
        else:
            print("出勤")
            try:
                demo3.pause()
            except:
                pass
            bool = False

try:
    main()
except KeyboardInterrupt:
    print("Forced termination")
    clf.close()
    sys.exit(0)

以上がmainプログラム。この中でimportされているdemo3.pyでspotifyを操作します。 参考はここ ここのプログラムはアーティスト名から勝手にプレイリストを作成してくれますが、プレイリストが多くなるので以下の様に変更しました。 

demo3.py

import spotipy
import spotipy.util as util
import sys
import random
import subprocess
import requests
import json

def play(): #再生

    username = "hogehoge"
    scope = 'user-read-playback-state,playlist-read-private,user-modify-playback-state,playlist-modify-public'

    token = util.prompt_for_user_token(username, scope)

    header = {'Authorization': 'Bearer {}'.format(token)}

    res = requests.get("https://api.spotify.com/v1/me/player/devices", headers=header)
    devices = res.json()
    device_id = devices["devices"][0]['id']

    playlist_id = 'HOGEHOGE' #プレイリストのURLの最後の/以下の文字列

    param = {'device_id':device_id,
            'context_uri':'spotify:playlist:%s' % playlist_id}

    res = requests.put("https://api.spotify.com/v1/me/player/play", data=json.dumps(param), headers = header)

def pause(): #停止

    username = "hogehoge"
    scope = 'user-read-playback-state,playlist-read-private,user-modify-playback-state,playlist-modify-public'

    token = util.prompt_for_user_token(username, scope)

    header = {'Authorization': 'Bearer {}'.format(token)}

    res = requests.get("https://api.spotify.com/v1/me/player/devices", headers=header)
    devices = res.json()
    device_id = devices["devices"][0]['id']

    playlist_id = 'HOGEHOGE' #プレイリストのURLの最後の/以下の文字列

    param = {'device_id':device_id,
            'context_uri':'spotify:playlist:%s' % playlist_id}

    res = requests.put("https://api.spotify.com/v1/me/player/pause", data=json.dumps(param), headers = header)

これによって、カードをかざすたびに、再生、停止が行えます。

ただし、気をつけなければいけないことが一つ。 rebootなどを行った際は、必ずケータイかPCのspotifyからraspotiyを選択して曲を再生、停止してからプログラムを実行させてください。

これで、完成です。 とってもざっくりな解説でしたが、誰かのお役に立てれば幸いです。

以上。