ラズパイを音声でシャットダウン

ラズパイを音声でシャットダウン

車にラズパイを持ち込んで使いたいけど
シャットダウンするときに困りそうなので
音声でシャットダウンできるようにする

bluetooth ボタンも考えたけど
ハズレをひくと買い直しになるし紛失を考えると
音声でシャットダウンし
シガーソケットから給電すればエンジンをかければ電源がはいる

音声認識エンジンJulius をまずはいれる

Raspberry Pi×JuliusとPythonでスマートスピーカー風にカメラを操作

Raspberry PiとJuliusで特定の単語を認識させる

を参考に

mkdir julius
cd julius/
wget https://github.com/julius-speech/julius/archive/v4.4.2.1.tar.gz
tar xvzf v4.4.2.1.tar.gz 
cd julius-4.4.2.1/

でGit で取得し展開したファイルに移動

sudo apt-get install libasound2-dev libesd0-dev libsndfile1-dev

で必要なライブラリのインストール

Raspberry pi3B+でjuliusを動かせるようになるまでの覚書き(2019.3.10現在)

にあるように
RaspberryPi3b+の最新カーネルでは
snd-pcm-ossモジュールが含まれていないので

sudo apt-get install osspd-alsa
sudo apt-get  install libasound2-dev

でサウンドドライバをインストール

./configure --with-mictype=alsa
make
sudo make install

でコンパイルしてインストール

次に音声認識パッケージの
ディクテーションキットの取得

cd ../
mkdir julius-kit
cd julius-kit/
wget https://osdn.net/dl/julius/dictation-kit-v4.4.zip
unzip dictation-kit-v4.4.zip 

で取得

さらに必要なライブラリのインストール

sudo apt-get install alsa-utils sox libsox-fmt-all

次にマイクの設定

 arecord -l

の結果が

**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

これを元に
ALSADEV設定で使用デバイスを指定

vim ~/.profile 

で設定ファイルを開き

export ALSADEV=hw:2

を最終行へ追記

hw;にはカード番号を記述

source ~/.profile 

で設定反映

あとは起動して実験

cd  ~/julius/julius-kit/dictation-kit-v4.4
julius -C main.jconf -C am-gmm.jconf -demo

起動はするけど精度が低すぎて使い物にならない

このため辞書ファイルを作成する

日本語入力ができるように mozc をインストール

sudo apt-get install fcitx-mozc

次に辞書ファイルの作成

cd ~/julius/
mkdir dict
cd dict/
sudo vim hello.yomi

でファイルを作成

おはよう おはよう
こんにちわ こんにちわ

として保存

左に認識させる言葉
右にはよみかたをひらがなで記述して
.yomi という拡張子で保存

区切りのスペースを半角にしないとバグるので注意

これを元に音素ファイルを作成する
このときに文字コードをUTF8 から EUC-JP に変換するので

iconv -f utf8 -t eucjp hello.yomi | ../julius-4.4.2.1/gramtools/yomi2voca/yomi2voca.pl | iconv -f eucjp -t utf8 > hello.phone

これでファイルが作成される
拡張子は
.phone となる

内容は

おはよう	o h a y o u
こんにちわ	k o N n i ch i w a

となる

次に構文ファイルの作成
これで
認識する文章の構成を定義している

sudo vim hello.grammar

でファイルを作成

S : NS_B HELLO NS_E
HELLO OHAYOU
HELLO KONNICHIWA

として保存

S : NS_B HELLO NS_E

NS_Bが文章の開始
NS_Eが文章の終了
という意味

HELLO OHAYOU
HELLO KONNICHIWA
の部分は
.phone ファイルの読みを大文字にしたもの

あとは語彙ファイルの作成
これはJulius に認識させたい言葉を定義するもので
拡張子は
.voca になる

sudo cp hello.phone hello.voca

でファイルをコピーし編集

% OHAYOU
おはよう o h a y o u
% KONNICHIWA
こんにちは k o N n i ch i w a
% NS_B
[s] silB
% NS_E
[/s] silE

というようにする

次に辞書ファイルへ変換

cd ~/julius/julius-4.4.2.1/gramtools/mkdfa/
mkdfa.pl ~/julius/dict/hello

を実行したがエラー

/home/pi/julius/dict/hello.grammar has 3 rules
/home/pi/julius/dict/hello.voca    has 4 categories and 4 words
---
Now parsing grammar file
Error:       parse error
Error: cannot open "/home/pi/julius/dict/hello.dfa.tmp"
---
no .dfa or .dict file generated

となる

このため
julius 辞書 自作
で検索

ラズパイ4日目①:Juliusで独自辞書を作成する

をみたところ

grammar ファイルの区切りで 
:
で区切っていないので修正

cd julius/dict/
sudo vim hello.grammar

でファイル編集

S : NS_B HELLO NS_E
HELLO : OHAYOU
HELLO : KONNICHIWA

として保存

mkdfa.pl ~/julius/dict/hello

を実行すると
.dfa
.term
.dict
ファイルが生成される

これで独自辞書ができたので
音声認識をするため

julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic

を実行

これで辞書ファイルへ登録した
おはよう
こんにちわ
だけは認識するようになるが
それ以外は表示されない

次に辞書の追加

Raspberry Pi×JuliusとPythonでスマートスピーカー風にカメラを操作

を参考に
.yomi ファイルを編集

おはよう おはよう
こんにちわ こんにちわ
電源オフ でんげんおふ

として保存

iconv -f utf8 -t eucjp hello.yomi | ../julius-4.4.2.1/gramtools/yomi2voca/yomi2voca.pl | iconv -f eucjp -t utf8 > hello.phone

を実行

sudo vim hello.grammar

でファイルを編集

S : NS_B HELLO NS_E
HELLO : OHAYOU
HELLO : KONNICHIWA
HELLO : DENGENNOHU

として保存

sudo vim hello.voca 

でファイルを編集

% OHAYOU
おはよう o h a y o u
% KONNICHIWA
こんにちは k o N n i ch i w a
% DENGENNOHU
電源オフ d e N g e N o f u
% NS_B
[s] silB
% NS_E
[/s] silE

として保存

mkdfa.pl ~/julius/dict/hello

で辞書ファイル作成

julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic


電源オフ
と認識されるのがわかる

次にモジュールモードでJulius の起動

julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf  -nostrip -gram ~/julius/dict/hello -input mic -module

これで Julius がサーバとなり
python プログラムとの通信待ちになる

次に

sudo vim speech.py

でファイルを区制

ラズパイと音声認識でLチカ

も参考に

いくつかコードも調べてみた

# -*- coding: utf-8 -*-

はpython3 なら記載不要

なおインストールしたままの状態だと

python --version

で調べると
Python 2.7.16

Python で文頭に記載する文字コードの「アレ」の名称(なんちゃら UTF-8 みたいなやつ)

を参考に

ファイルの内容は

# -*- coding: utf-8 -*-
import socket

host = 'localhost'   # Raspberry PiのIPアドレス
port = 10500         # juliusの待ち受けポート

# パソコンからTCP/IPで、自分PCのjuliusサーバに接続
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))

res = ''
while True:
 # 音声認識の区切りである「改行+.」がくるまで待つ
 while (res.find('\n.') == -1):
  # Juliusから取得した値を格納していく
  res += sock.recv(1024)

 # 音声XMLデータから、<WORD>を抽出して音声テキスト文に連結する
 word =''
 for line in res.split('\n'):
  # Juliusから取得した値から認識文字列の行を探す
  index = line.find('WORD=')

  # 認識文字列があったら...
  if index != -1:
   # 認識文字列部分だけを抜き取る
   line = line[index + 6 : line.find('"', index + 6)]
   # 文字列の開始記号以外を格納していく
   if line != '[s]':
    word = word + line

  # 「電源オフ」という文字列を認識したら...
  if word == '電源オフ':
   print("電源オフ")
  res =''

この後に

sudo python speech.py

とすると
マイクで
電源オフ
と話しかけると
電源オフ
と表示される

これで音声の認識はできたので
次に
python で linux コマンドの実行

これは subprocess モジュールを使うことでできる

Python: subprocessでOSコマンドを実行する

Pythonでシェルコマンドを実行する

Pythonからシェルコマンドを実行!subprocessでサブプロセスを実行する方法まとめ

を参考に

使い方は
subprocess.run([“実行したいコマンド”,”オプションなど”,…])
でOK

今回はshutdown コマンドを使うので

Raspberry Piの電源をブラウザからOFF

を参考に

# -*- coding: utf-8 -*-
import socket
import subprocess
cmd = "sudo shutdown -h now"

host = 'localhost'   # Raspberry PiのIPアドレス
port = 10500         # juliusの待ち受けポート

# パソコンからTCP/IPで、自分PCのjuliusサーバに接続
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))

res = ''
while True:
 # 音声認識の区切りである「改行+.」がくるまで待つ
 while (res.find('\n.') == -1):
  # Juliusから取得した値を格納していく
  res += sock.recv(1024)

 # 音声XMLデータから、<WORD>を抽出して音声テキスト文に連結する
 word =''
 for line in res.split('\n'):
  # Juliusから取得した値から認識文字列の行を探す
  index = line.find('WORD=')

  # 認識文字列があったら...
  if index != -1:
   # 認識文字列部分だけを抜き取る
   line = line[index + 6 : line.find('"', index + 6)]
   # 文字列の開始記号以外を格納していく
   if line != '[s]':
    word = word + line

  # 「電源オフ」という文字列を認識したら...
  if word == '電源オフ':
    print("電源オフ")
    subprocess.call(cmd, shell=True)
  res =''

として保存

再度

sudo python speech.py 

を実行し
マイクに電源オフと話すと
電源オフと表示された後にラズパイの電源が落ちる

ラズパイ3へNAS 構築

ラズパイ3へNAS 構築

以前構築したものが壊れたので再度NASの構築

以前ダウンロードしておいた
NOOBSを使いインストールメディアの作成

microSD を差し込み

unzip NOOBS_lite_v3_3.zip -d /media/snowpool/0403-0201/

で解凍

インストールは通常版をインストール

インストール終了後
ssh の有効化

sudo raspi-config

で設定画面をだす

5 Interfacing Options を選択

P2 SSH を選択

はい を選択

設定が終わったら
Finish で設定画面を抜ける

これでSSHは有効化されるので
続いて公開鍵認証にする

Ubuntu で ssh-keygenコマンドで作成

-t で暗号形式を rsa
-b で4096ビットに指定
なおデフォルトでは2048ビット

ssh-keygen -t rsa -b 4096

で作成

Enter file in which to save the key (/home/snowpool/.ssh/id_rsa): 

となったらファイル名を入力

今回は nas
としておく

パスフレーズは省略するので

Enter passphrase (empty for no passphrase): 

Enter same passphrase again: 


Enter にすればパスフレーズなしとなる

次に公開鍵の登録

これは
ssh-copy-id コマンドを使う

なお接続するラズパイ3のIPは
Android ならFing で調べることが可能

ssh-copy-id -i nas.pub pi@192.168.1.6

で登録

カレントディレクトリに鍵ファイルなどが生成されるので

mv nas* .ssh/

でファイル移動

ssh -i .ssh/nas pi@192.168.1.6

で接続

次に vim の設定

vim-tiny がインストールされているので

sudo apt-get --purge remove vim-common vim-tiny

でアンインストール

[shel]
sudo apt-get install vim
[/shell]
で通常版 vim をインストール

設定ファイルをつくるので

vim .vimrc

でファイルを作成

"クリップボードからのコピペを可能にする
set clipboard+=unnamed
" シンタックスハイライトの有効化
syntax enable
" 不可視文字を可視化(タブが「▸-」と表示される)
set list listchars=tab:\▸\-
" コマンドラインの補完
set wildmode=list:longest

を記述し保存

なお sudo 権限で vim を使うと設定が反映されていないので

sudo ln -s ~/.vimrc /root/.vimrc

でシンボリックリンクにしておく

鍵認証でログインできるようになったので
パスワード認証による SSHログインを無効化しておく

sudo vim /etc/ssh/sshd_config 

で設定ファイルをひらき

56行目の

#PasswordAuthentication yes

PasswordAuthentication no

にしておく

次に
外付けHDDを再起動時に自動マウントする設定

外付けHDDはすでに過去にext4 でフォーマットしたものを利用
ラズパイ4でRAID1 NASを構築した

によれば
直接ファイルシステムでやり取りしないため
フォーマットは exFAT でなくてもOKとのこと

 fdisk -l

を実行し

Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: External HDD    
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc675b7b1

Device     Boot Start        End    Sectors   Size Id Type
/dev/sda1          63 1953520064 1953520002 931.5G 83 Linux

となっているので認識はしているのを確認

UUIDを確認するので

sudo blkid /dev/sda1

を実行

今回の結果は

/dev/sda1: LABEL="outhdd" /dev/sda1: UUID="96cc41c9-808c-4851-83f5-53bdfa487787" TYPE="ext4" PARTUUID="c675b7b1-01"

外付けHDDのマウント先を作成し
マウント

sudo umount -f /media/pi/96cc41c9-808c-4851-83f5-53bdfa487787 /
sudo mkdir /mnt/hdd
sudo mount /dev/sda1 /mnt/hdd/

これを元に fstab の最終行へ書き込む

sudo vim  /etc/fstab 

でファイルを開き

UUID="96cc41c9-808c-4851-83f5-53bdfa487787"     /mnt/hdd       ext4    defaults 0 0

を追記

fstab については
fstab
https://wiki.archlinux.jp/index.php/Fstab
を参考に

あとは設定反映のため再起動するので

sudo reboot

を実行

これで

 df 

を実行し
マウントされていればOK

今回だと

ファイルシス   1K-ブロック    使用    使用可 使用% マウント位置
/dev/root         29542476 3659976  24358788   14% /
devtmpfs            440756       0    440756    0% /dev
tmpfs               474036       0    474036    0% /dev/shm
tmpfs               474036   18272    455764    4% /run
tmpfs                 5120       4      5116    1% /run/lock
tmpfs               474036       0    474036    0% /sys/fs/cgroup
/dev/mmcblk0p6      258094   54603    203491   22% /boot
/dev/sda1        960379088   95880 911428824    1% /mnt/hdd
tmpfs                94804       0     94804    0% /run/user/1000

というかんじ

次にSamba のインストール

sudo apt-get -y install samba

途中でWINS設定の有無が聞かれるけどいいえでOK

次に設定ファイルの編集

sudo vim /etc/samba/smb.conf 

で設定ファイルを開き
25行目あたりに

dos charset = CP932
unix charset = UTF-8
guest account = pi

を追加

dos charset = cp932
はwindows 側の文字コード

なお、vim の場合 ctrl + shift + v で貼り付けが可能
shift + g で最終行に移動し

[ファミリー]
        path = /mnt/hdd/share/family
        writable = yes
        guest ok = yes
        guest only = yes
        create mode = 0777
        directory mode = 0777

として保存

sambaの設定に関しては
SAMBAの設定(3.0  FC3)(Windowsから利用する場合) 
http://s135.moo.jp/linux/samba.html
を参考に

これで

service smbd restart

でSamba の再起動をすることでファイル共有が可能に

Ubuntu 16.04 の場合
エクスプローラで
ネットワークをクリックすると
RASPBERRYPI
と表示されるので
これを
クリックして今回設定したフォルダをクリックすると
ユーザ認証になるので
ユーザ名 pi
パスワード ラズパイ3のパスワード
とすることでログインしてファイル共有することが可能に

Macの場合 Finder からネットワークをクリックすれば
ファイル共有が可能

ラズパイとスマートホームコントローラ sRemo-R3

ラズパイとスマートホームコントローラ sRemo-R3

Raspberry PiとNode-redで、リビングに飾れる美しい「スマートホームコントローラ」を作ってみた

を参考に実践

irMagician で赤外線センサーを実験したけど
今使われているリモコンのように多数の赤外線センサーが
あるわけではなく1つだけなので
これだと正確に向きを合わせる必要性があり断念

多方向に赤外線を飛ばすには
スマートリモコンを自作するか
もしくは
対応するパーツを購入し
センサーの代わりに代用するほうが効率的と判断

今回は
sRemo-R3 を購入し
これを赤外線でコントロールするセンサーの代わりに使う

すでに node-red はセットしてあるので

ubuntu のブラウザ
今回は firefox で
http://raspberrypi.local:1880/admin/
へアクセス

すでにログインしているなら数日間は
自動ログインできる

管理者権限でのログインになるので
ユーザを admin

パスワードは

bash nrpiadminpass.sh 任意のパスワード

で設定したパスワードを使用

これでログインできることを確認したら
次に静的 webサーバの有効化

settings.js を変更することで静的webサーバを有効化

cd .node-red/
vim settings.js

で設定ファイルを開き
104行目の

//httpRoot: '/red',

のコメントアウトを外し

109行目の

//httpStatic: '/home/nol/node-red-static/',

    //httpStatic: '/home/nol/node-red-static/',
    httpStatic: '/home/pi/node-red-static/',

と元のコードを残し
パスを変えて保存

cd
mkdir node-red-static
cd node-red-static/
echo "<html><body>Test Page</body></html>" > index.html

でテストページを作成

あとは

node-red-restart

で node-red を再起動し

ブラウザで
http://raspberrypi.local:1880/
へアクセスすれば
テストページが表示される

次にスマートリモコンの設定
これはマニュアルをみて設定する

使用したスマートリモコンは
sRemo-R3

マニュアルについては
リモコン設定と操作(エアコン)

を参考に

次にsRemo Cloud へアクセス
https://sremo.biz/
へアクセス

Login をクリックし
初期設定のときに登録した
メルアドとパスワードでログイン

sRemo 情報をクリック

sRemo識別子を覚えておく

そして元のメニューにもどり
APIアクセストークン
をクリック

新規トークン発行をクリック

これでアクセストークンが発行される
なお1ユーザ1トークンとなるので
わからなくなったら再発行することになる

次に sRemoWebAPI の操作

curl -H "Authorization: Bearer <APIアクセストークン>" https://<APIサーバ>/user_api/<sRemo識別子>/send_sig?sig=0-<リモコン番号>

を実行

例えば

APIアクセストークン
123456789

APIサーバ
uapi1.sremo.net

sRemo識別子
abcdefghij

リモコン番号

なら

 curl -H "Authorization: Bearer 123456789" https://uapi1.sremo.net/user_api/abcdefghij/send_sig?sig=0-1

を実行すると
OK
となる

sCloud-API の利用方法については
sCloud-API利用方法

を参考に

温度 湿度 照度
を取得するなら

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/get_thl

を実行すれば

{"t":27,"h":48,"l":55}

というように
JSON形式で返答される
t が温度
h が湿度
l が照度
となる

時間の取得をするには

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/get_time

を実行すれば

{"t":"2020-08-08 05:47:12"}

というように現在時刻を取得できる

コマンドをコピペして実行したときに

{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \"access token\" parameter."}

と出たが
これは ” の部分が全角になっていたため

温度や湿度、照度の取得はできたので
次にエアコンの制御

{画面番号}-a-{ON/OFF}-{モード}-{風量}-{風向}-{温度}
という書式

画面番号1、冷房ON、風量:自動、風向:両方、温度:22℃の場合
リクエストは
https://uapi1.sremo.net/user_api/abcdefghij/send_sig?sig=1-a-n-2-1-4-22
というパラメータになる

ON なら n
OFF なら f

モードは
1 自動
2 冷房
3 暖房

風量は
1 自動
風向き両方なら

温度を22
としているので
コマンドは

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/send_sig?sig=画面番号-a-n-2-1-4-22

としたらできた

エアコンの停止をするには

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/send_sig?sig=画面番号-a-f-2-1-4-22

というように
パラメータを 停止の f を指定して実行すればOK

次に照明

{画面番号}-{家電種別}-{制御番号}
照明 l
TV 5
DVD d
スイッチ s
が家電種別

制御番号は
消灯2
全灯3

画面番号3、TV、ミュートの場合
https://uapi1.sremo.net/user_api/abcdefghij/send_sig?sig=3-t-29
というパラメータになるので
これを参考に実践

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/send_sig?sig=画面番号-l-3

で全灯

curl -H "Authorization: Bearer APIアクセストークン" https://APIサーバ/user_api/sRemo識別子/send_sig?sig=画面番号-l-2

で消灯
となる

とりあえずエアコンの動作、照明のON・OFFは
コマンドから操作できるようになり
部屋の温湿度、照度も
sRemo-R3 で取得できるようになった

取得結果は JSON で得られるので
今後の課題は
シェルスクリプトで定期的にセンサーで取得し
温湿度に合わせて自動でエアコンを動作させること

ラズパイ3で赤外線リモコンの操作

ラズパイ3で赤外線リモコンの操作

Raspberry Pi 3 で赤外線リモコン&温度センサーを試す

を参考に実践

まず
irMagician を ラズパイ3にUSB ケーブルで接続

使用するのはAndroid で使っているものでOK

irMagician の黄色LEDが点滅していれば認識している

また

ls -l /dev/ttyACM0


/dev 以下に ttyACM0 が存在していれば認識しているのを
確認できる

次に
ptyhon-pip と pyserial のインストール

curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
python get-pip.py
pip install pyserial

制御プログラムを git で取得

git clone https://github.com/netbuffalo/irmcli.git
cd irmcli/

で移動してから赤外線センサーの学習

udo python irmcli.py -c

を実行したけど

  File "irmcli.py", line 15
    print "Capturing IR..."
                          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Capturing IR...")?

となる

SyntaxError: Missing parentheses in call to ‘print’.
で検索してみると
どうやら
python3 から print の構文が変わっていて

Python3 print でシンタックスエラーになった。

によれば

Python3からはprint()で実行しないとエラーになる

とのこと

15行目の
print “Capturing IR…”

print(“Capturing IR…”)
として
実行したら

  File "irmcli.py", line 19
    print msg
            ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(msg)?

となるので

さすがに毎回変更は面倒なので

vim irmcli.py

でファイルを開き

:%s/print msg/print(msg)/g

で一度に変更

vim の置き換えについては
vim置換

を参考に

いくつか修正するところがあるので
/print ”
で検索し
print() になるように修正

  File "irmcli.py", line 113
    print ir_serial.readline().rstrip()

については

print(ir_serial.readline().rstrip())

とすると

Traceback (most recent call last):
  File "irmcli.py", line 142, in <module>
    captureIR(args.file)
  File "irmcli.py", line 16, in captureIR
    ir_serial.write("c\r\n")
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/serial/serialposix.py", line 532, in write
    d = to_bytes(data)
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/serial/serialutil.py", line 63, in to_bytes
    raise TypeError('unicode strings are not supported, please encode to bytes: {!r}'.format(seq))
TypeError: unicode strings are not supported, please encode to bytes: 'c\r\n'

となってしまう

irmagician ラズパイ エラー
で検索し

JSONに保存した赤外線データを使って赤外線照射したいのですが、エラーが出てできません。

によれば
python3 だと
“n,%d\r\n” % recNumberはstr型なので提示エラーになる

~.encode()とbyte型に変換するとよい
とのこと
python3 pySerial TypeError: unicode strings are not supported, please encode to bytes:

も参考にするように書いてある

少しわかりにくかったので
ser.write
で検索し

Python3でpyserialを使う

をみると
write() で
文字列の前に
b
をつければOKらしい

:%s/write(“/write(b”/g
で置き換えて実行したが
リモコンの学習ができない

仕方ないので
コードを書き換えるより
ディレクトリ単位で python 環境を構築することに

pyenv-virtualenvでディレクトリ単位のpython環境構築

ラズパイにpyenv・Python3.7.0をインストールしてpyenv-virtualenvで仮想環境の構築!

を参考に

なお pyenv-virtualenv のインストールに関しては
pyenv と pyenv-virtualenv で環境構築

を参考に

 git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

でファイルを取得

sudo vim .bash_profile 

でファイルを開き

最終行に

eval "$(pyenv virtualenv-init -)"

を追記して保存

source ~/.bash_profile

でファイルをリロード

次に仮想環境の構築

cd irmcli/

で irmagician のディレクトリに移動

次に python 2.7.9 をインストール

pyenv install 2.7.9

しかし

ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

となる

エラーを検索

RaspberryPiにpyenvを入れて複数のPython動かすよ

を参考に

sudo apt install -y libssl1.0-dev

Debian 9 Stretchでは、libssl-devは
OpenSSL 1.1.xベースになっているので
あったlibsslを入れろとの事

再度

pyenv install 2.7.9

を実行しインストール成功

pyenv は
global なら全体のバージョンを設定

local なら
カレントディレクトリに反映となるので

pyenv local 2.7.9 

として
irmcli ディレクトリのみ
python を 2.7.9 にする

次に
仮想環境の保存と再構築のため

pyenv exec pip install wheel

で wheel をインストール

freeze コマンドで
requirements ファイルを作成し
wheel ファイルを出力

pyenv exec pip freeze > ~/pyp_list.txt
pyenv exec pip wheel --wheel-dir=~/wheelhouse -r ~/pyp_list.txt

としておく

次に

python --version

で ver 2.7.9 になっているのを確認

curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
python get-pip.py
pip install pyserial
[/shell
で必要なものをインストール


vim irmcli.py

で変更した部分を元に戻しておく

元に戻したら

sudo python irmcli.py -c

で部屋のリモコンの全灯を押し学習させる

sudo python irmcli.py -s -f light_on.json

でファイルへ書き出し

リモコンの消灯を押して照明を消す

sudo python irmcli.py -p -f light_on.json

を実行すると全灯になって照明が点灯する

なお距離は2mでも動作するが
リモコンと異なり
赤外線センサーの向きなどがあっていないと
操作できないので注意

Amazon Echo でラズパイのコマンドを実行

Amazon Echo でラズパイのコマンドを実行

声で部屋の電気のON/OFFをしたい(後編:音声認識しちゃうよ)

AmazonEchoからRaspberryPiのコマンドを実行する(node-red-contrib-amazon-echo)

を参考に

ubuntu のブラウザ
今回は firefox で
http://raspberrypi.local:1880/admin/
へアクセス

すでにログインしているなら数日間は
自動ログインできる

ハンバーガーメニューから
パレットの管理をクリック

ノードを追加 をクリック

node-red-contrib-amazon-echo
で検索

node-red-contrib-amazon-echo

ノードを追加をクリック

追加をクリック

しばらくすると追加されるので
閉じるをクリック

これで入力欄に
amazon echo hub
amazon echo device
が追加される

amazon echo hub をドラッグ&ドロップ

ダブルクリックし
編集画面をだす

Port を 8111 にして
完了をクリック

次に
Amazon Echo Device をドラッグ&ドロップし
灰色の○をクリックして
Amazon Echo Hub とワイヤーをつなげる

Amazon Echo Device をダブルクリックし
設定画面で
Name に任意の名前を入力

今回は テスト として完了をクリック

これでデブロイをクリック

次に
https://alexa.amazon.co.jp/
へアクセスし

スマートホーム > デバイス > 検出
としたが
なぜか追加されない

とりあえず後にして
Node-RED のフローを作成

http://raspberrypi.local:1880/admin/
へアクセス

debug をドラッグ&ドロップすると
msg.payload となるので

これを
テスト
とワイヤーでつなぐ

なお
つなげるところを間違えたら
ワイヤーをクリックし
delete キーで消すことができる

今回はテストと
Amazon Echo Hub をつなげるときに
ワイヤーを間違えて設定したので
これを修正した

つなげることができたら
デブロイをクリック

次に
msg.payload をクリックし
デバッグアイコンをクリック

しかし反応がないため

sudo iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8111

で設定

iptables コマンドについては
iptables – システム管理コマンドの説明 – Linux コマンド集 一覧表

を参考に
ーI オプションでルール追加
–dport は送信先ポート設定
今回は80ポートを送信先にしている
-j で行動の設定
ACCEPTなのでパケットを通している

-A はルールの追加
PREROUTING は
送信先IPをマシン自身のIPへ変換

sudo apt-get install iptables-persistent

でインストール

現在のIpv4ルールを保存しますか?
現在のIpv6ルールを保存しますか?
となるので
はい
を選択

これで

sudo reboot

で再起動後

再度
デバイスを検出すると
Royal Philips Electronics スマートデバイス
として認識された

これで
Amazon Echo に
アレクサ テスト オン
アレクサ テスト つけて
と言っても動作しない

Android の Alexa アプリで見ると
照明として認識されているので

アレクサ 照明 オン
アレクサ 照明 オフ
とすると反応した

これで反応するようにはなったので
次に
Node-RED でのラズパイコマンドを実行

機能のところにある
exec をドラッグ&ドロップ

テストから
exec までをワイヤーでつなぐ

execをダブルクリックし
コマンドに
sh /home/pi/test.sh
として
完了をクリック

デブロイをクリック

次にラズパイで

vim test.sh

でファイルを作成し

if [ $1 = "on" ]
then
    echo "ON" >> /tmp/test.txt
elif [ $1 = "off" ]
then
    echo "OFF" >> /tmp/test.txt
fi

として保存

これで
アレクサ 照明 つけて
とすると
/tmp/test.txt

ON
と書き込まれる

確認したいのなら

cat /tmp/test.txt

とすればファイルの中身を見ることができる

なお
Alexa アプリで
文字化けしていたデバイス名を
テスト
と変更すれば
アレクサ テスト つけて
でも反応するようになった

ラズパイ3で Google カレンダー取得

ラズパイ3で Google カレンダー取得

Google Calenderの予定をPython3から取得する


Raspberry PiでGoogle Calendarの予定を読み上げさせる

Google Calendarの予定に応じてRaspberryPiに処理をさせる(その1)

Raspberry PiとGoogle カレンダでGoogle Homeにゴミの日を教えてもらう


参考に

まずはセットアップ
Google Calendar APIのPython Quickstart

を参考に行う

Enable the Google Calender API
をクリック

どのプラットフォームか聞かれるので
とりあえず Desktop app にして
CREATE をクリック

認証に必要な情報がでるので
DOWNLOAD CLIENTCONFIGURATION
をクリックし
json ファイルをダウンロード

終わったら
DONE をクリック

次にダウンロードしたファイルを
ラズパイ3にコピーする

scp credentials.json  pi@192.168.1.4:/home/pi/

次にラズパイ3で必要なライブラリのインストール

sudo pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

次に認証のためのスクリプトの取得

wget https://raw.githubusercontent.com/gsuitedevs/python-samples/master/calendar/quickstart/quickstart.py

次に認証をブラウザで行うことになるので

【ラズベリーパイ(ラズパイ)】ラズパイをスピーカーにもっとも簡単に接続する方法!

を参考に
VNCで設定を行う

sudo raspi-config

5 Interfacing OPtions を選択

P3 VNC を選択

はい を選択

設定できたら
Finish を選択

./VNC-Viewer-6.20.113-Linux-x64

でVNC Viewer を起動

使い方に関しては
Raspberry Pi(ラズパイ)をSSHとVNC設定してリモート接続してみた!【Windows10】

を参考に

IPアドレスを入力

ユーザ名 pi
パスワードはログインパスワードを入力し
OK をクリック

これでリモートデスクトップが表示されるので
端末アイコンをクリック

python quickstart.py

しかし

Traceback (most recent call last):
  File "quickstart.py", line 20, in <module>
    from googleapiclient.discovery import build
ImportError: No module named googleapiclient.discovery

となってしまう

googleapis /google-api-python-client

を見ると
virtualenv が必要らしい

pip install virtualenv

でインストール

virtualenv google_calender

で仮想環境を作成

source google_calender/bin/activate

で仮想環境を有効化

pip install google-api-python-client

の後に

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

を実行したが

WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))': /simple/pytz/

と同じようにでてくる

仕方がないので
ラズパイ3での認証はやめて
Ubuntu で認証することに

Google Calenderの予定をPython3から取得する

を参考に

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

で必要なライブラリのインストール

Enable the Google Calender API をクリックし
API Console をクリック

これで API の設定画面になるので
OAuth 2.0 クライアントIDの
ダウンロードアイコンをクリックし
ダウンロードしたファイルを
credentials.json
へ変更

あとは

vim quickstart.py

でファイルを作成

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Getting the upcoming 10 events')
    events_result = service.events().list(calendarId='primary', timeMin=now,
                                        maxResults=10, singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])

if __name__ == '__main__':
    main()

で保存

python quickstart.py 

を実行すると認証画面になる

最後のほうで
このアプリは 確認されていません
とでるが

https://eguweb.jp/gas/this-application-has-not-been-confirmed
を参考に
承認作業を行えばOK

これで
token.pickle
が作成されるので

Google カレンダーに予定を追加し

python quickstart.py 

を実行すると
最新10件まで Google カレンダーの予定を取得できる

あとは
token.pickle
credentials.json
をラズパイ3へ scp で転送する

scp token.pickle pi@192.168.1.4:/home/pi/
scp credentials.json  pi@192.168.1.4:/home/pi/

次に
天気予報情報・Googleカレンダーの予定をpythonで取得する方法 on Raspberry Pi/Mac

を参考に
ラズパイ3で

wget https://raw.githubusercontent.com/karaage0703/karaage-echo/master/get_gcal_schedule.py

でファイルを取得

python get_gcal_schedule.py

を実行したけど

Traceback (most recent call last):
  File "get_gcal_schedule.py", line 7, in <module>
    from oauth2client import client
ModuleNotFoundError: No module named 'oauth2client'

となるので
raspberry piでGoogleカレンダー取得スクリプトのセットアップ

を参考に

sudo pip install --upgrade oauth2client --ignore-installed six 

でインストール後

再度実行しても

/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access /home/pi/.credentials/calendar-python-quickstart.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
Traceback (most recent call last):
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/clientsecrets.py", line 121, in _loadfile
    with open(filename, 'r') as fp:
FileNotFoundError: [Errno 2] No such file or directory: 'client_secret.json'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "get_gcal_schedule.py", line 91, in <module>
    get_schedule()
  File "get_gcal_schedule.py", line 60, in get_schedule
    credentials = get_credentials()
  File "get_gcal_schedule.py", line 45, in get_credentials
    flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/client.py", line 2135, in flow_from_clientsecrets
    cache=cache)
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/clientsecrets.py", line 165, in loadfile
    return _loadfile(filename)
  File "/home/pi/.pyenv/versions/3.6.10/lib/python3.6/site-packages/oauth2client/clientsecrets.py", line 125, in _loadfile
    exc.strerror, exc.errno)
oauth2client.clientsecrets.InvalidClientSecretsError: ('Error opening file', 'cl

となる

このため
一度 ubuntu で
google_calender ディレクトリを作成し
ここで作業

別ディレクトリを作成したのは
quickstart.py がすでにあるので
別のファイルを作りたいため

vim quickstart.py

でファイルを作成

from __future__ import print_function
import httplib2
import os

from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage

import datetime

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/calendar-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Google Calendar API Python Quickstart'


def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'calendar-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def main():
    """Shows basic usage of the Google Calendar API.

    Creates a Google Calendar API service object and outputs a list of the next
    10 events on the user's calendar.
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('calendar', 'v3', http=http)

    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Getting the upcoming 10 events')
    eventsResult = service.events().list(
        calendarId='primary', timeMin=now, maxResults=10, singleEvents=True,
        orderBy='startTime').execute()
    events = eventsResult.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])


if __name__ == '__main__':

で保存し

cp ../ダウンロード/client_secret_354559203980-pd3t3vum75cc19ihvj6pgttqasf8npbd.apps.googleusercontent.com.json client_secret.json

でダウンロードしたファイルを
client_secret.json
として保存

あとは

python quickstart.py

を実行すればブラウザが立ち上がり認証画面になる

詳細をクリックし

Project Default Service Account(安全ではないページ)に移動
をクリック

許可をクリック

許可をクリック

これで ubuntu で
calendar-python-quickstart.json
が生成されるので

scp /home/snowpool/.credentials/calendar-python-quickstart.json    pi@192.168.1.4:/home/pi/.credentials/


ラズパイ3のディレクトリにコピー

これでラズパイ3で再度

python get_gcal_schedule.py

を実行すれば

get_gcal_schedule.pyが正常に動作する

あとは予定の読み上げ

Raspberry PiでGoogle Calendarの予定を読み上げさせる

では

python get_gcal_schedule.py | aquestalkpi/AquestalkPi -f - | aplay #pythonの出力結果をaquestalkpiにパイプし、それをさらに、aplayにパイプ

で読み上げていた

aquestalkpi は個人で非営利なら無料らしい
オプションなどについては
それ、ラズパイでつくれるよ——日本語を喋らせる

を参考に
-f オプションで
読み上げるテキストファイルを指定している

sudo bluetoothctl 
connect 6C:56:97:3A:52:98

を実行し Amazon Echo へ接続

ctrl + d で抜けて

jtalk.sh

でファイルを作成し

#!/bin/bash
tempfile=`tempfile`
#option="-m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice \
option="-m /usr/share/hts-voice/mei/mei_normal.htsvoice \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic 
-ow $tempfile"
#echo "$1" | open_jtalk $option
python get_gcal_schedule.py | open_jtalk $option
#aplay -q $tempfile
aplay  -D bluealsa $tempfile
rm $tempfile

として保存

./jtalk.sh

を実行すれば
予定があれば読み上げ
ないのなら
今日の予定はありません
と Amazon Echo で音声が流れるようになる

ラズパイ3にOpenJTalk インストール

ラズパイ3にOpenJTalk インストール

ラズパイ3に喋らせるため
OpenJTalk をインストール

「ラズパイ、音楽かけて」でRaspberry Piにmp3を再生させる


【Raspberry Pi】指定時間にゴミの収集日を音声でお知らせする方法[Open Jtalk+cron]

を参考に

sudo apt-get update

でリポジトリ更新

sudo apt-get install -y open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001

これでインストールして

MMDagent で女性音声の追加

wget --no-check-certificate https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.7/MMDAgent_Example-1.7.zip

wget –no-check-certificate
とすると
SSLのついたサイトへアクセスできる

wgetでこういう時はこうする!!

にオプションについて載っているので参考に

unzip MMDAgent_Example-1.7.zip

で解凍

sudo cp -R ./MMDAgent_Example-1.7/Voice/mei /usr/share/hts-voice/

cp コマンドの -R オプションを調べてみる

意味は
コピー元にディレクトリを指定した場合
再帰的に(サブディレクトリも含めて)コピーする

【 cp 】コマンド――ファイルをコピーする

を参考に

あとはテスト

echo "はじめまして、ラズベリーパイです" | \
open_jtalk -m /usr/share/hts-voice/mei/mei_normal.htsvoice \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic \
-ow voice.wav 

で音声ファイルを作成し

sudo bluetoothctl 
connect 6C:56:97:3A:52:98

を実行し Amazon Echo へ接続

ctrl + d で抜けて

aplay -D bluealsa voice.wav

で喋らせる

これで
はじめまして、ラズベリーパイです
と Amazon Echo から声がでる

もしくは

vim jtalk.sh 

を作成

#!/bin/bash
tempfile=`tempfile`
option="-m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic \
-r 0.7 \
-ow $tempfile"
echo "$1" | open_jtalk $option
#aplay -q $tempfile
aplay  -D bluealsa $tempfile
rm $tempfile

として保存

./jtalk.sh "こんにちは。音声テストです。"

というように
スクリプトの後に”” で囲んでテキストを入力し
それを喋らせる

もともとは
-q オプションででメッセージを表示しないようにする予定だが
音声がでないため
-D オプションで bluealsa を指定するようにしたら
男性の声で
こんにちは。音声テストです
と音声がでるようになった

aplay のオプションについては
aplayのヘルプ/オプション

を参考に

また OpenJTalk のオプションで
-r オプションによりしゃべる速度をコントロールできる

-r 0.7
だとちょっとゆっくりになる

OpenJTalk のオプションについては
Ubuntu Open JTalk その2 – open_jtalkコマンドの説明

を参考に

よく使うものとしては
-m で音声データ指定

-ow で保存するwavファイルの指定

あと
テキストファイルを用意して
OpenJTalk で音声ファイルを作成し
aplay で再生することもできる

vim test.txt

でファイルを作成

今日の予定はイオンで買い物

というように適当に入力し保存

open_jtalk  -m /usr/share/hts-voice/mei/mei_normal.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow text.wav test.txt

で音声ファイルを作成

aplay -D bluealsa text.wav

とすれば
今日の予定はイオンで買い物
と音声がでる

テキストの音声変換に関しては
テキストを音声データに変換してロボットに喋らせる。

も参考に

ラズパイ3に pyaudio インストール

ラズパイ3に pyaudio インストール

sudo pip install pyaudio

を実行すると

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pyaudio
  Downloading https://files.pythonhosted.org/packages/ab/42/b4f04721c5c5bfc196ce156b3c768998ef8c0ae3654ed29ea5020c749a6b/PyAudio-0.2.11.tar.gz
Building wheels for collected packages: pyaudio
  Running setup.py bdist_wheel for pyaudio ... error
  Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-q8X_DO/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/pip-wheel-DpglbX --python-tag cp27:
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-armv7l-2.7
  copying src/pyaudio.py -> build/lib.linux-armv7l-2.7
  running build_ext
  building '_portaudio' extension
  creating build/temp.linux-armv7l-2.7
  creating build/temp.linux-armv7l-2.7/src
  arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-InigCj/python2.7-2.7.16=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/usr/include/python2.7 -c src/_portaudiomodule.c -o build/temp.linux-armv7l-2.7/src/_portaudiomodule.o
  src/_portaudiomodule.c:29:10: fatal error: portaudio.h: そのようなファイルやディレクトリはありません
   #include "portaudio.h"
            ^~~~~~~~~~~~~
  compilation terminated.
  error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1
  
  ----------------------------------------
  Failed building wheel for pyaudio
  Running setup.py clean for pyaudio
Failed to build pyaudio
Installing collected packages: pyaudio
  Running setup.py install for pyaudio ... error
    Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-q8X_DO/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-POjPm0/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-armv7l-2.7
    copying src/pyaudio.py -> build/lib.linux-armv7l-2.7
    running build_ext
    building '_portaudio' extension
    creating build/temp.linux-armv7l-2.7
    creating build/temp.linux-armv7l-2.7/src
    arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-InigCj/python2.7-2.7.16=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/usr/include/python2.7 -c src/_portaudiomodule.c -o build/temp.linux-armv7l-2.7/src/_portaudiomodule.o
    src/_portaudiomodule.c:29:10: fatal error: portaudio.h: そのようなファイルやディレクトリはありません
     #include "portaudio.h"
              ^~~~~~~~~~~~~
    compilation terminated.
    error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1
    
    ----------------------------------------
Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-q8X_DO/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-POjPm0/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-q8X_DO/pyaudio/

というエラーがでる

CentOSにPyenvをインストールしてPython3の開発環境を構築する

を参考に

pip list

を実行すると

Package    Version
---------- -------
pip        18.1   
setuptools 40.6.2 
You are using pip version 18.1, however version 20.2b1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

となり
バージョンが古いらしい

pip install --upgrade pip

でアップデート

再度実行してもエラーになるので

sudo python --version

としたら

Python 2.7.16

となっていたので

 sudo pyenv global 3.6.10

としたところ

sudo: pyenv: コマンドが見つかりません

となってしまうので

PyenvによるPython3.x環境構築(CentOS, Ubuntu)

を参考に

sudo visudo

でファイルを編集する

なお nano エディタで操作することになるので
使い方に関しては
GNU nanoを使いこなす

を参考に

Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

の部分を

#Defaults       secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults        env_keep += "PATH"
Defaults        env_keep += "PYENV_ROOT"

として
ctrl + s で上書き保存し
ctrl + x で終了

これで

sudo pyenv global 3.6.10

とすれば

sudo python --version

を実行したときに

Python 3.6.10

と変更されるようになった

次に

sudo pip install pyaudio

を実行してみたが

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pyaudio
  Downloading PyAudio-0.2.11.tar.gz (37 kB)
Using legacy setup.py install for pyaudio, since package 'wheel' is not installed.
Installing collected packages: pyaudio
    Running setup.py install for pyaudio ... error
    ERROR: Command errored out with exit status 1:
     command: /home/pi/.pyenv/versions/3.6.10/bin/python3.6 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-_p6von58/pyaudio/setup.py'"'"'; __file__='"'"'/tmp/pip-install-_p6von58/pyaudio/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-eikj46h2/install-record.txt --single-version-externally-managed --compile --install-headers /home/pi/.pyenv/versions/3.6.10/include/python3.6m/pyaudio
         cwd: /tmp/pip-install-_p6von58/pyaudio/
    Complete output (16 lines):
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-armv7l-3.6
    copying src/pyaudio.py -> build/lib.linux-armv7l-3.6
    running build_ext
    building '_portaudio' extension
    creating build/temp.linux-armv7l-3.6
    creating build/temp.linux-armv7l-3.6/src
    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/home/pi/.pyenv/versions/3.6.10/include/python3.6m -c src/_portaudiomodule.c -o build/temp.linux-armv7l-3.6/src/_portaudiomodule.o
    src/_portaudiomodule.c:29:10: fatal error: portaudio.h: そのようなファイルやディレクトリはありません
     #include "portaudio.h"
              ^~~~~~~~~~~~~
    compilation terminated.
    error: command 'gcc' failed with exit status 1
    ----------------------------------------
ERROR: Command errored out with exit status 1: /home/pi/.pyenv/versions/3.6.10/bin/python3.6 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-_p6von58/pyaudio/setup.py'"'"'; __file__='"'"'/tmp/pip-install-_p6von58/pyaudio/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-eikj46h2/install-record.txt --single-version-externally-managed --compile --install-headers /home/pi/.pyenv/versions/3.6.10/include/python3.6m/pyaudio Check the logs for full command output.

となってしまう

このため

Pip install PyAudio

を参考に

sudo apt-get install python-dev portaudio19-dev

でパッケージをインストールし

sudo pip install pyaudio

でインストール

sudo bluetoothctl 
connect 6C:56:97:3A:52:98

を実行し Amazon Echo へ接続

ctrl + d で抜けて

vim test.py

でファイルを作成

import wave
import pyaudio

def play(wav_file):

    try:
        wf = wave.open(wav_file, "rb")

    except FileNotFoundError:
        print("No such file " + wav_file)
        return

    p = pyaudio.PyAudio()

    ## Bluetoothスピーカーの情報を取得
    for device_index in range(p.get_device_count()):
        device = p.get_device_info_by_index(device_index)
        if device["name"] == "bluealsa":
            bluetooth_device = device_index

    ## Bluetoothスピーカーを指定してストリームオープン
    stream = p.open(
        format=p.get_format_from_width(wf.getsampwidth()),
        channels=wf.getnchannels(),
        rate=wf.getframerate(),
        output=True,
        output_device_index=bluetooth_device
    )

    # 再生
    chunk_size = 1024
    data = wf.readframes(chunk_size)

    while len(data) > 0:
        stream.write(data)
        data = wf.readframes(chunk_size)

    stream.stop_stream()
    stream.close()
    p.terminate()


if __name__ == "__main__":

    play("/usr/share/sounds/alsa/Front_Center.wav")

として保存

音声再生サンプルコードは
Amazon EchoをRaspberry PiのBluetoothスピーカーとして利用する

のものを使わせていただきました

あとは

python test.py 

を実行し
Amazon Echo から
フロント センター
と聞こえれば
python による音声出力ができることが確認できる

ラズパイ3へ pyenv インストール

ラズパイ3へ pyenv インストール

Raspberry PiにpyenvをインストールしてPythonをバージョン管理

を参考に
pyenv をインストール

これができれば
Amazon EchoをRaspberry PiのBluetoothスピーカーとして利用する

を参考に
pyaudioモジュールを使うことで
Pythonで Amazon Echo に音声出力できる

なお、コマンドの実行結果が最新OSの場合異なっている

uname -a

結果

Linux raspberrypi 4.19.118-v7+ #1311 SMP Mon Apr 27 14:21:24 BST 2020 armv7l GNU/Linux
lsb_release -a

結果

No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

lsb_release コマンドは
ディストーションのバージョンを確認するコマンド

詳しくは
ディストリビューションのバージョンなどを確認する・lsb_releaseコマンド †

を参考に

まず必要なパッケージのインストール

sudo apt update
sudo apt upgrade
sudo apt install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev

次に Github から pyenv を取得

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

次にパスを通す

sudo vim ~/.bash_profile

でファイルを作成し開く

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

を追記して保存

設定反映のため

source ~/.bash_profile

で再読み込み

bashrc と bash_profile の違いについては
.bash_profileと.bashrcのまとめ

を参考に

.bash_profile
ログイン時に実行される
環境変数を設定

.bashrc
シェル起動時に実行される
エイリアス
シェル関数
コマンドラインの補完
を設定

なお
source コマンドは
ファイルに書かれた内容を実行するコマンド

これについては
Linux — source コマンドは何をしているのか > 実は環境をリロードするためのものではない

を参考に

pyenv のインストールができているなら

pyenv --version

でバージョンを表示できる

今回は

pyenv 1.2.18-19-gcf81e5a0

という結果になった

pyenv install --list

でインストールできるバージョンの一覧が表示される

今回は 3.6.10をインストール

これは
Amazon EchoをRaspberry PiのBluetoothスピーカーとして利用する

で使用しているバージョンが 3.6.10
であるのと
pyaudio モジュールが3.7 でインストールできない可能性があるため

現状だと

python --version

の結果が

Python 2.7.16
python3 --version

の結果が

Python 3.7.3

となっている

pyenv install 3.6.10

でインストール

pyenv global 3.6.10

でバージョンを変更

もし元に戻したいのなら

pyenv global system

とすればOK

ラズパイ3B+マイクとスピーカー設定その2

ラズパイ3B+マイクとスピーカー設定その2

Amazon echo Dot をスピーカーに設定できたので
次にマイクの設定

今回は以前購入したものを利用

ラズパイ3にはマイクを差し込むところがないため
USBオーディオ変換アダプタを使用

なお mic 側にマイクを差し込まないと認識しなかった

USBで接続したら

arecord -l

を実行

**** ハードウェアデバイス CAPTURE のリスト ****
カード 1: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

となり
このときのサブデバイス番号を覚えておく

arecord -D plughw:1 myvoice.wav

で録音開始

ctrl + c を押すまで録音される

^Cシグナル 割り込み で中断...
arecord: pcm_read:2145: 読込エラー: システムコール割り込み

となるが録音はされる

次に

aplay -D bluealsa myvoice.wav

を実行すれば録音した声が聞こえる

ただし、今回利用したパーツだとノイズが入っている