Rustの勉強

初めてのRust

Rustのドキュメントはとてもわかり易く、言語についての理解が深まる。

さて、まずは勉強1日目、今日はチュートリアルの88ページまで読んで、言語処理100本ノックの一問目をやってみた。

文字を逆順にして返す。

fn main() {
    let text = String::from("hello"); //Stringで変数を定義

    println!("{}", reverse(&text)); //メソッドの呼び出しと戻り値の出力(入力はString型が固定長ではないため参照で渡す。)
}

fn reverse(text: &str) -> String { 
    text.chars().rev().collect() // 固定長のchar型に変換し、逆順にして、またString型に戻す。
}

Pythonがいかに何も考えずにできたかがわかる、、、Rust難しい

Gold Experience

第玖章

nvidia diriverとcudaのバージョンの相性は機械学習を行う上で一番厄介かつ、重要なポイントである。 しかし、UNIX系ではパッケージ管理システムが存在する都合上、ふとした時に全体をアップグレードしてしまうこともしばしば存在する。

sudo pacman -Syu
sudo yay -Syu

この2つは全体をアップグレードするコマンドであるが、これによってnvidia driver及びcudaのバージョンが代わり相性が合わなくなるケースが存在する。 その際、どうやって再び合わせるのか、また、この2つパッケージのバージョンはどうやって固定するのか、ここでは記録として残したい。

まず、お互いの相性が悪くなった際に別々に再インストールすることで解決したが、どこまでのパッケージを再インストールすればいいか、正直よくわかっていない。

と、言うことは全体を再インストールしてやればいい。

sudo pacman -Qnq | sudo pacman -S - 
yay -Qnq | yay -S - 

これによってpacman及びyayに管理されるパッケージはすべて再インストールされる。 環境のクリーニングという面でも都合がいいかもしれない。

これによって再インストールされた後は再起動することでパッケージ同士のバージョンが安定する。

では、次にバージョンが安定すれば、このような悲劇がもう起きないように、パージョンを固定してやればいい。 固定するパッケージは/etc/pacman.confのIgnorePkg に記述する必要がある。

私は以下の様に記述している。

IgnorePkg   = cuda cudnn lib32-nvidia-utils linux510-nvidia nvidia-utils

これによって"おそらく"パッケージのバージョンが固定されるはずである。

さぁ、やっとBERTをGPUを用いて扱うことができる。

Gold Experience

第肆章

cudaのバージョンの最新が11.0から11.1に上がっていた。おかげでDockerのcudaイメージを叩いても、cudaとのネットワークがつながっていない。 なので、cudaのバージョンを上げようとしたが、nvidia-driverのバージョンから上がっていたようだ。 なので、nvidia系のパッケージをすべて削除、最新で入れ直した。 そしたらどっこい、nvidia-smiすら認識しなくなった。driverが死んだ。

悩んだ挙げ句、一つの必殺技を見つけた。

sudo pacman-mirrirs --fasttrack && sudo pacman -Syyu

おそらくpacmanの中で溜まったゴミを一層し、すべてのパッケージを入れ直してくれる、、、ようなイメージ(詳細は調べてない、すみません)。 これで、最新のnvidia系パッケージが正常にインストールできそう。 ただし、nvidia-455とカーネルlinux58及びlinux59は相性が悪いそう。 なので、、やっぱりPython同様7系のバージョンが安定しているようだ。

第伍章

逝った。なにがって?GPUが逝った。 モニターに描画されない。 状況をわかりやすく説明すると、GPUhdmiとディスプレイポートの端子をつないでモニターに接続している。 PCの電源を起動してすぐ、GRUB2によるカーネルの選択画面になり、その後真っ暗になるのだ。 どのカーネルを選択してもダメ、仕方なく "Alt + F2" でCUIモードを起動する。 なんでこういう描画はされるのに、他はダメなんだ、、、

ふと気づくとカーネルlinux56が消えている。俺の安定版だったのに。。。 記憶をたどると "sudo pacman -Syu" をした際カーネルがインストールされていた。 たしか、linux59だったか、、、しまった、最新のデフォルトカーネルが更新されて、同時にlinux56が削除されてしまったのか。。。

消えてしまったものに、思いを馳せても仕方ないので、最新のカーネル(linux59)で再度環境構築を行う。

ちなみにマザボにディスプレイを設定してみた結果、"Could not start simple desplay"などと記述されていたので結局大本のディスプレイドライバが死んでいる気がする。 というわけで、もう仕方ないので、nvidia系のすべてのパッケージを殺すことにした。

sudo pacman -Qs nvidia # インストールされているnvidiaパッケージをすべて出力する。
sudo pacman -Rs ???? # パッケージを依存関係ごと消去していく。

sudo pacman -S nvidia
sudo pacman -S cuda
sudo pacman -S cudnn

これでrebootすると、、、行けた。 今回の原因はカーネルのバージョンが変わったことで各パッケージも変わっていたのにパッケージを増やすばかりで取捨選択をしなかったことだった。 ちゃんと定期的にパッケージの取捨選択を行わないといけなかったわけだ。

いずれにせよ、OSを飛ばさなくて済み良かった。 デフォルトのカーネルの更新が早いので、これはいい教訓になったと思う。

第陸章

また逝ったよ。もちろんGPUです。 モニターが真っ暗ですわ。 原因は簡単。linux59のカーネルで今まで動かしてきたのに、興味本位でlinux510のカーネルを立ち上げたのが原因だった。 次にlinux59で起動したとき、HDDが読み込めなくなっていたほか、様々なトラブルが起きて立ち上がることさえなかった。 こうなってはもうやることは一つ、linux510で再構築するしかない。

再構築の手順は第伍章のとおりである。 そして文字コードGUIとは管轄が違うようなので、合わせることが必要になる。 コマンドは以下

LANG=C

また、"sudo pacman -Rsで消えないパッケージも存在した。

  • local/mhwd-nvidia-390xx 390.143-1 MHWD module-ids for nvidia 390.143
  • local/libvdpau 1.4-1 Nvidia VDPAU library

この2つは依存関係からどうも消去できない。(依存先を消していいものかわからない) まぁ、干渉してこないようなので、放置だ。

nvidiaには何度も悩まされるが、この情報があればなんとかなるだろう。

第漆章

今度はパッケージ更新した際に、HDMIから音声がでなくなった。 フォーラムでこの課題について確認すると同じ症状の人がいた。(https://forum.manjaro.org/t/hdmi-audio-isnt-working-on-an-asus-laptop/63320/50)

結果的に解決策としては、以下の2コードを打ち込むだけだった。

amixer -c0 sset 'Auto-Mute Mode' Disabled
rm ~/.config/pulse/cookie ~/.config/pulse/*.tdb 

ただ、このコマンドは該当パッケージが更新されるたびに打ち込む必要があるので注意。

第捌章

???「我々はひとつのOSを失った。しかし、これは廃棄を意味するのか?否!始まりなのだ! windowsユーザに比べ、我がmanjaroのユーザは30分の1以下である。 にもかかわらず今日まで使いこなしてこられたのは何故か? 諸君!我がmanjaroの使用目的が正義だからだ。これは諸君らが一番知っている。 我々は世界的シェアを追われ、ニッチなOS扱いにさせられた。 そして、一握りの企業らが世界的シェアにまで膨れ上がったwindowsを支配して50余年、 OS界の辺境に住む我々が自由を要求して何度踏みにじられたか。 manjaroの掲げるOS一つ一つの自由のための戦いを神が見捨てるはずはない。 私のOS!諸君らが愛してくれたmanjaroは飛んだ。 何故だ!?」

???「BIOSをアップデートしたからさ」 ※ 機動戦士ガンダム作中 manjaro追悼式典より

というわけで、manjaroが飛んだ 理由は前述の通りBIOSをアップデートしたからだ。

BIOSをアップデートする経験は初めてで、なんとなくアップデートしたのは間違いだった。 原因はアップデートした際、BIOSの設定が初期化されmanjaroが入ったSSDが読み込めなくなる。 ただ、それだけだったのだが、、、

原因を突き止められなかった私は、manjaroを起動できず、データすら取り出すことができなかった。 その結果、OSの再インストールを決めた(なので、飛んだ原因は私)。

だが悲劇はまだ続く manjaroがSSDをロックしており、外部から削除することができなかった。 また、削除する過程で、SSDに上書きを行った結果、実は上書きしたSSDがmanjaroではなく、操作中のwindowsだった。

そう、そもそも同じ型番のSSD、まさかwindows SSDが表示されており、それを操作しているとは微塵にも思っていなかった(マシンの理解不足)。 かくして、私は2つのOSを失った。

そして、更にその2つのSSDBIOSから姿を消した。 認識しなくなったのである。

流石にお手上げと思い、父に相談するが、SSDを物理的に壊したのではないかとの回答 そんなことがあるのか?たった数行のコマンドでSSDが物理的に、、、?

まさか、ありえない、そう思い探しまくり2日 見つけた。 これだ。

結果的には、以下の3つの設定を変更することで解決した。

  1. セキュアブートを無効にします。
  2. RAID OnからSATAコントローラーをAHCIに設定します。
  3. ブートモードをUEFIからレガシーに設定します。

もう二度とこんなことごめんだ。 バックアップは適宜取るように心がけたい。

Gold Experience

これはubuntuしか触ったことのない少年がmanjaroと出会い、成長していくストーリーである。

第零章 : PUROROGE

まず私は、自分がintel core-i9 10850Kを購入したことに感謝したい。 manjaroは、インストール直後nvidia driverは入っていないため、GPUに接続されたモニタは機能しないのだ。 そこで、core-i9の "K" の出番である。"K" には、CPUに最低限のGPUが内蔵されている。 私はそのおかげで、マザーボードに接続されたモニタでmanjaroの設定を行うことができた。

第壱章 : INSTALLER

ubuntuは、いい。わからないときには、調べれば初心者用の記事が数多く出てくる。 しかし、デザインが好きではなかった。私はubuntuに飽きてしまったのだ。 その日私は、ubuntuの環境構築を行っていた。もうやりなれた作業で、淡々とこなしていたが、GPUの環境構築でしくじった。 最近よく見るubuntuの環境構築記事はAWSを対象に書いている記事も多い。 私は、誤ってそちらの記事を参考にnvidiaのドライバをいれてしまった。 結果、GPUは正常に作動していたが、描画用に機能する設定はできていなかったのである。

そこで、ラボのシス管はこういった。 「manjaroにしましょう。」と。 manjaroとは、そもそもArch-linux系のカーネルで、ubuntudebian系のカーネルである。 同じlinuxでも、どの程度ubuntuの経験が通用するか不安で、はじめは渋った。 しかし、彼のmanjaroに対する熱い想いに押され、私はついにmanjaroに手を出したのだった。

manjaroのインストーラには4つのタイプがある。

  • plasma : デザインがイケメン
  • XFFCE : windowsに似ている
  • GNOME : ubuntuに似ている

これはX-windowのデザインを選択させている。また、CUIアーキテクチャだけを最初にインストールし、自分で詳細を細かく設定することもできる。 私は、この中でシス管の彼が使用していたplasmaを入れることにした。

第弐章 : INSTALL

パッケージを入れたUSBから、インストーラを起動した。 GRUB2のブートローダからmanjaroを選択し、OSを起動させた。 しかし、真っ黒な背景にBIOSのアイコンが画面中央に表示されたまま止まった。 しばらくして、紫色のノイズが画面上に走り、真っ黒な背景を半分に割ったのだった。 モニタから出たHDMIケーブルはGPUに接続されていた。

 

何度再起動しても、画面にはノイズが走る。原因がわからない。 そこで、CUIインストーラをUSBに入れ、再度試した。 しかし、GRUB2のブートローダが起動するのは、CUIアーキテクチャとて変わらない。 結果は、失敗だった。

時刻はその時26時を回っていた。 眠気がじわじわと押し寄せる中、ふとマザーボードのHBMIポートにケーブルを挿し直した。 すると、きれいな細かい文字が下から上へサーっと流れ、manjaroのインストーラが起動したのだった。

起動した感動で眠気が飛び、manjaroのM.2 SSDへのインストールを淡々とボタンをポチポチと押し、実行した。 ここで、問題が出た。 インストーラが95%で止まったのだ。 ちょうどその時シス管の彼が3時間前に投稿されたmanjaroのバグについて読んでいた。 同じ症状だった。解決策はまだ立っていなかったので、強制シャットダウンし、インストールされたmanjaroを起動してみた。

更新されていないパッケージが500件ほどあったが、問題なく動作している。 もしやイけるのでは...?

第参章 : PACKAGE

ここでubuntuとの違いだが、ubuntuのパッケージ管理システムはaptだが、manjaroはpacmanである。 これがうまく動作すれば、おそらく大丈夫だろうと考え、まずはパッケージの更新を行った。

sudo pacman -Syu #全パッケージのアップグレードとリフレッシュ

これを行うことで、95%で固まったインストーラの残りのタスクを保管できていると思っている。(実際更新されたパッケージは500個ほどあり、インストール直後にあった未更新のパッケージ数とほぼ一致した。)

さぁ、ここからは自分の欲しいパッケージのインストール作業である。 私のPCには、RTX2070SUPERが入っているのですが、現状モニタに接続されているのは、マザボであるためGPUからモニタ接続したい。 欲しいパッケージは - nvidia-driver-450.66 - cuda11 - cuDnn8 の3つである。 ubuntuであれば、CUDAのインストールまでがOSのインストールだと思っている。 というのは、慣れるまではCUDAのインストールがとても骨が折れる作業なのである。 しかし、manjaroはその限りではない。なぜなら "pacman"がいるからである。 上記3つのインストールは

sudo mhwd -i pci video-nvidia-450xx
sudo pacman -Syu cuda
sudo pacman -Syu cudnn

以上である。 素晴らしい。ubuntuのあの努力は何だったのか。 あぁ、、、もっと早くmanjaroを知りたかった。 他にもメジャーなパッケージはpacmanを用いれば簡単にダウンロードできるそうだ。 あぁ、感動だ。 今回はこれで以上にしたい。 manjaroを紹介してくれたシス管の彼には本当に感謝したい。ありがとう。

 

就活サイトからESをかっさらってくる。

最近、機械学習用の言語データがないかなーって探していたんですけど、いい情報がなくて諦めていました。 そしたらたまたま、いい記事を見つけたので真似をしてみることに。

それがこちらの記事 この記事はunistyleに公開されているESをスクレイピングによって取得するというものでした。

しかし、この記事は2年前に執筆されており、実行すると不具合が出ました。 そこで、コードを修正(コードの可読性、効率は悪くなった、、、)し、ここに記録として載せました。

それが以下のコード

#coding:utf-8
PURPLE  = '\033[35m'
RED     = '\033[31m'
CYAN    = '\033[36m'
OKBLUE  = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL    = '\033[91m'
ENDC    = '\033[0m'

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from bs4 import BeautifulSoup
from extractcontent3 import ExtractContent
import pickle
import sys

##### ExtractContent(only fetch contents)########
def extractor(html):
    extractor = ExtractContent()
    opt = {"threshold":50}
    extractor.analyse(html)
    text, title = extractor.as_text()
    return text


email = 'USER_ID'
password = 'USER_PASSWORD'
LOGIN_URL= 'https://unistyleinc.com/'

# Log in
options = Options()
options.binary_location = "/usr/bin/google-chrome"
b = webdriver.Chrome(chrome_options = options, executable_path='./chromedriver')
b.get(LOGIN_URL)
b.find_element_by_id('LoginLink').click()
b.find_element_by_name('user[email]').send_keys(email)
b.find_element_by_name('user[password]').send_keys(password)
b.find_element_by_class_name('login_submit').click()

def first():
    # Move to categories
    time.sleep(0.1)
    b.get('https://unistyleinc.com/categories')
    category = b.find_element_by_class_name('es_category_list')
    a = category.find_elements_by_css_selector("a")
    dict_category = {}
    for total,i in enumerate(a):
        if not total == int(category_num):
            continue
        name = str(i.text.replace('>',''))
        URL  = str(i.get_attribute("href"))
        print ('STEP1 : '+str(total+1)+'/'+str(len(a))+' '+name+'--->'+OKBLUE+URL+ENDC)
        dict_category[name]=URL

    # Move to company from the category
    dict_company = {}
    for name in dict_category:
        URL = dict_category[name]
        b.get(URL)
        time.sleep(0.1)
        companies = b.find_element_by_class_name('essearch_common_wrap')
        a = companies.find_elements_by_css_selector("a")
        for i in a:
            company = str(i.text.split(' ')[0])
            URL  = str(i.get_attribute("href"))
            if URL != 'https://unistyleinc.com/categories':
                dict_company[company] = URL
                print ('STEP2 : '+company+'--->'+OKGREEN+URL+ENDC)

    # 本選考などESpageを取得
    dict_kindofES = {}
    for company in dict_company:
        URL = dict_company[company]
        b.get(URL)
        time.sleep(0.1)
        ESs = b.find_element_by_class_name('essearch_common_wrap')
        a = ESs.find_elements_by_css_selector("a")
        
        count = 0
        for i in a:
            cmp = str(i.text.split(' ')[0])
            URL  = str(i.get_attribute("href"))
            if count != 0 and URL != 'https://unistyleinc.com/categories':
                dict_kindofES[company+cmp] = URL
                print ('STEP3 : '+company+cmp+'--->'+OKGREEN+URL+ENDC)
            count = count + 1

    # Move to (ES/interview/OB visit etc...)page from company URL
    dict_com_url = {}
    for company in dict_kindofES:
        URL = dict_kindofES[company]
        b.get(URL)
        def get_ES_URL(b,dict_com_url):
            time.sleep(0.1)
            list_ES = b.find_elements_by_class_name('es_container')
            for i in list_ES:
                a = i.find_element_by_css_selector("a")
                url   = str(a.get_attribute("href"))
                print ('STEP4 : '+company+'--->'+PURPLE+url+ENDC)
                dict_com_url.setdefault(company, []).append(url)

        ES_page_number = b.find_elements_by_class_name('fg essearch_page_btn')
        if not len(ES_page_number) == 0:
            for epn in ES_page_number:
                a = epn.find_element_by_css_selector("a")
                EsPageUrl = str(a.get_attribute("href"))
                b.get(EsPageUrl)
                get_ES_URL(b,dict_com_url)
        else:
            get_ES_URL(b,dict_com_url)
    with open('./dict_com_url.pickle', mode='wb') as f:        
        pickle.dump(dict_com_url,f)
        
def second():
    with open('./dict_com_url.pickle', mode='rb') as f:
        dict_com_url = pickle.load(f)
    #Save contents
    W = open('result'+args[2]+'.csv','w')
    W.write('ID,Company,URL,Contents\n')
    num = 0
    code = 0
    dict_com_url_count = 0
    for key in dict_com_url:
        list_URL = dict_com_url[key]
        for j,URL in enumerate(list_URL):
            try:
                b.get(URL)
                time.sleep(0.1)
                html = b.page_source
                text = extractor(html)
                # text = text.replace(',','').replace('\n',' ').replace('\t','').replace('\r','')
                text = text.replace(',',',')
                print ('STEP5 : '+key+'--->'+PURPLE+URL+ENDC)
                print (text[:100]+'...')
                W.write(str(num)+','+key+','+URL+','+text+'\n')
            except:
                # print ('request error')
                code = 1
                break
            num+=1
        if code == 1:
            print("システムが終了しました。\n最終実行はdic_com_url:"+str(dict_com_url_count)+"番のlist_URL:"+str(j)+"番です。")
            break
        dict_com_url_count += 1
    W.close()

def therd():
    with open('./dict_com_url.pickle', mode='rb') as f:
        dict_com_url = pickle.load(f)
    #Save contents
    W = open('result'+args[2]+'.csv','a')
    num = int(args[3])
    code = 0
    dict_com_url_count = 0
    for i,key in enumerate(dict_com_url):
        if i >= int(args[3]):
            list_URL = dict_com_url[key]
            for j,URL in enumerate(list_URL):
                if i == int(args[3]) and j < int(args[4]):
                    continue
                try:
                    b.get(URL)
                    time.sleep(0.1)
                    html = b.page_source
                    text = extractor(html)
                    text = text.replace(',',',')
                    print ('STEP5 : '+key+'--->'+PURPLE+URL+ENDC)
                    print (text[:100]+'...')
                    W.write(str(num)+','+key+','+URL+','+text+'\n')
                except:
                    code = 1
                    break
                num+=1
            if code == 1:
                print("システムが終了しました。\n最終実行はdic_com_url:"+str(dict_com_url_count)+"番のlist_URL:"+str(j)+"番です。")
                break
            dict_com_url_count += 1
    W.close()

args = sys.argv
category_num = args[2]

if args[1] == "1":
    first()
elif args[1] == "2":
    second()
elif args[1] == "3":
    therd()
else:
    print(args+"が入力されました\n第一引数:シーケンス番号,第二引数:カテゴリ番号,第三引数:中途開始番号1,第四引数:中途開始番号2")

このコードは2回、ないし3回実行することが必要です。

実行は

python3 Scraping.py 1 [企業カテゴリ番号(0-35)]
python3 Scraping.py 2 [企業カテゴリ番号(0-35)]

しかし、seleniumの影響でスクレイピング数が変化します。 なので、もし途中で止まった場合、どこで止まったか最後に表示するようにしているので、 その続きから実行するために

python3 Scraping.py 3 [企業カテゴリ番号(0-35)] [中途開始番号1] [中途開始番号2]

として、エラーなく最後まで実行できるようにします。 また、これでもまだ途中で止まる可能性があるので、その場合は途中開始番号1に前回の途中開始番号1を足した値を入れてあげることで またその続きから実行できます。

お粗末な改修プログラムですが、誰かのお役にたてますように

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を選択して曲を再生、停止してからプログラムを実行させてください。

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

以上。