みずぴー日記

人間の再起動ボタンはハワイのビーチにある

🖥43インチモニタ

43インチの4Kモニタを購入した。 体験がいい。

f:id:mzp:20181021214220p:plain

🛒購入したもの

🍖焼き肉寿司

@izmさんに誘われて焼き肉寿司を食べにいった。

f:id:mzp:20181021222449p:plain

うまいうまいと食べてたら、テンションがあがって4Kモニタを注文してしまった。 もともと欲しいと思ってたので、「ボク使っていますが最高ですよ」と言われて背中を押されてしまった。

@izmさんはiPhoneXSを買っていた。

📦設置

数日後に届いた。 「二人以上で作業しろ」と書いてあった。そんなこと言われても困る。

そこまで重くなかったので、見なかったことにして一人で取り出した。

机に置けないかなと思って挑戦したが、まったく置ける気配がなかった。さらにドライバーがなかったので台の取り付けもできなかった。

とりあえず壁に立て掛けて、MacBookProをつないだ。Netflix言の葉の庭を再生したら最高になった。

🔧モニタアーム

最高だけど床に置いたままにはできないのでモニタアームを注文した。ドライバーのセットも買った。

到着したあと説明書を見ながらアダプタを取り付けたり、モニタアームをデスクに装着したりした。2回くらい取り付け方向をミスったがなんとかなった。

f:id:mzp:20181021215811p:plain

怖かったので、ベッドの位置をずらして、万が一落下しても頭にあたらないようにした。

🔌HDMI変換アダプタ

使ってたHDMI変換アダプタが4K解像度に対応しておらずフルHD解像度しかでなかった。

フルHDはつらいので変換アダプタを注文した。コンセントまで電源ケーブルが届かなかったのでOAタップも買った。あわせ買い対象商品のため、金額調整のために洗濯用洗剤も買った。

これで4K解像度で出力できるようになったので、最高になった。

f:id:mzp:20181021222337p:plain

ばしばしウインドウ開いても狭くならないので最高。若干もてあましている。

f:id:mzp:20181021221437p:plain

🗑今後の課題

💡スマート家電

引越ししたので家電をいくつか進捗した。 せっかくなので、リモートで制御できるものを買った。

🤖ルンバ

床がちらかる前にルンバを買った。iPhoneアプリで制御できるなかでは一番安いモデルにした。

動かしたらいきなりケーブルを巻き込んで停止した。ケーブルボックスを導入したら、なんとかなった。

いまも週一くらいで停止している。かわいい。

💨エアコン

エアコンは部屋についてたので、NatureRemo miniを購入した。

あまり調べずに買ったが、温度調整のUIが格好よくていい。温度計がついてるのもおもしろい。

f:id:mzp:20181010071151j:plain

💡照明

照明も部屋に備え付けだったが、調べたらリモコン操作に対応していた。

リモコンの信号をNatureRemo miniに覚えさせたいけどどうしたらいいのかなーと調べたが、どうやら実物が必須らしかった。Amazonで購入して初期設定したあとはしまってある。

⚡️HomeBridge

それぞれ別のアプリから制御する必要があって不便だった。 iPhoneのHomeアプリから一括制御するためにnfarina/homebridgeを導入した。

部屋はひとつしかないがベッドルームということにしている。

f:id:mzp:20181010231934p:plain

HomeBridgeはRaspberryPiZeroWで動かしている。Raspberry Pi Zero W ケースキット - SWITCH-SCIENCEを買ったが、SDカードがついてないことを見落してて追加購入した。

セットアップ以下のサイトを参考にした。

モジュールは以下のものをいれた。

💕感想

一番の利点はいつも手元にあるiOSバイスから制御できるようになった点である。リモコンはどこに置いたか忘れがちだが、iPhoneiPadmacOSのどれかが手元にあることは多い。

Siri経由で操作できるけどそこまで便利ではない。

あとは以下のものをスマート家電化したいができてない。

  • スマートロック。Qrioがよさそうに見えるが。
  • コーヒーメーカー。自動応答するコーヒーメーカーは夢がある。RFC 2324 Hyper Text Coffee Pot Control Protocolをしゃべってほしい。
  • 洗濯機・炊飯器。残り時間をアプリから確認したい。

☀️ダイナミックデスクトップ壁紙

Mojaveのダイナミックデスクトップでは時刻によって壁紙が変化する。 これを用いてミクさんが部屋の中を歩きまわる壁紙を作成した。

f:id:mzp:20180926194346p:plain

(livetune feat. 初音ミク「Redial」Music Video - YouTubeより)

🖥ダイナミックデスクトップ

macOS Mojaveの紹介ページに記載されているとおり、Mojaveでは時間の経過に応じて壁紙が変化する。

f:id:mzp:20180926195049p:plain

WWDCのキーノートでも、生活にあわせて変化する壁紙のデモがあった。

f:id:mzp:20180926195305p:plain

f:id:mzp:20180926195314p:plain

f:id:mzp:20180926195323p:plain

🛠仕組み

ダイナミックデスクトップ用の壁紙は他の壁紙と同様 /Library/Desktop Pictures に配置されている。 異様にファイルサイズがでかい。

f:id:mzp:20180926195543p:plain

プレビューで開くと16枚の画像が確認できる。HEIFでは一つのファイルに複数の画像をまとめられるので、その機能を利用している。

f:id:mzp:20180926195613p:plain

それに加えてメタデータに時刻と画像の対応、より正確には太陽の位置と画像の対応を格納している。 ここに関しては、以下の記事が詳しい。

💕 作る

WallpaperEngineを使った以下の壁紙の再現を目指す。動きまわってるのがかわいい。

livetune feat. 初音ミク「Redial」Music Video - YouTubeをダウンロードしてフレームごとに分割する。

youtube-dl 'https://www.youtube.com/watch?v=243vPl8HdVk'
ffmpeg -i 'livetune feat. 初音ミク「Redial」Music Video-243vPl8HdVk.mkv' -f image2 %d.png

ここからいい感じの16枚を選ぶ。

f:id:mzp:20180926200339p:plain

複数の画像を束ねた上でメタデータを書き込むのは、mczachurski/wallpapper: Console application for creating dynamic wallpapers for macOS Mojaveで行なう。

brew tap mczachurski/wallpapper
brew install wallpapper

macOS Mojave dynamic wallpaper – ITNEXTを参考に定義ファイルを雑に作る。

info.json

[
  {
    "altitude": -0.3427528387535028,
    "azimuth": 270.9334057827345,
    "fileName": "1.png",
    "isPrimary": true,
    "isForLight": true,
    "isForDark": false
  },
  {
    "altitude": -10.239758644725045,
    "azimuth": 81.77588714480999,
    "fileName": "2.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -4.247734408075456,
    "azimuth": 86.33545030477751,
    "fileName": "3.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 1.3890866331008431,
    "azimuth": 90.81267037496195,
    "fileName": "4.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 7.167168970526129,
    "azimuth": 95.30740958876589,
    "fileName": "5.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 13.08619419164163,
    "azimuth": 99.92062963268938,
    "fileName": "6.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 40.41563946490428,
    "azimuth": 129.18652208191958,
    "fileName": "7.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 53.43347266172774,
    "azimuth": 182.2330942549791,
    "fileName": "8.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 38.793128200638634,
    "azimuth": 233.5515919580959,
    "fileName": "9.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 11.089423171265878,
    "azimuth": 261.87159046576664,
    "fileName": "10.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": 5.1845753236736245,
    "azimuth": 266.4432737071051,
    "fileName": "11.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -6.248309374122789,
    "azimuth": 275.44204536695247,
    "fileName": "12.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -12.20770735214888,
    "azimuth": 280.07031589401174,
    "fileName": "13.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -39.48933951993012,
    "azimuth": 309.41857318745144,
    "fileName": "14.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -52.75318137879935,
    "azimuth": 2.1750965538675473,
    "fileName": "15.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": false
  },
  {
    "altitude": -38.04743388682423,
    "azimuth": 53.50908581251309,
    "fileName": "16.png",
    "isPrimary": false,
    "isForLight": false,
    "isForDark": true
  }
]

このファイルを用いてダイナミックデスクトップ用の壁紙を生成する。

wallpapper -o ~/Pictures/redial.heic -i info.json *.png

システム環境設定から設定する。なぜかサムネ画像がおかしい。

f:id:mzp:20180926200606p:plain

時刻を変更して動作を確認する。

f:id:mzp:20180926194346p:plain

f:id:mzp:20180926194359p:plain

✨感想

動画を壁紙にする場合と比較して変化がおだやかなので、そこまで気がちらない。よい。

こちらを覗き込む画像は夜に表示されるようにしている。 なので、出社前は空の部屋で、家かえってきてPCをつけるとミクさんと目があうので、体験としてよい。

もうちょっと応用したいが、変化してたのしい壁紙のアイデアが足りない。WallpaperEngineのときもそういう話をしていた。

♨️銭湯

東京に引っ越したら銭湯によく行くようになった。東京にはいっぱい銭湯があってよい。

💼持ち物

タオルやシャンプーなどは置いてないことが多いので、自分のものを持っていく。 ダイソーで買ったビニールバッグにコンビニで買ったシャンプーセットを入れている。

水を持ち込んでる人もたまに見かける。 炭酸水を持ち込んで、飲み水と頭を洗うのに使ってて、なるほど感があった。

👍よい

  • 大きい風呂に入れる。
  • 10分くらい歩いたとこにあるので便利。ご飯を炊いてる間に風呂、とかをやっている。お風呂の四階に住む。 - 物件ファンほど近くはない。
  • 銭湯によっては温泉にはいれるとこもあってお得。
  • あまり混んでないので、雑に行ける。

🤔微妙

  • 銭湯の料金 > 水道代なので、やりすぎると破産するかもしれない。
  • 街中を歩いてた直後、店にはいって数十秒で全裸になるという行為に違和感を覚えてしまう。慣れない。
  • 結構話しかけられる。街中で話しかけられることはほぼないのに、全裸だと話しかけられるのおもしろい。

AquaSKK 4.6.0/4.6.1: Mojave対応

Mojave対応を行なったAquaSKKを4.6.0としてリリースした。2018-9-1: HighSierraで一部機能(#84)が動かない不具合が見付かったので、修正して4.6.1としてリリースした。

f:id:mzp:20180901105107p:plain

https://github.com/codefirst/aquaskk/releases/tag/4.6.1

🌓ダークモード

Mojaveではダークモードが導入された。

f:id:mzp:20180729124441p:plain (WWDC2018 Keynoteより引用)

AquaSKKもダークモードに対応させ、候補ウインドウがダークモードで表示されるようにした。 さらに、アクセントカラーも扱うようにした。

f:id:mzp:20180831210108p:plain

🎨 アイコン色の調整

ダークモードではASCIIモードのモードアイコンの視認性がかなり低くなる。

f:id:mzp:20180831085106p:plain

Mojaveより前から存在していた問題(Issue #75)だが、ダークモードが強化されたMojaveではより顕著になる。

色合いを調整して、視認性を向上させた。

f:id:mzp:20180831102112p:plain

👋32bitサポートの廃止/libc++への切り替え

Xcode10から32ビットアプリケーションのサポートが廃止された。Mojave以降は64ビットアプリケーションのみのサポートとなるので、これを気に32ビットサポートは廃止した。

f:id:mzp:20180831101611j:plain (WWDC2017 Keynoteより引用)

またlibstdc++のサポートが廃止されたので、libc++に切り替えた。これは目に見える影響はないと思う。

🙊NDAへの配慮

本記事はNDAに配慮し、Xcode 10やmacOS Mojaveのスクショショットは利用していない。Mojaveが正式リリースしてから書けば楽だったが、キリがついたのでリリースした。若干、無理がある。

ダークモード対応中の様子は楽しいので、それはどこかでロンダリングした上で出したい。

🔥Firebase

夏休みなのでFirebaseの練習をした。

ライブフォトをシェアするSNSのプロトタイプを作った。ライブフォト好きだけど、他の人に共有しづらくて困っている。

f:id:mzp:20180828221417p:plain

📝参考にしたもの

基本的にFirebase Guidesを読んで作った。 これでだいたい分かるので、すごい。

ただ、Apple Developer Portalの設定が必要な箇所になると急に説明が雑になるので、そこは茅場町モバイルアプリもくもく会で教えてもらった。

🔥開発の様子: Firebase

ログイン

Firebase Authenticationを使うと、あっさりGoogleアカウントログインが作れる。便利。

Firestore

Firestoreでプロフィール情報を保存するようにした。

コンソールからデータが確認できて便利。

f:id:mzp:20180828222603p:plain

データの保存にはCodableFirebaseが便利だった。 Codable な構造体を型安全に扱えてよい。

func get<T: Codable>(documentPath: String) -> SignalProducer<T?, NoError> {
   let ref = Firestore.defaultStore().collection("collectionName")
   return SignalProducer { observer, _ in
     ref.document(documentPath).getDocument { document, error in
       if let data = document?.data(),
          let entity = try? FirestoreDecoder().decode(T.self, from: data) {
            observer.send(value: entity)
       }
       observer.sendCompleted()
    }
  }
}

Storage

Cloud Storageで画像を保存できるようにした。

通知

Firebase Cloud MessagingCloud Functionsを使ってfav通知を作った。

Cloud MessagingでAPNsを使う方法は2通りあるがAPNs authentication keyのほうが、どのアプリでも使えて便利。(茅場町モバイルアプリもくもく会で教えてもらった)

通知のロジックを書く場所が分からなかったが、Cloud FunctionsでDB等の変更を監視して通知を送るのがよいらしい。

f:id:mzp:20180828230025p:plain (What can I do with Cloud Functions?から引用)

コンソールから通知を送る方法が分からなかったが、Growカテゴリの下にあった。

f:id:mzp:20180828230530p:plain

📱進捗: Firebase以外

差分更新

画面更新にはDifferenceKitを使った差分更新を採用した。reloadData を読んでた箇所をDifferenceKitに書き換えるだけでよかったので便利。

index c7e6661..ab0d428 100644
--- a/Sources/Controllers/PhotosViewController.swift
+++ b/Sources/Controllers/PhotosViewController.swift
@@ -5,6 +5,7 @@
 //  Created by mzp on 2018/08/20.
 //  Copyright © 2018 mzp. All rights reserved.
 //
+import DifferenceKit
 import MobileCoreServices
 import NorthLayout
 import Photos
@@ -40,11 +41,15 @@ public class PhotosViewController: UICollectionViewController,
             UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #s
elector(add))
 
         collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: kCell)
+
+        self.dataSource.combinePrevious([]).signal.observeValues { oldValue, newValue in
+            let changeset = StagedChangeset(source: oldValue, target: newValue)
+            self.collectionView.reload(using: changeset) { _ in }
+        }
         PhotoFetchLatest().call().collect().startWithResult {
             switch $0 {
             case .success(let photos):
                 self.dataSource.swap(photos)
-                self.collectionView.reloadData()
             case .failure(.firebase(let error)):
                 self.presentError(title: "Firebabse", message: error.message)
             case .failure(.filesystem(let error)):

ライブフォトの読み書き

ライブフォトの読み書きはアンドキュメントな機能を使う必要がある。

読み込みは、imagePickerController(_:,didFinishPickingMediaWithInfo:)info から取得する。

extension ViewController: UIImagePickerControllerDelegate {
    public func imagePickerController(_ picker: UIImagePickerController,
                                      didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        guard let livePhoto = info[UIImagePickerController.InfoKey.livePhoto] as? PHLivePhoto else { return }
        guard let imageURL = photo.value(forKey: "imageURL") as? URL else { return }
        guard let videoURL = photo.value(forKey: "videoURL") as? URL else { return }
        // ....
    }
}

作成は、PHLivePhotorequest に、 画像と動画のURLを渡すことで生成できる。 PHLivePhotoInfoCancelledKey に対応する値が0になるまで待たないと生成されない。

func create(imageURL: URL, videoURL: URL) {
  PHLivePhoto.request(
    withResourceFileURLs: [imageURL, videoURL],
    placeholderImage: nil,
    targetSize: .zero,
    contentMode: .aspectFit) { livePhoto, info in
        if let canceled = info[PHLivePhotoInfoCancelledKey] as? NSNumber,
           canceled == 0,
           let livePhoto = livePhoto {
             // ...
        }
  }
}

✨その他

GitGuardian

なにも考えずにPublicレポジトリでやっていたら、GitGuardianから警告メールが来た。 あわててrevokeしてprivate レポジトリにした。

f:id:mzp:20180828232548p:plain

夏休み

気分転換のために何度か近所の喫茶店に行ったが、夏休みの宿題をやっているらしき兄弟がいて、夏を感じた。

そうか東京の子どもは喫茶店で宿題やるのか。 そんな文化しらないぞ、という気持ちにもなる。

🐣個人esa

Misocaを退職したらMisocaのesaにアクセスできなくなった。不便だったので個人でesaを契約した。

f:id:mzp:20180813154908p:plain

📝日報

esa標準の日報テンプレートにしたがって「今日の作業」「発生した問題」「明日の予定」「所感」を書いている。

f:id:mzp:20180813155125p:plain

一緒に日報書きましょうと募集したら4人あつまった。毎日、みんな書いてて偉い。

f:id:mzp:20180813161720p:plain

見る人がいるのでローカルのメモとブログの中間の温度感になっている。 たのしい。往年の会員制SNSを彷彿させる。

🛠各種メモ

esaは次の特徴があるのでメモを書くときにちょうどいい。

  • Markdownでサクサク書ける。エディタも使いやすい。
  • WIP/ShipItの区別がわかりやすい。
  • 記事ごとに共有URLが発行できる

🐞WebKitへのバグレポート - みずぴー日記も最初はesaに書いて、まとまった段階ではてなブログに移した。 WIPではじめれるので、気軽に書きはじめれる。 また早くShipItしたいという気持ちも働く。

f:id:mzp:20180813155052p:plain

引越しに関するメモも置いてある。 これは、かなり頻繁に参照している。

f:id:mzp:20180813160050p:plain

イベントの予定もここに書いている。 共有URLを発行して関係者に共有できて便利。

f:id:mzp:20180813160301p:plain

✨その他

個人esaの契約どうしようかなーと思ってトップページにいったら、 mzpという人がおすすめコメントを寄せてた。 なるほどと納得したので契約した。

f:id:mzp:20180813160909p:plain

日報メンバーのりんすきさんがアプリのドキュメンテーションesaを使いはじめてた。 esaの輪の広がっている。