鹿児島で暮らしていると、降灰は天気の一部です。天気予報では桜島上空の風向きが伝えられ、洗濯物を外に干すか、窓を開けるか、車をどこに停めるか——灰は日々の小さな判断に関わってきます。
ただ、既存の降灰情報は、正直に言って使いづらいものでした。噴火があったこと、灰がどの方角へ流れるかは分かる。でも、いちばん知りたいのは方角ではありません。「それで結局、うちに降るのか」です。方角の情報から自分の家に降るかどうかを読み解くのは、毎回ちょっとした頭の体操でした。
だったら、その読み解きを道具にやらせればいい。それが灰なうの始まりです。
「方角」を「あなたの地点」に変換する
灰なうの仕組みは単純です。気象庁は桜島の降灰予報を発表しています。灰なうはその予報データと、あなたが登録した地点(自宅・職場など最大3つ)を突き合わせて、登録地点が降灰の予想エリアに入ったときだけ通知します。
いちばんこだわったのは、この「地点ピンポイント判定」です。「桜島の北東方向に降灰のおそれ」ではなく、「あなたの登録した地点に降灰のおそれ」まで変換して届ける。情報としては同じものでも、読み解く手間がゼロになると、道具としてまったく別物になります。
中で起きていることも、そう複雑ではありません。灰なうは5分おきに、気象庁が公開している防災情報XMLのフィードを見にいきます。桜島の降灰予報が新しく出ていたら、そのXMLを取ってきて、中から降灰の予想エリアを取り出します。
エリアは、符号付きの緯度と経度を「/」で区切って並べた、一本の長い文字列で入っています。+緯度+経度/+緯度+経度/… という形です。これを座標の配列に直すと、地図の上に描ける多角形になります。
あとは、あなたの登録地点がその多角形の内側にあるかどうかを判定するだけです。使っているのは ray casting(レイキャスティング)という古典的な方法で、判定したい点から一方向へ半直線を伸ばし、多角形の辺と何回交差するかを数えます。奇数回なら内側、偶数回なら外側。この判定の前に、まず多角形をすっぽり囲む長方形を作って、そこから外れている点を先に落としています。辺を一本ずつ調べるより、四つの数字を比べるほうが圧倒的に速いからです。
通知の送信そのものも自前で書きました。Web Push は、ブラウザの通知サーバーへ暗号化した本文を届ける仕組みで、送り主の身元を示す署名と、本文の暗号化の両方が要ります。既製のライブラリを使えば数行で済むところですが、灰なうが動いている Cloudflare Workers は Node.js ではないので、その多くがそのままでは動きません。結局、Workers に組み込みの暗号機能だけを使い、仕様書を読みながら書くことになりました。
通知の量を選べるようにした時期もありました。少しの灰でも知りたい人がいれば、多量のときだけ知りたい人もいるだろう、と考えたからです。これは後から取り下げています(後述)。ただ、毎回鳴る通知はいずれ無視される通知だという考え方そのものは、いまも変わっていません。
アカウント登録は不要で、ブラウザの通知を許可するだけで使えます(iPhoneはホーム画面への追加が必要です)。
気象庁の降灰予報XMLには、出来事を識別する ID と、第何報かを示す番号が付いています。ところが桜島の場合、実データを見るとID は常に「506」(桜島の火山番号)、報番号は常に「1」でした。つまり、この2つでは個々の噴火を区別できません。
同じ通知を二度送らないためには「どの噴火に対する予報か」を見分ける必要があるので、灰なうは代わりに予報の対象時刻(速報・詳細では噴火が起きた時刻)を鍵として使っています。ここを ID に戻すと、別々の噴火に対する予報が「もう送った」と判定されて、丸ごと消えます。
降灰予報には、3種類ある
ここまで「降灰予報」とひとことで書いてきましたが、実は3種類あります。そして、この違いが灰なうの作りのほとんどを決めています。
| 定時 | 速報 | 詳細 | |
|---|---|---|---|
| いつ出るか | 噴火警報が出ている火山に、3時間ごと。噴火とは関係なく出続ける | 噴火の直後 | 噴火のあと、少し遅れて |
| 何を言っているか | 「もし今日噴火したら、この範囲に灰が降ります」という想定 | 「噴火しました。この範囲に灰が降ります」 | 速報の内容に、灰の量が加わる |
| 灰の量 | なし | なし | あり(多量/やや多量/少量) |
| 灰なうの扱い | 原則、通知しない(例外は後述)。地図には出す | 通知する | 通知する |
いちばん大事なのは、定時は「噴火する前から出ている」予報だということです。桜島は噴火警戒レベル3が常態なので、定時予報はほぼ常に発表されています。「灰が降る」と言っているのではなく、「もし噴火が起きたとしたら、その灰はこちらへ流れます」と言っている。風向きの予報に近いものです。
詳細予報には、もうひとつ細かい罠がありました。定時も詳細も、予報は時間帯ごとにエリアを持っています。ところが、定時が「0〜3時間」「3〜6時間」と互い違いに進んでいくのに対して、詳細はすべての時間帯が噴火時刻から始まり、終わりだけが1時間後、2時間後……と伸びていく累積の形になっています。この違いを知らずにそのまま扱うと、6時間かけて灰が届く遠くの地点まで「いま降っています」として警告してしまう。取り込むときに、増分の区間へ直しています。
いちばん難しかったのは、鳴らさない判断
作ってみて分かったのは、この道具の仕事の大半が「どう鳴らすか」ではなく、「どういうときに鳴らさないか」だということでした。
1週間で19回噴火して、速報が出たのは1回だけ
最初の設計では、降灰予報の速報と詳細だけを見ていました。噴火したらそれが出るはずだ、と思っていたからです。
実際に記録を取ってみると、違いました。2026年8月2日から9日までの1週間で、桜島の噴火に関する火山観測報は19報。それに対して、降灰予報の速報が出たのは1件だけでした。速報と詳細は気象庁の発表基準に達したときにだけ出るもので、桜島の噴火の大半はそこに届きません(定時予報のほうは、この間も3時間おきに出続けています)。
つまり、速報と詳細だけを見ていると、噴火の大半で灰なうは一言も喋らないことになる。
そこで、噴火そのものを知らせる「噴火に関する火山観測報」も見るようにしました。ところがこの観測報には、降灰の予想エリアが入っていません。噴火した時刻、現象、噴煙の高さ、流れていく方向は分かりますが、多角形は付いてこない。
方角から扇形を自分で描く、という手も考えましたが、やめました。半径をどう決めても根拠がないし、気象庁がすでに多角形という形で答えを出しているのに、それより粗い自作の図形で通知を送るのは筋が悪い。
代わりに取ったのは、「定時予報の多角形」と「噴火が実際に起きた事実」を掛け合わせるという方法です。定時予報は「もし噴火が起きたら、この範囲に降ります」と言っている。そこへ観測報が「噴火が起きました」と伝えてくる。二つを合わせれば「その想定が現実になった」と読める。気象庁が計算したエリアをそのまま使えるので、精度を落とさずに済みます。
ただし、噴火から30分以上が経った報では通知しません。手遅れの知らせは、無いほうがましだからです。
定時予報では、噴石の範囲を使わない
降灰予報には、灰の範囲だけでなく小さな噴石が飛ぶ範囲も入っています。噴石は灰と違って身の危険に直結するので、ここに地点が入ったときは夜間の設定も飛び越えて「頑丈な建物の中など安全な場所へ」を送るようにしました。
これを定時予報にも同じように適用したら、まずいことになりました。
定時予報の噴石の範囲は、想定される最大規模をもとに描かれています。桜島の場合、火口から西へ12kmまで伸びていて、鹿児島市の中心部がすっぽり入ります。一方で灰のほうの扇は、まったく別の方向を向いていることがある。実際に、降灰は南へ40km、噴石は南西へ3km、という予報を見たことがあります。
レベル3が常態の火山で、「もし噴火したら」の想定を根拠に、市の中心部にいる全員へ避難を促す通知を送る。これは誤報です。いまは定時予報のときだけ噴石の範囲を判定から外し、実際の噴火に対応する速報・詳細では従来どおり扱っています。
画面のほうも同じように外しました。片方だけ直すと、「画面は風下だと言っているのに通知は来ない」という食い違いが起きます。
風下に入った、その瞬間だけ
定時予報は通知しない、と表に書きましたが、ひとつだけ例外があります。登録地点が想定範囲の外から中へ変わったときです。
風向きは変わります。朝は風下でなかった家が、昼には風下に入る。それを知らせるのには意味がある。でも、定時予報は3時間ごとに出るので、範囲に入っているたびに通知していたら、風下に居座る日は1日に最大8通届くことになります。8通目には、もう誰も見ていません。
だから、外から中へ変わった瞬間だけ送ることにしました。いま風下にいる地点の一覧を持っておいて、新しい定時予報が来るたびに前回と比べる。新しく入った地点にだけ「風下に入りました」を送り、すでに入っていた地点には何もしません。
この方式には、始めるときの落とし穴がありました。一覧が空の状態で最初の予報を処理すると、全員が「新しく入った」ことになって一斉に鳴ります。空の一覧は「まだ一度も記録していない」のか「いま誰も風下にいない」のか区別がつかないからです。最初の一回は記録だけして通知しない、という印を別に持たせて回避しています。
予報が取り消されたとき、誰に知らせるか
気象庁の予報には、取り消しがあります。発表したあとで「あれは無かったことに」と訂正が出る。
困ったのは、取消の予報には降灰の情報が入っていないことでした。範囲も量も書かれていないので、「誰の地点が対象だったか」を計算し直せません。
取った方法は、逆から辿ることです。灰なうは「誰のどの地点へ、どの予報で通知を送ったか」を送信の履歴として持っています。取消が届いたら、その履歴から同じ噴火の通知を受け取った人を引いて、その人たちにだけ「取り消されました」を送る。通知のまとめ方も元の通知と揃えてあるので、スマホの通知トレイでは元の通知が「取り消されました」に置き換わります。
ここで一度、雑な引き方をして事故りかけました。履歴の鍵は「予報の種別・対象時刻・報番号」の組み合わせなのですが、種別を「どれでもいい」にして時刻だけで引くと、たまたま同じ時刻の別種別の通知まで拾ってしまう。定時予報の対象時刻はちょうどの時刻なので、噴火が正時に起きた回で衝突しえます。取り消されるのは速報と詳細だけなので、いまはその2つに限って引いています。
通知が鳴る条件、鳴らない条件
ここまでは作り手の話です。使う側から見て「どういうときに鳴って、どういうときに鳴らないのか」を、まとめておきます。アプリの画面には書ききれていない部分です。
| 出来事 | 鳴るか |
|---|---|
| 噴火(爆発、または噴煙1500m以上) | 鳴る |
| それ以外の噴火 | 火口から20km以内の地点で鳴る |
| 降灰予報(速報)で範囲に入った | 鳴る |
| 降灰予報(詳細)で範囲に入った | 鳴る |
| 降灰予報(定時)の範囲に入った | 外から中へ変わった瞬間だけ鳴る |
| 小さな噴石の範囲に入った(速報・詳細) | 鳴る |
| 予報が取り消された | 元の通知を受け取っていれば鳴る |
| 夜間(22時〜7時。設定した場合) | 多量だけ鳴る。見送った分は翌朝1通にまとめる |
夜間(22時〜7時)の設定を有効にすると、その時間帯は多量の灰だけに絞ります。ただし、絞って見送った分は捨てずに取っておいて、翌朝7時に1通のまとめとして届けます。夜中に鳴らさないことと、朝起きたときに前の晩に何があったか分かること。その両方を成立させたかったからです。
登録した地点の座標は、小数第4位(およそ10m)に丸めて保存しています。降灰予報のエリアはもともと約2km四方のグリッド由来なので、それより細かい精度は判定に要りません。要らない精度は持たない、というのが一番安全なやり方だと考えています。
選べるようにした設定を、2つ取り下げた話
もともとは「通知する灰の量」と「噴火の通知の範囲」を選べるようにしていました。どちらも後から廃止しています。作ったときの想定が、実際のデータと合っていませんでした。
「多量のときだけ通知する」
灰の量(多量・やや多量・少量)が入っているのは詳細予報だけです。定時にも速報にも、噴火の観測報にも入っていません。量が分からないものを「多量です」として送るわけにはいかないので、この設定を選んだ人には詳細予報しか届かない作りになっていました。
ところが桜島では、その詳細予報が出ないことのほうが多い。つまりこの設定は「多量だけ受け取る」ではなく、実質「ほとんど何も受け取らない」でした。灰が降るかを伝えるための道具として逆を向いていたので、やめました。いまは登録地点が降灰の予想エリアに入ったら通知する、の一本です。
「爆発、または噴煙1500m以上の噴火だけ」
こちらは噴火の通知の既定でした。桜島は噴火が頻繁で、1週間で19報という数字がそのまま通知の数になったら道具として使い物にならない、という判断です。これも取り下げました。理由が3つあります。
ひとつ目。気象庁は桜島では、ごく小規模な噴火をそもそも発表していません。月ごとの解説資料の脚注に「噴火のうち、爆発もしくは噴煙量が中量以上(概ね噴煙の高さが火口縁上 1,000m以上)の噴火の回数を計数しています」「基準に達しない噴火は、ごく小規模な噴火として噴火回数に含めていません」とあります。灰なうに届いた時点ですでに絞られていたわけで、そこからさらに1500mで切ると、1,000〜1,500mの噴火だけを落としていたことになります。
ふたつ目。その規模でも灰は降ります。2026年7月の桜島は噴火39回のうち爆発は1回でしたが、同じ月に鹿児島地方気象台(火口から約10km)では12日、灰が観測されています。
みっつ目。噴煙の高さは、曇っていると低く出ます。雲に入ってしまうと、そこまでの高さしか記録されないからです。8月25日の爆発は「火口上400m(雲に入る)」でした。高さで線を引くと、規模ではなく天気で通知が消えることになります。
いまは、爆発か、雲に邪魔されずに1500m以上と確認できた噴火なら、降灰の予想エリア全体へ送ります。それ以外は火口から20km以内の地点に限って送ります。
この20kmは自分で決めた数字ではなく、鹿児島県の降灰量観測に合わせました。県は62か所の観測点を「噴火口より20km以内/以遠」で分けています。爆発が無く噴煙が1,500m級までだった月(2026年1月と2025年10月)の記録を見ると、20km以内では風下側で1平方メートルあたり数十グラムから355グラムの灰が観測されているのに、20km以遠は29か所すべてが0〜4グラム、ほぼ検出の下限でした。自分で線を引くより、すでに現地で引かれている線に乗るほうが確かだと考えています。
まだ試行錯誤中の表現
いま悩んでいるのが、「登録地点にすでに灰が降り始めていて、この先さらに降る可能性がある」ときの伝え方です。予報が「これから降るかもしれない」なのか、「すでに降っていて、まだ続くかもしれない」なのかは、体感としてはまったく違う情報です。ひとつの通知でどちらの状態も分かりやすく伝えるにはどう表現すればいいか、正直まだこれという答えが出せていません。使ってくれる人の声を見ながら、これからも調整していくつもりです。
正直に書いておきたい限界
灰なうは万能ではありません。
噴火に対応して出る速報・詳細は、噴火が発生したあとに発表されるため、噴火から通知まで10〜20分ほどのタイムラグがあります。また、予報は約2km四方のグリッド単位なので、「ピンポイント」といっても限界があります。予想エリアに入っても降らないことも、その逆もあります。
だから灰なうは、防災の道具ではなく、暮らしの判断の道具だと考えています。命に関わる判断は、必ず気象庁や自治体の公式発表に従ってください。灰なうが引き受けるのは「洗濯物、どうしようかな」のほうです。
私自身がいちばん使っているのは、まさにその「洗濯物を外に干すか」の判断です。干す前にひと目、通知が来ていないかを確かめる。それくらいの、ささやかな道具です。
桜島は、これからも噴火し続けます。灰と付き合う暮らしが少しでも軽くなるように、これからも手を入れていくつもりです。