14
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Qiitaの「いいね」メーターを作る

Last updated at Posted at 2017-11-05

#はじめに
ESP-WROOM-32ってWiFiにつながるんだから、もっと役に立ちそう。
単体で情報取得してLEDでも点灯させようかな。
でも、天気予報に応じて色が変わる傘立てとかあったような。
じゃあ、QiitaAPIを使ってみよう!
そして、「いいね」を取得してみよう!
#やりたいこと
「いいね」メーターによる投稿状況の可視化で、目標達成へのモチベーションを上げる。
#やり方
1.ESP-WROOM-32をWiFiにつなぐ
2.Qiita APIを使って情報を取得
3.いいね状況に応じてメーターに反映する
##完成イメージ
system.png
##詳細ルール
1.「いいね」状況をQiita APIを使用して15分ごとに確認する
2.メーターは__100__「いいね」をMAX(これは自分の目標に合わせる)
3.新着LEDで新着「いいね」があった場合に点灯する
4.新着LEDはESP-WROOM-32のタッチセンサへのタッチで消灯する

#用意するもの

  • ESP-WROOM-32(ESP32-DevKitC)
  • バーグラフLED : いいね目標値への達成度表示用
  • LED : 新着いいね用
  • 抵抗 : LED抵抗用

タッチセンサはESP-WROOM-32に内蔵されている

#作る
##接続する
回路はあまり得意ではないので、チップの寿命を縮めているかもしれない。
Evernote Snapshot 20171105 185343.png

完成!
qmeter.png
##プログラムを作る
WebアクセスやJSONなどはC言語で使いにくいため、MicroPythonを使用した。これはいい。
Qiita APIは「いいね」を直接取得することはできない。そのため投稿からその数を取得する。
投稿を取得すると、ESP-WROOM-32ではメモリが不足したため工夫が必要だった。
###ソースコード
ソースコード全体はgithubにおいた。
####WiFiに接続する
SSIDとパスワードを指定してWiFiに接続する。

def connect_wifi(ssid, passkey, timeout=10):
    wifi = network.WLAN(network.STA_IF)
    if wifi.isconnected():
        print('already Connected. skip')
        return wifi
    else:
        wifi.active(True)
        wifi.connect(ssid, passkey)
        while not wifi.isconnected() and timeout > 0:
            print('.')
            utime.sleep(1)
            timeout -= 1

    if wifi.isconnected():
        print('Connected')
        return wifi
    else:
        print('Connection failed!')
        return null

####WebAPIを使う
urequestsを使用し、HTTP GETを行なっている。
投稿を一度に取得すると、ESP-WROOM-32上のMicroPythonではメモリが足りなくなった。
そのため、get_item_countで投稿数を取得し、get_likes_countで1投稿ずつ「いいね」の数を取得している。
1投稿ずつでもメモリが足りなくなるため、delgc.collect()で使用しなくなった変数を解放している。

def get_items_count():
    token = 'set_your_token'
    headers = {
            'content-type'  : 'application/json',
            'charset'       : 'utf-8',
            'Authorization' : 'Bearer ' + token
            }
    url = 'https://qiita.com/api/v2/authenticated_user'
    response = urequests.get(url, headers=headers)
    json = response.json()
    count = int(json["items_count"])
    del token
    del headers
    del url
    del response
    del json
    gc.collect()
    
    return count

def get_likes_count(num):
    token = 'set_your_token'
    headers = {
            'content-type'  : 'application/json',
            'charset'       : 'utf-8',
            'Authorization' : 'Bearer ' + token
            }

    u1 = 'https://qiita.com/api/v2/authenticated_user/items?page='
    u2 = str(num)
    u3 = '&per_page=1'
    url = u1 + u2 + u3

    del token
    del u1
    del u2
    del u3
    gc.collect()

    response = urequests.get(url, headers=headers)
    pattern = r'"likes_count":[0-9]+'
    matchOB = ure.search(pattern, response.text)

    if not matchOB:
        sys.exit(0)

    likes_str = matchOB.group(0)
    likes_str = likes_str.split(':')
    count = int(likes_str[1])

    del headers
    del pattern
    del url
    del response
    del matchOB
    del likes_str
    gc.collect()

    return count 

####JSONをParseする
ujsonを使用したかったがメモリが足りず。。。
文字列を解析し、いいね数を取得する方針とした。

response = urequests.get(url, headers=headers)
    pattern = r'"likes_count":[0-9]+'
    matchOB = ure.search(pattern, response.text)

    if not matchOB:
        sys.exit(0)

    likes_str = matchOB.group(0)
    likes_str = likes_str.split(':')
    count = int(likes_str[1])

####バーグラフLEDを制御する
達成度に応じて、つけるLEDを増やしていく。

def set_led_level(level):
    pin12 = machine.Pin(12) 
    pin14 = machine.Pin(14) 
    pin27 = machine.Pin(27) 
    pin26 = machine.Pin(26) 
    pin25 = machine.Pin(25) 
    pin33 = machine.Pin(33) 
    pin32 = machine.Pin(32) 
    pin5 = machine.Pin(5) 
    pin18 = machine.Pin(18) 
    pin19 = machine.Pin(19) 

    if level >= 10:
        pin12.value(1)
    
    if level >= 20:
        pin14.value(1)

    if level >= 30:
        pin27.value(1)

    if level >= 40:
        pin26.value(1)

    if level >= 50:
        pin25.value(1)

    if level >= 60:
        pin33.value(1)

    if level >= 70:
        pin32.value(1)

    if level >= 80:
        pin5.value(1)

    if level >= 90:
        pin18.value(1)

    if level >= 100:
        pin19.value(1)

####新着LEDを点灯/消灯する
GPIO21に新着LEDを接続しており、その制御をする。

def set_arrivals_led_on():
    pin = machine.Pin(21) 
    pin.value(1)

def set_arrivals_led_off():
    pin = machine.Pin(21) 
    pin.value(0)

####「いいね」状況をLEDに反映する
目標値を100として今の達成度合いをバーグラフLEDに反映させる。
また、前回取得時から「いいね」が増加している場合は新着LEDを点灯させる。

def update_likes_led():
    global prev_likes_count

    items_count = get_items_count()

    likes_count = 0
    for num in range(1, items_count+1):
        likes_count += get_likes_count(num)

    print(likes_count)

    target = 100
    rate = (likes_count/target)*100
    set_led_level(int(rate))   
    
    if (likes_count > prev_likes_count) and (prev_likes_count > 0) :
        set_arrivals_led_on()

    prev_likes_count = likes_count

####タッチセンサ入力を取得する
タッチセンサを使用する方法は以下である。
タッチで数値が下がるため閾値(適当)を設けてタッチ判定を行なっている。
割り込み処理のやり方が分からなかったため、ポーリングにしている。

tp = machine.TouchPad(machine.Pin(13))
while True:
    utime.sleep(0.1)
    value = tp.read()
    if value < 400:
        print('touched')
        set_arrivals_led_off()

####15分毎に状況を確認する
タイマー割り込みを使用している。
900000msec(15分)ごとにcallback関数が呼ばれるように設定する。
callback関数はupdate_likes_ledが呼ばれる。

t0 = machine.Timer(0)
t0.init(period=900000, mode=machine.Timer.PERIODIC, callback=intr_handler_timer0)

#テスト
##いいね達成度メーター
いいね状況が分かる!
現在、58いいねだから、取得と表示が成功しているようだ。
meter_led.png
##新着LED
新着LEDの点灯/消灯は新しく「いいね」がつかないので確認できなかった。
この投稿で確認できたらなぁ

#最後に
サイト見れば済む話だけどね。

#参考サイト
techtutorialsx
micropython on ESP32 でぽちっとな
いっぺーちゃんの いろいろやってみよ~

14
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?