自作キーボード Mint60を組み立てた

自作キーボードのMint60を組み立てた。キースイッチとかキーキャップとか個別に揃えるのが面倒だったのでBoothでスターターキットを購入した。
組み立て直後は何故か片側のキーボードが動かなかったりしたが今の所安定して稼働している。ちなみにこの記事はMint60で入力している。

booth.pm

f:id:hkou:20181230225625j:plain

組み立て準備

電子工作を一切やったことがなく、当然道具も何も持っていなかったので必要と思われるものを揃えた。

  • 温度調整機能付きはんだこて
  • はんだこて台
  • はんだ
  • ハンダ吸い取り線
  • 先曲がりピンセット
  • マイクロニッパー
  • コネクタ補強用の接着剤

この中でたぶん使わないだろうなと思ってたけど意外と役に立ったのがピンセットだった。
また、マスキングテープは買わなかったのを後悔した。組立時にかなり必要になる。今回は一緒に組み立てをした人がマスキングテープを持っていたので借りることで事なきを得た。

f:id:hkou:20181228094907j:plain

組み立て

組み立ては一人では心もとなかったので同じく自作キーボードを組み立てようとしている人を誘って共同で組み立てをした。
iPadで組み立て解説ページを開いておいて横に配置して逐次見ながら組み立てた。 f:id:hkou:20181230130015j:plain

ダイオードの取り付け。まっすぐなダイオードを手で一つ一つ折り曲げてボードに刺していく。他の記事を見たら専用の折り曲げ機を利用したりアクリル板を重ねたところに置いて一気に折り曲げたりしていたのでこういうのを真似ればもっと作業スピードが早くなった可能性はある。 f:id:hkou:20181230134948j:plain

刺し終えたら裏側からはんだ付けをするので落ちないようにマスキングテープで固定する。 f:id:hkou:20181230150816j:plain

はんだ付けをする。一列ずつはんだ付けしていって付け終えたらニッパーで余った線をカットして次の列にはんだ付けみたいな流れでやるとやりやすいことがわかった。
はんだの煙が顔にモロに来てつらかったので横に扇風機を配置して煙を飛ばすように工夫した。 f:id:hkou:20181230151528j:plain

スタビライザの組み立て。最初それぞれの部品の向きがわからず組み立てに地味に時間がかかってしまった。 f:id:hkou:20181230164151j:plain

組み立てたスタビライザをボードに固定する。 f:id:hkou:20181230164640j:plain

アクリル板にキースイッチを固定していく。Mint60は自作キーボードの中ではキーの数が多いので地味に大変だった。 f:id:hkou:20181230171423j:plain

MCUのUSBコネクタ補強用の接着剤を用意する。2種類の溶剤を混ぜて接着剤として使用するらしい。 f:id:hkou:20181230181109j:plain

コネクタ内部の接点に入り込まないように丁寧にコネクタ周りに盛っていく。 f:id:hkou:20181230181440j:plain

MCUのはんだ付け、キースイッチのはんだ付け、LEDのはんだ付けをした。
MCUのはんだ付けは接点と接点の距離がめちゃくちゃ近いので隣通しがくっつかないようにはんだ付けにかなり神経を使った。
LEDは裏面が接着面になっていたが接着面がはんだづけした突起が並んでいてでこぼこしていてとても貼れないので雑だがテープでなんとか接着した… f:id:hkou:20181230185353j:plain

だいぶ見た目がキーボードっぽくなってきた。 f:id:hkou:20181230192842j:plain

2つとも組み上がって後はキーキャップをはめるだけという段階でPCに接続して動作確認をしてみた。あとあと他の組み立て記事を見てみるともっと早い段階で動作確認をしていたので、もう少し早めにやればよかったと思っている。
また最初に動作確認したときは何故か片側のキーボードしかLEDが光らない&キーボードが反応しない現象が発生し、いろいろコネクタを抜き差ししていたら唐突に両方使えるようになった。未だになぜ使えるようになったのかよく分からない。 f:id:hkou:20181230200445j:plain

キーキャップを取り付けた。このとき何故か左シフトキーが押したら戻らなくなってしまい何度か分解しても原因は不明だった(スタビライザーはちゃんと動作している)0Insのキーではなくテンキーの+を代わりに刺したらうまく動くようになった。

f:id:hkou:20181230203838j:plain

ApplePay->GooglePayへ移行している

iPhone8 PlusからPixel3に乗り換えたので、決済もApplePay→GooglePayへ乗り換えた(途中)

iPhone8 Plusについては以下 hkou.hatenablog.com

Google Payに移行して変わったことなど

対応する電子マネーが増えた

個人的にはnanacoが利用できるようになった点が大きい。自宅と職場の近くにセブンイレブンがありよく利用するため。
iPhoneでもSuicaで利用できていたが, nanacoだとPointが貯められるのが良い。

エクスプレスカードが不要になった

ApplePayでは電子マネーを利用するときにWallet起動・認証不要するためには、その電子マネーを「エクスプレスカード」に指定する必要があった。
GooglePayでは不要である。というよりも、すべての電子マネーがエクスプレスカードになった感じ。
GooglePayではスリープ状態ですべての電子マネーが利用できる。

その他

Suicaが未だに移行できていない。
iPhone -> iPhoneへの機種変更は簡単にできるみたいなのだが、iPhone -> Androidへの機種変更はSuica自体、アカウントを削除して作成しなおす必要がある。
また、Suicaを削除するときに残金が残っている場合は払い戻し処理をする必要があるがその際に手数料220円がかかる。
手順が面倒だし、無駄にお金もかかるので、このあたりはもう少し改善してほしい。

www.jreast.co.jp

3Dプリンタ FlashForge Adventure3を購入した

6月頃に予約注文したAdventurer3 が届いた。
初回予約組は7月中頃発送とのことなので、運良く初回予約組に入っていたらしい。

f:id:hkou:20180723080801j:plain

開封してみた。PLAのフィラメントと電源ケーブルが入っている。

f:id:hkou:20180723080912j:plain

本体を箱から取り出した。流石に最新モデルだけあってデザインがかっこいい

f:id:hkou:20180723081014j:plain

蓋を開けたところ。奥の方に見える緑色の留め具を外さなければいけないことが説明書には書いておらず、知らずに動作させてガタガタ言わせてしまった。

f:id:hkou:20180723081119j:plain

フィラメントをセットして、本体メモリに入っていたテスト用のボックスを印刷してみた。
中身がある領域はハニカム構造で印刷することで、フィラメントの節約をしているらしい。
動作音については、他の機種は知らないので比較はできないけどとても静かで、隣の部屋で稼働させてても睡眠できそうなぐらい静か。

f:id:hkou:20180723081237j:plain

出来上がったブツ

f:id:hkou:20180723081455j:plain

箱だけだとつまらないのでThingiverseで公開されているモデルを印刷してみた。

www.thingiverse.com

箱みたいな小さいものなら問題ないが、大きいブツを作る時は途中で剥がれてきて失敗してしまうということが分かったので台座に糊を付けた。

f:id:hkou:20180723081641j:plain

完成した。側面のつるつるしたところもちゃんとできていてすごい

f:id:hkou:20180723081800j:plain

ApplePencilを装着してみた。

f:id:hkou:20180723081914j:plain

次は他の素材で試してみたり、自分で作ったモデルを印刷したりしてみたい。

バイク試乗してきた(VERSYS-X 250, VStorm250)

VERSYS-X 250

  • 足つきはCRF250Lよりは良い
  • スリッパークラッチ搭載なのでクラッチレバーがすごく軽い
    • 試乗したバイクはクラッチミートがだいぶ遠くてなれるまでちょっと手こずった
  • 高回転型っぽいエンジン特性でツアラーとしてそれはどうなのとか思った(普段CRF250Lに乗っているせいか全然合わなかった)
  • シートが硬すぎる。10分ぐらい走っただけで尻が痛くなった

f:id:hkou:20180721152028j:plain

VStorm250

  • 足つき最高。両足ベタつきだった。
  • かなり粘るエンジンで下道でも5速~6速で普通に走れてかなり運転しやすい
  • シートがふかふかで長時間乗ってても疲れなさそう
  • VERSYS-X 250とVStorm250のどちらか片方買うとしたら間違いなくVStorm250にすると思う

f:id:hkou:20180721160252j:plain

Office 365 Teamsにoutgoing webhookが来たのでbotっぽいものを作ってみた

Twitterを眺めていたらMS TeamsにOutgoing Webhookが導入されたという情報が流れてきたので早速これを利用してbotを作成してみた。

docs.microsoft.com

システム構成

f:id:hkou:20180609122136p:plain

WebHookの通知を受けるAPIはServerlessFrameworkを利用して作成する。
ServerlessFrameworkのセットアップ等手順は以下のページを参照。

hkou.hatenablog.com

bot作成

Outgoing WebHookの登録

Teams上でOutgoing WebHookの登録を行う。
チームを選択して右クリック→「チームを管理」をクリック f:id:hkou:20180609124735p:plain

「アプリ」タブをクリック

f:id:hkou:20180609124940p:plain

画面右下の「送信WebHook」をクリックする(少し場所が分かりづらい)

f:id:hkou:20180609125059p:plain

送信WebHookのダイアログが表示されるので各項目を埋めていく。

  • 名前
    • botの名前になる
  • コールバックURL
    • 下記で作成するAPIURIを入力

f:id:hkou:20180609125500p:plain

「作成」をクリックするとセキュリティトークンが表示されるのでコピーしてLambdaの環境変数に設定する。

f:id:hkou:20180609125959p:plain

発信者の認証をする

リクエストに含まれるHMAC証明書の検証を行う必要がある。
検証OKの場合、後続の処理に進めるようにする。

const crypto = require('crypto');

// ①セキュリティトークン取得(セキュリティトークンは環境変数から取得する)
const sharedSecret = process.env.SHARED_SECRET;
const bufSecret = Buffer(sharedSecret, "base64");

// ②HTTPヘッダに含まれるAuthorizationの値を取得
const auth = event.headers['Authorization'];

// ③リクエストボディ + セキュリティトークンを用いてハッシュ値を生成しHMACを作成する
const msgBuf = Buffer.from(body, 'utf8');
const msgHash = "HMAC " + crypto.createHmac('sha256', bufSecret).update(msgBuf).digest("base64");

// ④HMACとヘッダのAuthorizationが一致すればOK
msgHash === auth

レスポンスを返却(テキストのみ)

以下の形式でレスポンスを返却するとテキストのみのメッセージが返せる。

{
  "type": "message",
  "text": "Hello World"
}

レスポンスを返却(画像のみ)

以下の形式でレスポンスを返却するとテキスト + 画像サムネイルのメッセージが返せる。

{
  "type": "message",
  "text": "任意の文字列",
  "attachments": [{
    "contentType": "image/jpg",
    "contentUrl": "画像のURL",
  }]
}

その他の形式については以下を参照

www.botkit.ai

botに実装した機能

動作テスト用にテキトウに作ったけどもうちょっとちゃんとしたやつを作りたい。

UUIDv4生成

たまに任意のUUIDv4文字列が欲しくなるときがあるのでbotで生成できるようにした。

f:id:hkou:20180609130145p:plain

為替情報取得

内部でAPI叩いて取得してきた為替情報を取得するだけ。外部API呼び出しの動作確認用に作った。 f:id:hkou:20180609130518p:plain

botのコード

github.com

日帰りダム&温泉ツーリング(スパー美輝)

本日は行ったことのない温泉を開拓するべくツーリングをしてきた。 まずは下呂方面へ向かう。休日だったが大通りから外れた道を選んだのでそこまで混雑はしていなかった。

金山湖 岩屋ダム

金山湖沿いの道は程よいワインディングになっておりバイクで走っていてとても楽しい道だった。また、両車線ともにほとんど他の車がおらず快適に走行できた。

岩屋ダムはロックフィル式のダムで、頂上部分が道になっているので乗り入れることができる。頂上からは広大なダム湖を望むことができる。結構高さがあり柵も簡単に乗り越えられそうなものなのでちょっと怖かった。

f:id:hkou:20180602225234j:plain

放水側、高低差がありちょっと怖い f:id:hkou:20180602225340j:plain

貯水側 f:id:hkou:20180602125545j:plain

スパー美輝

本日の目的地。未開拓の温泉。事前調査から食事も美味しそうだったので、食事と入浴券のセットメニューを購入した。

f:id:hkou:20180602132104j:plain

温泉は内湯、サウナの種類が豊富で飽きずに入ることができる。また、露天風呂からは山々を眺めながらゆっくりと入ることができた。この温泉の一つ山を超えたところには下呂温泉があり、普通の人は下呂の方へ行くのでこの温泉は施設が充実しているにも関わらず人が少なくゆったりと入ることができた。

www.mikinosato.co.jp

美輝の里定食 f:id:hkou:20180602142924j:plain

Apache IgniteでバックエンドにH2 Databaseを利用して永続化する

概要

Apache Igniteはインメモリデータグリッドを実現するミドルウェアであるがデータを永続化したいことがある。
永続化の方法としてディスク領域に保存するNative Parsistenceと外部のデータベース等に保存する3rd Party Persistence機能があり、 この記事では後者の3rd Party Persistence機能試してみる。

apacheignite.readme.io

環境

構成

f:id:hkou:20180518234016p:plain

手順

H2 Database

All Platformsのzipファイルをダウンロードして、解凍する。

www.h2database.com

binディレクトリのh2.batを起動するとWeb管理画面が開く
Apache Igniteからも接続したいので設定済みファイルをServerにして接続する

f:id:hkou:20180518234733p:plain

build.sbt

ignite関連のlibraryを追加

libraryDependencies ++= {
  val igniteVersion = "2.4.0"
  Seq(
    "org.apache.ignite" % "ignite-core" % igniteVersion,
    "org.apache.ignite" % "ignite-spring" % igniteVersion,
    "org.apache.ignite" % "ignite-indexing" % igniteVersion
  )
}

config(xml)

Apache Igniteは設定をxmlファイルで保持する。
xmlファイルはsrc/main/resources/META-INFディレクトリに配置した。

H2 Databaseへの接続設定

先程のH2 DatabaseのWeb管理画面に指定した接続先設定と同じものを指定する。

<bean id= "simpleDataSource" class="org.h2.jdbcx.JdbcDataSource">
    <property name="user" value = "sa" />
    <property name="url" value="jdbc:h2:tcp://localhost/~/test" />
</bean>

キャッシュの設定

  • CacheJdbcBlobStoreFactoryを利用してBLOB形式でデータベースに保存
  • write, readスルー機能を有効化
<property name="cacheConfiguration">
    <list>
        <bean class="org.apache.ignite.configuration.CacheConfiguration">
            <constructor-arg name="name" value="testCache"></constructor-arg>
            <property name="cacheStoreFactory">
                <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory">
                    <property name="user" value = "sa" />
                    <property name="dataSourceBean" value = "simpleDataSource" />
                </bean>
            </property>
            <property name="writeThrough" value="true"/>
            <property name="readThrough" value="true"/>
        </bean>
    </list>
</property>

Scalaプログラム

データをputしてgetするだけの単純なプログラムを書いた。

import org.apache.ignite.Ignition

object Main extends App {
  using(Ignition.start("example-ignite.xml")) { ignite =>
    using (ignite.getOrCreateCache[String, String]("testCache")) { cache =>
      cache.put("test1", "test1Value")
      cache.put("test2", "test2Value")

      println(s"test1 = ${cache.get("test1")}")
      println(s"test2 = ${cache.get("test2")}")
    }
  }

  def using[T <: AutoCloseable, A](resource: T)(proc: T => A): Unit = {
    try {
      proc(resource)
    } catch {
      case e: Throwable => e.printStackTrace()
    } finally {
      resource.close()
    }
  }
}

実行した

上記のScalaプログラムを実行した。igniteのログが表示され、getしたデータが取得できた

[22:58:03]    __________  ________________
[22:58:03]   /  _/ ___/ |/ /  _/_  __/ __/
[22:58:03]  _/ // (7 7    // /  / / / _/
[22:58:03] /___/\___/_/|_/___/ /_/ /___/
[22:58:03]
[22:58:03] ver. 2.4.0#20180305-sha1:aa342270
[22:58:03] 2018 Copyright(C) Apache Software Foundation
[22:58:03]
[22:58:03] Ignite documentation: http://ignite.apache.org
・・・・

永続化されたか確認する

H2 DatabaseのWeb管理画面から確認したところ、ENTRIESテーブルが新たに追加されていた。
内容を確認したところ先程putしたデータが保存されているようだ。

f:id:hkou:20180519000002p:plain

SELECT UTF8TOSTRING(akey), UTF8TOSTRING(val) FROM ENTRIES;