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;

Akka Remoteを利用したServer, Clientの簡単なActor通信するサンプルで動作確認した

概要

akka remoteを使ったリモート間のActorプログラムに慣れるために、client -> server構成の単純なプログラムを作成して動作を確認した。

作成したプログラムは以下

github.com

動作環境

  • Windows 10 Pro 1709
    • JRE build 1.8.0_151-b12
  • scala 2.12.6
  • akka-actor 2.5.12
  • akka-remote 2.5.12

構成

  • メッセージを待ち受けるserverと、メッセージを送信するclientの2プロジェクト構成
  • serverとclientは別プロセスとする

f:id:hkou:20180512102432p:plain

動作シーケンス

  • client
    • serverのActorに対して一定時間間隔でメッセージを送信する
    • 最後にserverを停止するメッセージを送信する
  • server
    • メッセージ待受するActorを起動する
    • 受け付けたメッセージを標準出力に表示する

f:id:hkou:20180512104004p:plain

パケットキャプチャ

remote actorに対する通信を理解するためにパケットキャプチャを用いて通信の内容を確認する。
このサンプルプロジェクトはlocalhost環境で動かしている。WireSharkでは自マシン間での通信はキャプチャできない為、RawCapを利用した。

www.netresec.com

server起動

sbt 
project server
run

client起動

serverとは別のsbtで以下を実行する

sbt
project client
run

キャプチャ結果確認

RawCapは標準でpcap形式のファイルを出力するので、キャプチャ内容を確認するときはWireSharkを利用することができる。

f:id:hkou:20180512110621p:plain

  • 一度コネクションを張るとshutdownするまでずっとコネクションを維持し続ける
  • デフォルトでは4秒?毎にheart beatが投げられている
  • 小さいメッセージ(今回はString9文字程度)だとペイロードの大半がactor pathの情報が占めるように見える

ServerlessFrameworkでS3の静的サイトのホスティングをする

概要

S3に静的サイトのホスティング機能がある。静的ファイル(HTML, js, css等)をS3に配置すると、それらのファイルをウェブ公開してくれる機能だ。
ウェブホスティング用のS3バケットを作成したり、静的ファイルをS3にアップロードしたりするのをServerlessFramework経由で行う。

プロジェクトを作成

とりあえず以下のコマンドを実行してプロジェクトを作成する。プロジェクト名はs3-sync-testにした。

sls create --template aws-nodejs --path s3-sync-test

プラグイン導入

ファイルをS3にアップロードする機能はServerlessFramework標準には無いようなので以下のプラグインを利用する。

github.com

以下のコマンドでプラグインをインストールする。

sls plugin install -n serverless-s3-sync

serverless.ymlの末尾にpluginsの項目が追加されたはずだ。

plugins:
  - serverless-s3-sync

S3バケットの設定

resourcesの項目にS3バケット設定とS3バケットポリシーを記載する。

resources:
  Resources:
    StaticSite:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.webSiteName}
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html
    StaticSiteS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: StaticSite
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: "*"
              Action:
              - s3:GetObject
              Resource:
                Fn::Join: ["", ["arn:aws:s3:::",{"Ref": "StaticSite"},"/*"]]

customにウェブサイト名とS3にアップロードするファイルを配置しているディレクトリ名を記載する。

custom:
  webSiteName: s3-sync-test.com
  s3Sync:
    - bucketName: ${self:custom.webSiteName}
      localDir: static

HTML用意

<project>/static ディレクトリにindex.htmlerror.htmlを配置した。

デプロイ

以下のコマンドでデプロイする。

sls deploy -v

動作確認

AWSのマネジメントコンソールからS3のページへ遷移して、上記で作成したバケットがあるか確認する。
バケット内を確認し、HTMLファイルがアップロードされているか確認する。

f:id:hkou:20180507212858p:plain

ブラウザから確認

プロパティからStatic website hostingを選択してエンドポイントを開く。

f:id:hkou:20180507213123p:plain

ブラウザから表示することができた。

f:id:hkou:20180507213246p:plain