Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

Chrome拡張で毎時0分にチャイムを鳴らす

仕事に集中しすぎていませんか?

久々に投稿のえんどうです。
弊社では現在もテレワーク可能でほとんどの人が自宅から仕事しています。自宅でひとりで働いていると時間を忘れてしまうこともあります。
たまに時間を確認できるようにチャイムを鳴らしたいと思いました。

要件

  • 仕事の日だけ仕事をしている間は鳴らしたい
  • 月ー金でも休みの日はある
  • たまには残業やシフト勤務もあるかも
  • チャイムを止める操作はしたくない
  • 毎日チャイムを有効にする操作はしたくない
  • 時報(時間をしゃべってくれるやつ)はいらない
  • 新たにアプリを入れたくない

実現方法を考える

動作する日や時間帯については仕事中=PCが起動しているのでPCの電源が入っている間は動くようにすればよさそうです。
そしてPCでいつも動いているものはブラウザ(Chrome)です。

Chrome拡張機能を作ってアラームを鳴らす

できました。展開する場所はどこでも構いませんが、Chromeに読み込んだ後も参照されるので誤って削除しないところに置きます。

Chromeウェブストアには上げてませんのでChromeの拡張機能画面で「デベロッパーモード」をONにして「パッケージ化されていない拡張機能を読み込む」をクリックして上記zipを展開した場所を選択します。または、拡張機能画面にフォルダをドロップしてもOKです。

このようなカッコ悪い拡張機能のカードが表示されていればOKです。設定画面はありません。
コードや音声ファイルを変更したときは更新ボタンをクリックします。

仕組み

Chrome拡張機能のアラームAPIを利用しています。

アラームの管理はChromeが行い必要な時にイベントとして呼ばれます。イベントはServiceWorkerがListenしますがServiceWorkerからは音声再生できません。
音声再生するためにオフスクリーンドキュメントを作成し、そこで play-sound.html を表示し(実際には表示されない)再生します。

音を変えたい

このファイルを変更します。

// pages/play-sound.js
chrome.runtime.onMessage.addListener((message) => __awaiter(this, void 0, void 0, function* () {
    if (message.target !== "offscreen-document")
        return;
    const audio = new Audio("chime1.mp3");
    yield audio.play();
}));

const audio = new Audio("chime1.mp3"); の部分のファイル名を変更します。
pages/chime1.mp3 を別のファイルに差し替えても変更できます。
変更を反映するため拡張機能を更新してください。

なお、zipファイルに含めた音声ファイルは下記のWebサイトより利用させていただきました。

時間間隔を変えたい

// service-worker.js
chrome.runtime.onInstalled.addListener(() => __awaiter(this, void 0, void 0, function* () {
    yield chrome.alarms.clearAll();
    const now = new Date();
    // now.getHours() + 1 = 24 になってもうまくやってくれるので気にしない
    const when = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours() + 1);
    yield chrome.alarms.create('each-hour', {
        periodInMinutes: 60,
        when: when.getTime(),
    });
}));

when はalarmの起動時刻を指定するため作成したコードでは次の0分の時間を作っています。5分間隔にしたい場合は次の5分区切りの時間(12:35:00など)を計算して when に設定する必要があります。
しかし過去の日付を指定しても即時1回だけイベントを発火したあと periodInMinutes の間隔でalermが発火するので、次のように変更すると5分間隔になります。
ほとんどの場合、 when は変えずに、 periodInMinutes だけを変えれば動くはずです。

const when = new Date('2020-01-01 00:00:00');
yield chrome.alarms.create('each-hour', {
    periodInMinutes: 5,
    when: when.getTime(),
});

過去の日付を指定すると即時1回だけイベントを発火するのですが、この分のイベントは次の部分のif文ではじかれるためalarmが鳴ることはありません。

// service-worker.js
chrome.alarms.onAlarm.addListener((alarm) => __awaiter(this, void 0, void 0, function* () {
    // sleepなどでalarm処理できなかった分は1回分だけfireするため、時間を比較して無視する
    // 通常はスケジュールから数ミリ秒で来るので多めに見積もって10秒差以上を無視
    if (new Date().getTime() - alarm.scheduledTime < 10000) {
        yield chime();
    }
}));

似ているもの

  • Chime: 音声で時間を読み上げて知らせてくれます。

作った後に思ったんですけど…

Windowsタスク スケジューラで設定するだけでできるんじゃないか?という気がとてもします。
「Chrome拡張機能を作ってみた」ということで良しとします。してください。
Macだってこの拡張機能を入れるだけで動くし!

他に検討した案

Google Nest Hubに発話してもらう

こうすると平日の10時に「ポーン」としゃべりますが…

  • この設定を10時から19時まで作る必要がある
    • この業界の人にとっては耐え難い屈辱
  • もちろん祝日でも有給休暇でも動く

時報機能がある時計

お金で解決するパターン。
いわゆる鳩時計です。夜は鳴らさないようにもできるようですがさすがに有給休暇や祝日の設定は無理そうです。

Windows標準アプリの「クロック」

再通知までの時間を1時間にすることで1時間ごとのアラームを作ります。

初期設定ではPCが起動してなければ鳴りませんので「仕事中のみ」の条件はクリアできそうです。

試しに設定してみるとアラーム音と同時に通知が出ました。アラームを止めるためには「再通知」をクリックする必要があります。「閉じる」をクリックしてしまうと以降その日は鳴らなそうです。
しかも「再通知」をクリックしてから1時間後となるのでずれてきます。


BPSアドベントカレンダー2024


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。