読者です 読者をやめる 読者になる 読者になる

Raspberry Pi Julius導入

Juliusのインストール

ダウンロード

wget -O julius-4.3.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz'

解凍

tar zxvf julius-4.3.1.tar.gz

インストール

cd julius-4.3.1/
./configure
make
sudo make install

Juliusディクテーションキット・文法認識キットのダウンロード

ダウンロード

wget -O dictation-kit-v4.3.1-linux.tgz 'http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz'
wget -O grammar-kit-v4.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F51159%2Fgrammar-kit-v4.1.tar.gz'

解凍

tar zxvf dictation-kit-v4.3.1-linux.tgz
tar zxvf grammar-kit-v4.1

まとめる

mkdir julius-kits
mv dictation-kit-v4.3.1-linux julius-kits
mv grammar-kit-v4.1 julius-kits 

マイクセットアップ

ライブラリのインストール

sudo apt-get install alsa-utils

マイクの優先度確認,マイク名を覚えておく

sudo cat /proc/asound/modules

マイクの優先度変更

sudo nano /etc/modprobe.d/alsa-base.conf

ドライバモジュールを組み込む

sudo modprobe snd-pcm-oss

辞書の作成

nano julius-kits/word.yomi

途中...

ECHONETLiteパーサ

コード

# coding:utf8
# python3.4.4

def el_parser(code):
    try:
        dict_ = {}

        dict_['ehd1'] = code[0:2]
        dict_['ehd2'] = code[2:4]
        dict_['tid'] = code[4:8]
        dict_['seoj'] = code[8:14]
        dict_['deoj'] = code[14:20]
        dict_['esv'] = code[20:22]
        dict_['opc'] = code[22:24]

        edata = code[24:]

        #opcで記されている分だけkeyを作ってやって振り分ける
        for i in range(int(dict_['opc'], 16)):
            for key in ['epc', 'pdc', 'edt']:
                if key is 'edt':
                    pdc_ = int(dict_['pdc'+str(i)], 16)*2

                    if pdc_ is 0:
                        break

                    d = edata[:pdc_]
                    dict_[key+str(i)] = d
                    edata = edata[pdc_:]

                else:
                    d = edata[:2]
                    dict_[key+str(i)] = d
                    edata = edata[2:]

        if len(edata) is not 0:
            raise

    #ELに準拠したコードでなければFalseを返す
    except:
        return False

    else:
        return dict_

使い方

# coding:utf8
# python3.4.4

from el import el_parser
from pprint import pprint #出力を見やすくするために

code1 = "1081000005ff010ef0016201d600" #ELコード
code2 = "elko-dozyanaiyatu123456789@@" #ELコードじゃないやつ

pprint(el_parser(code1))
print('----------------------------')
pprint(el_parser(code2))

出力結果

{'deoj': '0ef001',
 'ehd1': '10',
 'ehd2': '81',
 'epc0': 'd6',
 'esv': '62',
 'opc': '01',
 'pdc0': '00',
 'seoj': '05ff01',
 'tid': '0000'}
----------------------------
False

Python Tips

文字列を16進数にエンコード・デコード

from binascii import hexlify, unhexlify

# str -> hex
def str2hex(str_):
    return hexlify(str_.encode('utf8'))

# hex -> str
def hex2str(hex_):
    return unhexlify(hex_).decode('utf8')

UNIXタイムスタンプの取得

#from datetime import datetime

#datetime型を渡すとタイムスタンプで返す デフォルトは現在時刻
#def get_timestamp(datetime_=datetime.now()):
#    return round(datetime_.timestamp())

上のやり方は間違い。

from datetime import datetime

#datetime型を渡すとタイムスタンプで返す デフォルトは現在時刻
def get_timestamp(datetime_=None):
    if datetime_ is None:
        datetime_ = datetime.now()
    return round(datetime_.timestamp())

ローカルIPアドレスの取得

from socket import socket, AF_INET, SOCK_DGRAM
from contextlib import closing

def get_ip():
    with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
        sock.connect(('8.8.8.8', 80))
        ip = sock.getsockname()[0]
    return ip

UDP関連

・ip: 自分のローカルIPアドレス
・addr: 送り先のIPアドレス
・bufsizeはいつも4096で設定してる

from socket import *
from contextlib import closing

#ユニキャスト送信
def send(addr, port, data):
    with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
        sock.sendto(data, (addr, port))
    return 1

#ユニキャスト受信
def recv(ip, port, bufsize=4096):
    with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
        sock.bind((ip, port))
        data, addr = sock.recvfrom(bufsize)
    return [data, addr[0]]


#マルチキャスト送信
def multi_send(ip, group_addr, port, data):
    with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
        sock.setsockopt(IPPROTO_IP, IP_MULTICAST_IF, inet_aton(ip))
        sock.sendto(data, (group_addr, port))
    return 1

#マルチキャスト受信
def multi_recv(ip, group_addr, port, bufsize=4096):
    with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
        sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.bind(('', port))
        sock.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP,
                        inet_aton(group_addr)+inet_aton(ip))

        data, addr = sock.recvfrom(bufsize)
    return [data, addr[0]]

マルチスレッド処理

・マルチスレッドで動かすときによく使う関数たち

from threading import Thread, Event, active_count

#マルチスレッドで動かしたい関数
def function(arg):
    print(arg)

thread = Thread(target=function, args=['ヽ(*゚д゚)ノ',])


thread.start()#マルチスレッド開始

thread.join()#スレッドが死ぬまで待機 タイムアウトを浮動小数点数で設定できる

thread_state = thread.is_alive()#スレッドが生きていればTrueを返す


flag = Event()#スレッド間のフラグ処理に使う

flag.set()#flagにTrueをセット

flag.clear()#flagにFalseをセット

flag.wait()#flagがTrueになるまで待機 タイムアウトを浮動小数点数で設定できる

flag_state = flag.is_set()#flagがTrueだったらTrueを返す


active_count()#生存中のスレッド数を返す

OpenWeatherMapから天気情報を取得

・requestsをインストールしとく
・appidはOpenWeatherMapに登録して入手
・公式のAPI一覧に詳しく載ってる(https://openweathermap.org/api)
・無料で得られる情報は2時間ごとの更新
・1分間で60回までリクエストできる

import requests

#緯度経度から現在の天気情報を取得
def get_current_weatherdata_latlon(appid, lat, lon):
    params = {'appid': appid, 'lat': lat, 'lon': lon}
    res = requests.get('http://api.openweathermap.org/data/2.5/weather', params)
    return res.json()

#緯度経度から天気予報情報を取得(5日間分、3時間毎)
def get_forecast_weatherdata_latlon(appid, lat, lon):
    params = {'appid': appid, 'lat': lat, 'lon': lon}
    res = requests.get('http://api.openweathermap.org/data/2.5/forecast', params)
    return res.json()

TwitterAPI関連

・requestsとrequests_oauthlibをインストールしとく
oauth認証の各キーはtwitterデベロッパーに登録して取得。
・各APIごとに呼び出し制限回数は異なる。制限は15分でリセットされる。
・公式のAPI一覧に詳しく載ってる。(https://dev.twitter.com/docs)
・とりあえずよく使うものだけ

import requests
from requests_oauthlib import OAuth1

oauth_keys = {}
oauth_keys['consumerkey'] = '***************'
oauth_keys['consumersecret'] = '***************'
oauth_keys['accesstoken'] = '***************'
oauth_keys['accesstokensecret'] = '***************'

class TwitterCliant:
    def __init__(self, oauth_keys):
        self.auth = OAuth1(oauth_keys['consumerkey'], oauth_keys['consumersecret'],
                           oauth_keys['accesstoken'], oauth_keys['accesstokensecret'])

    #ツイートを上げる
    def update(self, text):
        url = "https://api.twitter.com/1.1/statuses/update.json"
        data = {"status": text}
        res = requests.post(url, data=data, auth=self.auth)
        return res.json()

    #ツイートIDを指定してリプライ
    def reply(self, id_, text):
        url = "https://api.twitter.com/1.1/statuses/update.json"
        data = {"in_reply_to_status_id": id_, "status": text}
        res = requests.post(url, data=data, auth=self.auth)
        return res.json()

    #ツイートIDを指定してリツイート
    def retweet(self, id_):
        url = "https://api.twitter.com/1.1/statuses/retweet/%s.json"%id_
        res = requests.post(url, auth=self.auth)
        return res.json()

    #ツイートIDを指定してツイート削除
    def delete(self, id_):
        url = "https://api.twitter.com/1.1/statuses/destroy/%s.json"%id_
        res = requests.post(url, auth=self.auth)
        return res.json()

    #ホームタイムラインの取得
    def timeline(self, count):
        url = "https://api.twitter.com/1.1/statuses/home_timeline.json"
        params = {"count": count}
        res = requests.get(url, params=params, auth=self.auth)
        return res.json()

    #キーワードでツイート検索(キーワードはリストで渡す)
    def search(self, keys, count):
        url = "https://api.twitter.com/1.1/search/tweets.json"
        query = ' AND '.join(keys)
        params = {"q": query, "count": count}
        res = requests.get(url, params=params, auth=self.auth)
        return res.json()

ECHONETLite通信周り

コード

# coding:utf8
# python3.4.4

from socket import *
from time import sleep
from contextlib import closing
from threading import Thread
from binascii import hexlify, unhexlify

class ELCliant:
    def __init__(self):
        self.ip = self.get_ip()
        self.el_port = 3610
        self.el_group = '224.0.23.0'
        self.bufsize = 4096

        self.flag = True
        self.receiver_isalive = False

    #ローカルIPの取得
    def get_ip(self):
        with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
            sock.connect(('8.8.8.8', 80))
            ip = sock.getsockname()[0]
        return ip

    # str -> hex
    def str2hex(self, str_):
        return hexlify(str_.encode('utf8'))

    # hex -> str
    def hex2str(self, hex_):
        return unhexlify(hex_).decode('utf8')

    #ユニキャスト送信
    def send(self, addr, code):
        b_code = self.str2hex(code)
        with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
            sock.sendto(b_code, (addr, self.el_port))
        return 1

    #マルチキャスト送信
    def multi_send(self, code):
        b_code = self.str2hex(code)
        with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
            sock.setsockopt(IPPROTO_IP, IP_MULTICAST_IF, inet_aton(self.ip))
            sock.sendto(b_code , (self.el_group, self.el_port))
        return 1


    #マルチキャスト受信 受け取ったデータをon_dataに投げる
    def multi_recv(self):
        with closing(socket(AF_INET, SOCK_DGRAM)) as sock:
            sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
            sock.bind(('', self.el_port))
            sock.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP,
                            inet_aton(self.el_group)+inet_aton(self.ip))

            while self.flag:
                b_data, addr = sock.recvfrom(self.bufsize)
                data = self.hex2str(b_data)

                if data == '':
                    break

                self.on_data([addr[0], data])

    #受信開始
    def start(self):
        self.flag = True
        self.receiver = Thread(target=self.multi_recv)
        self.receiver.start()
        self.receiver_isalive = True
        sleep(0.001)
        return 1

    #受信停止
    def stop(self):
        self.flag = False
        self.send('127.0.0.1', '')#multi_recv内のループを判定処理まで進ませる
        self.receiver.join()
        self.receiver_isalive = False
        return 1

    #データを受信すると実行される ここをオーバライド
    def on_data(self, data):
        print(data)
        return 1

使い方

from el import ELCliant

class MyCliant(ELCliant):
    def on_data(self, data):
        print('ヽ(*゚д゚)ノ<ジュシン!')
        print(data)

code = "1081000005ff010ef0016201d600"

EL = MyCliant()
EL.start()
EL.multi_send(code)
EL.stop()

出力結果

ヽ(*゚д゚)ノ<ジュシン!
['192.168.10.10', '1081000005ff010ef0016201d600']

Raspberry Pi SSH設定

環境

・クライアント(192.168.10.10):Ubuntu
・サーバー(192.168.10.50):Raspbian
・サーバー側ではOpenSSHが動作中 ・公開鍵認証にする

クライアント側

接続の確認

ssh pi@192.168.10.50

公開鍵・秘密鍵の生成

ssh-keygen

公開鍵をサーバー側に転送

scp ~/.ssh/id_rsa.pub pi@192.168.10.50:

パーミッションの変更

sudo chmod 700 ~/.ssh

サーバー側

公開鍵設定

cat id_rsa.pub >> authorized_keys

mkdir .ssh
mv authorized_keys /home/pi/.ssh

パーミッションの変更

sudo chmod 600 /home/pi/.ssh/authorized_keys

sshd_config」の編集

sudo nano /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile /home/pi/.ssh/authorized_keys

SSHを再起動

sudo /etc/init.d/ssh restart

クライアント側

「.ssh/config」の編集

Host raspi
    HostName 192.168.10.50
    User pi
    IdentityFile ~/.ssh/id_rsa

確認

ssh raspi

Raspberry Pi WiFi設定

SSID,PASSWARDの登録

「/etc/wpa_supplicant/wpa_supplicant.conf」にSSIDとPASSWARDを登録する

sudo wpa_passphrase SSID PASSWORD >> /etc/wpa_supplicant/wpa_supplicant.conf

「Permission denied」と表示される場合

sudo chmod 666 /etc/wpa_supplicant/wpa_supplicant.conf

ネットワーク設定

「/etc/network/interfaces」を編集する。

自動でIPアドレスを割り振ってもらう場合

auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet dhcp

wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

IPアドレスを指定する場合

auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0
iface wlan0 inet static
address 192.168.10.50 #Raspberry Piに割り振るIPアドレス
netmask 255.255.255.0
gateway 192.168.10.1

wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

接続の確認

ifconfig wlan0