技術を磨くだいぱんまん

散歩とインターネットが大好きなシステムエンジニア。暮らし、おでかけ、テクノロジーについて書いています。

その日の運勢がわかる「Raspberry Pi星占い」はじめました

f:id:donchan922:20170611090804p:plain

こんにちは、だいぱんまん(@donchan922)です。

Raspberry Piとスイッチを使ってなにか電子工作してみたいなと思っていたところ妻から

その日の星占いをLINEで通知してよ

と具体的に言われたので、スイッチを押したらその日の運勢をLINEで通知する仕組みを作ることにしました。あとから気づいたんですが、この要望ならスイッチを使う必要はなく、スケジュール化して毎日決まった時間に通知するようにすればよかったですね。スイッチのバカ。

完成形がこちら


この通知を射手座の妻にしたところ、「なんで私が11位やねん」と怒られました。そんなん俺に言われても知らんやん……

どうやって実現するの?

以下の処理の流れで実現します。

  1. スイッチが押されたことを検知する
  2. 占いAPIを利用してその日の占いデータを取得する
  3. LINE Notifyを利用して占い結果をLINE通知する

1については、Raspberry PiのGPIOを利用すれば簡単に検知できますね。GPIOについては以下記事でわかりやすくまとめています。

電子工作初心者がRaspberry PiのGPIOについて調べてみた - 技術を磨くだいぱんまん

2については、そもそも占いのデータを取得できるAPIなんてあるんかいなと思っていたらありました。しかも無料で。ということで以下占いAPIを利用することにしました。

Web ad Fortune 無料版 API - 占いAPI(システム)をかんたん導入

ちなみに上記の占いAPIを無料で使用するための使用条件は、「商用でないこと」とサイト上に以下2つのリンクを貼ることです。


3については、HTTP POSTを使って簡単にLINEメッセージを送れるLine Notifyを利用しました。

準備するもの一覧

まずは以下のものを用意しましょう。

Raspberry Pi

前提として、Raspberry Piのセットアップが完了しているものとします。セットアップに必要な機器および手順は以下の記事でまとめています。

Raspberry Pi 3にRASPBIAN JESSIE WITH PIXELをSSH経由でセットアップする方法 - 技術を磨くだいぱんまん

ジャンパワイヤ(メスーオス)

2本使います。

実装手順

LINE Notifyの設定を行う

f:id:donchan922:20170610205125p:plain
まずはLine Notifyのサイトで、「ログイン」を選択します。その後ログイン画面でLINEのID、パスワードを入力し、Line Notifyにログインします。


f:id:donchan922:20170610205128p:plain
画面右上のログイン名をクリックし、「マイページ」を選択します。


f:id:donchan922:20170610205132p:plain
「トークンを発行する」を選択します。


f:id:donchan922:20170610205137p:plain
以下情報を入力し、「発行する」ボタンを選択します。

  • トークン名:通知の際に表示される名前
  • トークルーム:通知するトークルーム

トークルームについては、事前に作成しておいたRaspberry Pi通知用の夫婦専用トークルーム「ラズパイ」に設定しました。ちなみに自分のみに通知する場合は「1:1でLINE Notifyから通知を受け取る」を選択します。自分以外の誰か1人(例. 妻)を選択することはできないようです。


f:id:donchan922:20170610205145p:plain
発行されたトークンをメモしておきます。このページを閉じると二度とトークンが参照できないので注意です。


f:id:donchan922:20170610205825p:plain
続いてスマホのLINEを開き、さきほど選択したトークルームに「Line Notify」を招待します。


f:id:donchan922:20170610205830p:plain
以下が確認できればLine Notifyの招待完了です。

  • トークルームの人数が増えていること
  • 「Line Notifyが参加しました。」

最後に以下コマンドを入力し、Line Notifyからトークルーム宛に通知がくるか確認しましょう。ACCESS_TOKENは、さきほどメモしておいたトークンと置き換えてください。

curl -X POST -H 'Authorization: Bearer ACCESS_TOKEN' -F "message=hoge" https://notify-api.line.me/api/notify

コードを実装する

Python3で書きました。

# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
from datetime import datetime
import requests
from time import sleep

# 占いたい星座
SIGN = '射手座'

# 占い結果を取得する
def getHoroscope(sign):
    # 本日日付取得
    today = datetime.now().strftime("%Y/%m/%d")
    # 本日の占い結果を取得するWEPAPI先
    url = 'http://api.jugemkey.jp/api/horoscope/free/' + today
    # 占い結果取得
    horoscope = requests.get(url)
    # 占い結果をJSON形式に変換
    json = horoscope.json()
    # JSONのパース
    purse = json['horoscope'][today]

    # 占いメッセージ作成
    for i in purse:
        if i['sign'] == sign:
            message = ''
            message += '今日の' + i['sign'] + 'の運勢は' + str(i['rank']) + '位です。'
            message += i['content']
            message += 'ラッキーアイテムは' + i['item'] + 'です。'
            message += 'ラッキーカラーは' + i['color'] + 'です。'
            return message

# 占い結果をLine Notifyで通知する
def postLine(message):
    url = 'https://notify-api.line.me/api/notify'
    headers = {
        # ACCESS_TOKENは自身のトークンと置き換えてください
        'Authorization': 'Bearer ACCESS_TOKEN'
    }
    data = [
        ('message', message)
    ]
    requests.post(url=url, headers=headers, data=data)

GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
    while True:
        if GPIO.input(21) == GPIO.LOW:
            # 星占い通知処理実行
            message = getHoroscope(SIGN)
            postLine(message)
        sleep(0.02)

except KeyboardInterrupt:
    pass

GPIO.cleanup()

GPIO.setmode……以降は、以下のサイトが大変参考になりました。

タクトスイッチの入力待受処理を無限ループ化することで、スイッチが押されるたびに星占い通知を行うようにしています。sleep(0.02)をはさむことでCPU使用率が100%になることを防いでいます。こちらの環境では処理実行中はCPU使用率0.3%で推移しています。

今回はこのコードをhoroscope.pyとして保存しておきます。

配線する

f:id:donchan922:20170611093553p:plain
配線はシンプルです。21ピン(GPIO番号)からタクトスイッチにつなげ、抵抗をはさんで、最後はグランドにつないでいます。

いざ処理実行!

まずは以下コマンドでプログラムを実行しておきます。

$ python3 horoscope.py

あとはタクトスイッチを押すだけ。押すたびに、Line Notifyで設定したトークルームにその日の星占い結果が届きます。

まとめ

Raspberry Pi星占いの完成です(明日は射手座の運勢が1位でありますように……)。