🐬

【WebApp】家から出るまで鳴り止まない目覚ましアプリを作った

2024/09/29に公開

今回は自作Webアプリの解説を行います。
本アプリの主な機能は目覚まし勉強管理です。



0. ページ紹介

最初にアプリのページを紹介します。

・ページ(それぞれホーム、当日の予定、今後の予定)

アプリの詳細を以下で紹介していきます。

1. 課題

アプリを作るに至った課題が、大きく2つあります。

1.1 起きられない

私は、低血圧なこともあり朝早く起きることが苦手です。

ですが、
・テスト期間、早朝に勉強する
・朝、学校や会社に行く前に運動する
など、朝の時間を有効活用したいと考えていました。

1.2 集中できない

もう一つ、勉強などに集中できないという課題もあり、こちらも解決したいと考えていました。
(正確には勉強途中で気が散って、効率が落ちてしまうことが課題でした。)

2.  機能要求

課題を解決するために、2つの主な機能を考えました。

2.1 目覚まし

背景

起きられないという課題に対処するために、目覚まし機能を作ることにしました。

"目覚まし"の機能は"目を覚まさせること"です。
しかし、
・二度寝
・動画を見てしまう
など、目が覚めても行動できないこともあります。

色々検証したところ、目を覚まして、家から出た後は問題なく勉強や運動を行うことが出来ることが分かりました。
そこで"目を覚ます"ことではなく、"家から出る"ことを目的とした目覚まし機能を作ることにしました。

機能要求

・設定した時間にアラームが鳴る
・アラームを停止させるときに位置情報を参照し、自宅から20m以上の時のみ停止する
・アラームは、スヌーズのように繰り返し行う

2.2 スケジュール

背景

集中できないという課題に対処するために、スケジューラー機能を作ることにしました。

ハードルとして
・勉強を始めること
・勉強中に他のことをしないこと
があり、これらを解決するために、勉強の開始時にアラームが鳴り、"作業中はアプリ画面から離れない"ようなスケジューラー機能を作ることにしました。

機能要求

・設定した時間にアラームが鳴る(目覚ましと共通)
・作業中は、アプリから離れると再度アラームが鳴り、アプリに戻るまで止まらない。

3. 技術スタック

3.1 使用言語、フレームワーク

バックエンド: Python, Flask
フロントエンド: HTML, CSS, JS
データベース: SQLite
サーバー: EC2(AWS)

・選定理由
バックエンド: 研究で使用していたPythonを使用
フロントエンド: 初めてのWebAppのため、基礎的なHTMLとCSS、JSを使用
データベース: 簡易的アプリのためSQLite
サーバー: コスト面から1年間の無料クレジットが付与されていたAWSを使用

3.2 アーキテクチャ

・全体

4. 使い方

ユーザ目線の機能は主に以下の4つです。
・アラームの登録
・実行開始
・アラーム停止
・その日のアラームを無効化

それぞれについて説明していきます。

  1. アラーム登録
    当日の予定を直接編集、もしくは今後の予定を編集します。
    今後の予定は平休日もしくは曜日で設定することができ、朝5時に当日のスケジュールとして更新されます。

    起床時間の指定: 右のボックスに"起きる"もしくは"起床"と入力します。
    作業時間の指定: 右のボックスに"作業"と入力します。

  2. 実行開始
    スケジュール開始ボタンを押すと、指定した時間にアラームが鳴るようになります。

  3. アラーム停止
    アラーム停止ボタンを押すと、アラームが停止します。
    (予定が"起床"の場合、自宅との距離が20m以上の場合のみアラームが停止します)

  4. その日のアラームを無効化
    何か予定があり、スケジュールを停止したい場合は"今日のスケジュールを停止"というボタンを押すと、その日のスケジュールが停止されます。

5. 実装

5.1 スケジュール登録

HTMLから渡されたスケジュールの内容を、Pythonで受け取りDBのschedule Tabelに記録します。

# スケジュール登録
con = sqlite3.connect(DATABASE)
con.execute('INSERT INTO schedule_table VALUES(?,?)',[id,schedule_item])

ユーザーがページ訪れた際には、逆にPython側でDBからスケジュールをHTMLに渡し、Flaskを用いて表示します。

# スケジュール表示
<tr {% if schedule_dic.action_time == closest_schedule_time %}class="closest_schedule_time"{% endif %}>
  <td class="text-center">{{ schedule_dic.action_time }}</td>
  <td>{{ schedule_dic.action }}</td>
</tr>

5.2 実行開始

スケジュール開始ボタンを押すと、実行日時を取得してAPSchedulerオブジェクトに設定し、予定の時間にアラームが鳴るように予約します。
※APSchedulerは、予約実行や定期実行ができるpythonのライブラリです。

# start_call関数を指定の時間に実行する
task_scheduler.add_job_date(start_call, args=(new_job_id,), run_time=schedule_time_dict)

5.3 アラーム停止

アラーム停止ボタンを押すと、APSchedulerオブジェクトからjobを削除し、アラームを停止します。
予定が"起床"の時は現在地の緯度経度を取得し、自宅の緯度経度から距離を算出し20m以上の場合、アラームを停止します。

# アラーム停止
if now_loc:
    distance = cal_distance(home_loc['lati'],home_loc['longi'],now_loc['lati'],now_loc['longi'])
    if distance >= 0.02: #km (20m)
        task_scheduler.remove_job('call')

5.4 その日のアラームを停止

同様に距離を計算し、20m以上の場合は存在するAPSchedulerオブジェクトを全て削除します。

5.5 位置情報の取得

現在はicloudを利用して位置情報を取得しています。
今後、webブラウザから位置情報を取得できるようにする予定です。

# 位置情報の取得
async def get_location(api, timeout=60, interval=5):
    for _ in range(timeout // interval):
        auth_1 = api.devices[3].location()
        if auth_1:
            return auth_1
        await asyncio.sleep(interval)
    return None

ICLOUD_ADDRESS = os.getenv('ICLOUD_ADDRESS')
ICLOUD_PASS = os.getenv('ICLOUD_PASS')
api = PyiCloudService(ICLOUD_ADDRESS, ICLOUD_PASS)

loc = asyncio.run(get_location(api))

5.6 アラーム

Twilioの音声通話サービスもしくはLINE Notifyによる通知を使用しています。
どちらも内容の編集が可能で、好きな内容で通話やテキストの送信が可能です。

・Twilio
https://www.twilio.com/en-us
・LINE API
https://notify-bot.line.me/en/

5.7 作業監視

予定が"作業"の時、バックエンドでは30秒後にアラームを鳴らすAPSchedulerを開始します。
そしてユーザーがアプリを開いている間、HTML側からは20秒毎に信号がPython側に送られ、このSchedulerを停止させると同時に次のSchedulerを開始します。

・イメージ図
HTMLからの信号は、上のSchedulerを止めると同時に下のSchedulerを開始します。

つまり、アプリから離れると信号が途切れ、30秒後にアラームが鳴るようになっています。



以上が主な機能の実装です。

6. 効果

使用した結果、ほぼ100%早起きすることに成功しました。
また、作業中も他のアプリを使用しないようになり、休日はコンスタントに10時間以上勉強できるようになりました。

ゆっくり眠りたい時は前日に時間を遅く設定したり、作業を中断する時は当日のアラームを停止したりと計画通りに休み、動くことができるようになり、「やりたいのに怠けてしまった」ということがとても少なくなりました。

7. まとめと今後の展望

今回は自作した目覚ましアプリについて紹介しました。

現在は個人用アプリのため限定公開ですが、同じ悩みを持つ人も多いと思うので、今後はmysqlやReactなど、技術スタックを更新し、新しく公開用アプリとして開発したいと考えています。

紹介は以上になります。
最後まで読んでいただきありがとうございました。

※業務関係でページを確認したいという場合は、DM等で教えていただければURLを共有します。

Discussion