Mac でロケーションごとの気温を表示する

2021年2月1日

ロケーションごとの気温を表示する

前に GeekTool でデスクトップに現在の気温を表示するスクリプトを公開した。

🔗 【Mac】現在の気温をデスクトップに | 林檎コンピュータ

これを書き直したいとずっと思ってたんだけど、あまりいいきっかけを見出せずにいた。
 というところに、天気予報 – ウェザーニュースという素晴しいサイトを見つけた。
 こちらのサイトさんは、URL に現在地の座標を噛ませることで、今いる場所の天気と気温を教えてくれるのである。

iPhone のコンパスを開くと、緯度、経度、高度を表示してくれる。
 同じように Mac でも緯度と経度を取得できるはず。
 取得できれば、ウェザーニュースさんで現在地の天気と気温を取得できることになり、すなわち MacBook Air をどこへ持っていっても、その場所の気温を表示できることになる。

Mac でジオロケーションを取得する

Mac で緯度と経度の座標を得る簡単な方法は、マップ.app を使うことだろう。どこかの地点をクリックし、ポップアップを表示する。右肩あたりの「 … 」メニューに、「座標をコピー」という項目がある。
 たとえば新宿歌舞伎町の「ゴジラヘッド」は、「35.695012, 139.701867」という位置にあるらしい。

マップ.appによる座標の取得

これはこれでわかりやすいが、最終的に GeekTool で表示したいので、シェルスクリプトの形になるものがいい。ターミナルで現在の座標を出せないか調べたら、そういうプログラムがちゃんと作られていた。

🔗 GitHub – robmathers/WhereAmI: A quick command line tool for OS X to get your geographic coordinates using the CoreLocation framework.

引数なしで、「whereami」というコマンドを打ちこむと、緯度、経度、精度、タイムスタンプの 4 行を返してくれる。

whereamiの動作

これを使って、30 分とか一時間ごとに座標を調べ、天候のデータを取得するのがいいかもしれない。
 と、思ったが、筆者の環境だと今ひとつ動作が安定しない。Apple シリコンの Mac だからかもしれない。

lua スクリプト

他になにかないか、と捜したら、身近なところにあった。
 筆者がやたら推す Hammerspoon にも、緯度と経度を出力してくれる関数があったのである。
 さらに、Hammerspoon は wifi の切り替わりも検知してくれる。
 家の wifi から外の wifi に切り替わった時に緯度と経度を出力する、というやり方がスマートではなかろうか。Mac は位置情報を wifi の情報から求めているらしいし。

なお、下記のスクリプトを動かす場合、Hammerspoon に位置情報サービスの許可を与える必要がある(システム環境設定>セキュリティとプライバシー>プライバシー>位置情報サービス、に Hammerspoon を追加する)。

Hammerspoonに位置情報サービスの許可を与える

また、今回は「書類」フォルダに「weather」というフォルダを設け、作業場とすることにした。

📝 init.lua

wifiWatcher = nil
function ssidChanged()
    local loc = hs.location.get()
    if loc then
        local ido = loc['latitude']
        local keido = loc['longitude']
        local f = io.open(os.getenv("HOME").."/Documents/weather/loc.txt", "w")
        f:write(ido..'/'..keido)
        f:close()
    end
end

wifiWatcher = hs.wifi.watcher.new(ssidChanged)
wifiWatcher:start()

Hammerspoon の Getting Started というページに wifi event を扱った一節があり、わかりやすい。
 英語だけど、Google Chrome の翻訳や DeepL翻訳を使えば素直に読める。

どうであれ、これで wifi が切り替わった時、座標をテキストにして weather フォルダに出力してくれるはず。
 そのテキストに基づいて気象データを取得すればいい。
 シェルスクリプトは下記のようなものを考えてみた。
 せっかく weather フォルダという作業場を作ったので、そこに現在地も出力する。

シェルスクリプト

📝 weather.sh

#!/bin/zsh

loc=$(cat $HOME'/Documents/weather/loc.txt')

html=$(curl -Ss 'https://weathernews.jp/onebox/'"$loc"'/&temp=c&lang=ja')

weather=$(echo "$html" | grep -A 2 'weather-now__ul' | sed -e 's/天気//' -e 's/気温//' -e 's/<[^>]*>//g' -e 's/ //g' -e '/^$/d')

address=$(echo "$html" | grep '<title>' | sed -e 's/<title>【一番当たる】//' -e 's/の最新天気(1時間・今日明日・週間) - ウェザーニュース<\/title>//' -e 's/ //g')

tenki=$(echo $weather | sed -n 1p)
kion=$(echo $weather | sed -n 2p)

echo $address > $HOME/Documents/weather/address.txt
echo $tenki $kion

GeekTool の command は、

sh /Users/ユーザ名/パス/weather.sh

ということになる。更新のインターバルは 3600 とした。
 現在地の表示は、

cat $HOME/Documents/weather/address.txt

とした。

GeekToolでの表示

これでいいはず、なんだけど、なんかピンとこない。
 というのも、筆者は自分の住んでいる町からほとんど出ないからだ。
 MacBook Air を閉じたまま仕事場へいくと、なんかぬるっと wifi が切り替わっていて、Hammerspoon が切り替えの瞬間をうまく検知できたのかわからない。
 いちおう、print('wifi 切り替わったよ')などと加えてみると、Hammerspoon のコンソールには表示されるのである。
 というか、田舎すぎて wifi が少なく、なかなか確認が出来ない。
 隣村まで車でいって確かめようとしたら、wifi どころか携帯の電波さえなかなか捕まらねー有様。でもたぶん、これでいけると思うんだよな。

あるいは 30 分や一時間ごとに座標を吐き出し続けるほうがいいかもしれない。
 その場合は init.lua をこう書き直す。

hs.timer.doEvery(1800, function()
    local loc = hs.location.get()
    if loc then
        local ido = loc['latitude']
        local keido = loc['longitude']
        local f = io.open(os.getenv("HOME").."/Documents/weather/loc.txt", "w")
        f:write(ido..'/'..keido)
        f:close()
    end
end)

hs.timer.doEvery(秒数 fn()なので、この場合 1800 秒、30 分ごとに更新することになる。けっこう粗いというか、細やかな表示は期待できない。かといって一分おきに更新するようなもんでもないだろうし。

まぁでも、そこまでして正確な気温知りたいか、という話もあるからな。
 きょう寒いけど何度くらい? みたいな、ちょっとした好奇心を満たせればそれでいいんである。大都会で頑張るヤングのライフスタイルは知らんけど、こちとらはイカ臭いおじさんしかいない群馬の山奥なんであって、そもそも MacBook Air なんか持ち歩かねーわ、という話だ。
 だいたい、通知センターに天気ってあるからね。
 気温も表示されっからね。
 ということで、今回はここであきらめます。すみません。