ぴょんぴょんブログ

Djangoで作るLIFFアプリ

はじめに

この記事はあくあたん工房 Advent Calendar 2019,10日目の記事です.Advent Calendarにはなんでもありな面白い記事が載ってるのでぜひ.

adventar.org

この記事ではLINE Front-end Framework(LIFF)の紹介を兼ねてLINE上で動く簡単なアプリを作っているのでそれを紹介したいと思います.

LIFFって?

LINE Front-end Framework(LIFF)は、LINEが提供するウェブアプリのプラットフォームです。このプラットフォームで動作するウェブアプリを、LIFFアプリと呼びます。

LIFFアプリを使うと、LINEのユーザーIDなどをLINEプラットフォームから取得できます。LIFFアプリではこれらを利用して、ユーザー情報を活用した機能を提供したり、ユーザーの代わりにメッセージを送信したりできます。

developers.line.biz

LINE Botなどと合わせて使えたりするのとプロフィールやルーム情報を利用できる点が利点なのかなと思います.また従来はLINE内のブラウザでしか利用できなかったそうなんですが,バージョン2から外部のブラウザでも使えるようになりできることの幅が広がりました.

作っているもの

友人と行っている筋トレを今日は何時に行く?とか誰が行く?とかを毎回LINEで決めているんですがもうちょっといい感じに連絡できないかなということで筋トレのスケジュールを管理するアプリを作ろうかなと思いました.どうせなんでやった筋トレのメニューとかも保存する機能とかほしいなぁ……

構成

  • LIFF 2.1
  • Django 3.0
  • Bootstrap 4.3

アプリはPythonAnyware上にデプロイしました.

仕組みをざっくりと図にしました.認証するとliffを使ってユーザ情報を取得したりメッセージを送信したりできるようになります.

f:id:ocucraqp:20191210213342j:plain

したこと

  1. LINEチャネル作成
  2. Djangoでアプリ作成
  3. デプロイ

LINEチャネル作成

LINEにはAPIやclova用のスキルの作成時に利用するLINE Developersというものがあります.ここにMessaging APIを登録することでLIFFを利用できるようになります.

developers.line.biz

Djangoでアプリ作成

普通にWebアプリを作ればいいのですがLIFFを組み込む必要があります.javascriptでLIFFを利用して取得したID等の情報をpostしてサーバで管理することにしました.

一応コードをおいておきます.

github.com

デプロイ

PythonAnywareにデプロイしました.Django Girls Tutorialを見ながらしたのですがすごく簡単にデプロイできてびっくりしました.

tutorial.djangogirls.org

おわりに

一応デモのようなものは動いてはいるんですが機能もほとんど実装できてない上セキュリティなどがガバガバのガバなので公開するのは辞めておきます.一応テストで出した画面をおいておきます.(これのために何年かぶりにプロフィールを設定しました.)

f:id:ocucraqp:20191210221931p:plain
プロフィールを表示するデモ

また,LINE内のブラウザで動かすのが前提みたいなところがあるのでもっと軽いフレームワークで作りたかった(LIFFを使ってる記事とか見るとVueとかで実装してるのが多い気がする)んですが他のフレームワークを勉強する余裕がなかったんで使用経験のあるDjangoになっちゃいました.

明日以降もAdvent Calendarは続いていくので見ていただければ幸いです.

LINE Dev Day参加レポート

はじめに

LINE 株式会社様より学生への交通費支援を利用させて頂き LINE DEVELOPER DAY に初めて参加してきました.楽しくてとても勉強になるイベントに招待頂きありがとうございました.自分が聞いたセッションや参加したハンズオンについてのまとめと感想を紹介できたらと思います.間違えている部分などがあれば優しく指摘していただけると嬉しいです.

入り口からスマホを何台も使ったロゴがあってびっくりしました.私は事前に顔認証での登録をしておいたのでスムーズに入場できました.受付も顔認証が認証端末に近づいたときには既に認証されているという速さでびっくりしっぱなしでした.

f:id:ocucraqp:20191125150015j:plain
豪華な入り口

keynote

speakerdeck.com

これまでの Dev Day や今年の事業の話と力を入れている 3 つの分野についての話です.最初の Keynote については Developer アカウントが詳しくツイートされていますので是非御覧ください.

twitter.com

3 つの分野は下の 3 つです.

  • AI
  • Data Platform & Infrastructure
  • Security & Privacy

AI

Smart Channel や LINE BRAIN の話がありました.Smart Channel とは,最近よくトーク一覧の上に表示されているあれです.なんとユーザの行動を基にした 2000 万次元もある特徴量を分析して,表示するコンテンツを決めているそうです.LINE BRAIN は,LINE で培われた AI を技術を外販するサービスです.受付でも使われていた顔認証システムや OCR 技術,自然言語処理,STT/TTS,動画解析など多くの技術が開発されています.自分は LINE の AI 関連技術は主に LINE Clova しか知らなかったので想像以上に力を入れているのが分かりました.会場で OCRAPI を無料体験できるコードを頂いたので時間があれば使ってみたいと思います.

Data Platform & Infrastructure

それぞれの欲しいデータがすぐ手に入る環境(Self-Service Data Platform)を目指しているそうです.LINE では毎日 1 兆件ものレコード(390TB)を処理しており,次の課題の解決が必要でした.

  1. Accessibility
  2. Multi-tenancy
  3. Data Quality

これらに対して,次のような解決策を考案したそうです.

  1. オンラインでのプラットフォームの統合
  2. スケーラブルなオンデマンド分析環境の実装
  3. 自動でデータ分類・メタデータの構築

プラットフォームの統合によってデータガバナンスが向上したそうです.また,プライベートクラウド Verda の紹介がありました.自社でクラウドを運用することで,不具合が発生しても迅速に対応することが可能になっています.ソフトウェアでインフラ機能を実装することでインフラのライフサイクルを開発のライフサイクルに近づけることができたそうです.

Security & Privacy

LINE では法律の専門家を加えたチームがいて,エンジニアと設計段階からセキュリティーとプライバシーについて話あって開発を行っている程プライバシーを大事にしているそうです.私もネット上のデータや OSS を利用したりする際法的に問題ないか心配になるときがあるので,ユーザだけでなくエンジニアも安心できる仕組みだと思います.またアカウント乗っ取りについて,昨年の乗っ取り件数が 0 件だったのは驚きました.乗っ取り対策についても機械学習が使われていて,フィルタリングルールを自動的に更新している手動で更新するコストを削減していました.他にもいち早く FIDO の導入が行われていたり,透明性レポートを発行しているなどの話がありました.

LINE が開発した時系列データベース‘Flash’の紹介

speakerdeck.com

眠いときは DB の話を聞くと元気がでるらしいです.

既存の DB は何かしらの欠点があったため新しい DB を作る必要があったそうです.新しい DB を作るにあたって必要だったものは次の 3 つ.

  • ユーザがどのプロトコルを使ってもサポートしたい
  • 簡単にスケールアウトでき読み込みも書き込みも高速
  • メンテンナンスコストが低い

これらを目標に実際に完成した DB は以下のようなものでした.

  • 秒間 400 万の Datapoints を書き込める
  • 秒間 1000 クエリを処理できる
  • Write P99 < 100ms
  • Read P99 < 100ms

時系列 DB とは,CPU などの情報を Label,時間毎の Label を Datapoint,一連の Datapoint を Serie として定義された DB です.Flash の実現には,基本的に利用することが多い最新の 28 時間分データは DRAM 保存したり,Delta-Delta Xor Algorithm というものを利用したそうです.

プロトタイプとベータ版はたったの 2 ヶ月で完成したが,製品としてリリースするには 1 年かかかったらしいです(通常は 5 年はかかるらしいのでめちゃくちゃ早い).現在のスペックにはまだ満足していなそうで,これから秒間に書き込める Datapoints を 100 倍,クエリの数を 10 倍にすることを目指しているとのことでした.

LINT (LINE Improvement for Next Ten years)

speakerdeck.com

2011 年から溜まっている過去の技術的負債を消すための活動について聞くことができました.LINE は「安定したメッセージングサービスを目指す段階」から,「より信頼でき,より柔軟なプラットフォームを目指す段階」に移行しており,多くの部分で改善が必要になっているそうです.これらの改善のために,様々な分野の専門家が集まった LINT チームが誕生しました.現在主に取り組んでいる課題は以下の 4 つです.

  1. HTTP/2 and Push
  2. Event delivery mechanism
  3. Authentication Token renewal
  4. General setting storage for client/server

セッションでは 1 と 2 について語られていて,1 については,Google がサポートを終了している SPDY をベースにした LEGY という内製プロトコルを使っており,それが無駄なリクエストをしているため,HTTP/2 ベースに変えていきたいという内容でした.2 についてはクライアントとサーバ間でのデータの不整合を分かりやすくしたり,久しぶりに LINE を起動すると使ってなかった期間のデータを一気にフェッチしようとして重くなるのを改善しようという取り組みです.データ整合性に関してはデータのダイジェストをクライアント・サーバ間で交換することで整合性を保つ Auto Repair という仕組みを導入しているそうです.フェッチの部分には,メッセージが 100 件以下程度なら従来どおりフェッチし,それ以上であれば FullSync という API を叩きデータを得る仕組みとなっていました.

他にも自分がずっと改善を望んでいるマルチアカウント機能やマルチデバイス機能も今後の課題として挙げられており改善が楽しみです.

Kubernetes の利用・普及,その先は何か?

このセッションのスライドは見つけられなかったです.最初は Docker や k8s(Kubernetes)などに関して軽い説明がありました.世界ではすでに k8s を使ったプロダクトは当たり前で,日本は出遅れている状態だそうです.また Google はすべての業務がコンテナで実行されているというのはさすが Google という感じでした.

なぜ k8s を選んだかについて

登壇者の河さんが所属するZ Labのミッションは「イケてるモダンなインフラを作る」というもの.Portability & Reproducibility の観点からコンテナ技術に注目したが,当時は k8s の他に docker swarm や mesos もありました.k8s を選んだのはスポンサー企業の数やセキュリティ対応などから将来性が高いと判断したから.とりあえず k8s を構築してみるとすぐに運用がハードであることが分かったそうです.VM と同時に k8s を運用するのは保守コストが非常に高いのでソフトウェアで解決しようということで Caas を立ち上げ.

CaaS (Container as a Service)

CaaS はいろいろ操作が 1 コマンドでできるように作られました.k8s は Declarative object configuration モデルをサポートしており,この設定を読み込み,処理するプログラムを Controller と呼ぶ.理想の状態を定義し,Controller がその状態になるように稼働し,この機構を Reconciliation Loop と呼ぶ.CaaS 自体が SPOF(単一障害点)になることを防ぐために,自身が所属する K8s クラスタも CaaS が生成する.CaaS が壊れても k8s が復旧し,k8sVM に障害が起きても CaaS が復旧する.

CaaS と k8s がそれぞれ補い合っているというシステムが面白いと思いました.このセッションを聞いて国内外の同年代に負けないように自分も頑張って行きたいと気持ちを改めました.

Gatebox の内と外 - AR でも VR でもない新しいデバイスプラットフォーム

www.gatebox.ai developer.gatebox.biz

Gatebox の仕組みをガッツリ紹介していただきました.こちらもスライドは見つけられなかったです.

Gatebox の癒しの花嫁である逢妻ヒカリは人らしい会話や能動的アクション,動きにこだわっているそうです.システムは Unity, STT/TTS, Gatebox SDK, CIC SDK などで構築されており,クライアント側のことを Hikari App,サーバ側のことを Hikari Brain としていました.ユーザの時間分布や特徴的な発話傾向などを分析することでクオリティが対応力が上げています.キャラクターの動きをフレーム単位で制御し,どんなときでも不自然にならないように状態を変更する技術がすごいと思いました.例えば飲み物を飲んでいるときに話すのはおかしいので,そういうことにならないように設定されているのはこだわりを感じました.今後は Gatebox 上で動くアプリ・サービスの開発がオープンでできるようになるというのは夢もあるし,サービスの数が増えるのはユーザにはかなり嬉しいことなんじゃないかと思います.

LINE Pay ハンズオン ~ あなたの Bot に LINE Pay 決済機能を追加してみよう

LINE Pay v3 ハンズオン資料 [Version. 2019.11.22]

最初に LINE Pay について簡単なまとめがありました.個人でも(法人でなくても)個人事業主であれば加盟店になれて,sandbox(開発環境)の利用のみなら加盟店になる必要もないそうです.LINE なのでユーザ行動と連動したサービスを作りやすいのも魅力です.

ハンズオンでは次の流れで行いました.

  1. LINE Pay Sandbox の設定
  2. ngrok の実行
  3. LINE Developers 上でチャネルの作成
  4. チャネルの設定(アクセストークンの発行や Webhook URL の設定など)
  5. サンプルプログラムのダウンロード
  6. リッチメニューの作成
  7. チャネル ID 等を設定して実行
  8. コードの解説

実際に動いた次のように画面が動いて感動しました.想像以上に簡単にできて感動しました(コードは書いてませんが).

f:id:ocucraqp:20191125152801p:plain
LINE Pay 商品画面

f:id:ocucraqp:20191125152828p:plain
LINE Pay カート画面

私は法人でも個人事業主でもないため,実際に活用ができないのが残念ですが,もしナイスなサービスが思いついたらまたチャレンジしたいです.

Journey of Feature Flag development in LINE Android

speakerdeck.com

LINE での Android アプリ開発の中で生まれた Feature Flag についてメリットから課題まで説明していただきました.

まずは Feature Branch についての説明がありましたが,これは Git を使って開発するときに機能ごとに切るブランチのことです.これの問題点ですが,大規模開発においては Feature Branch が多くなり,複雑に絡み合って管理やコンフリクトの修正が大変になるということでした.

Feature Flag は,従来 Feature Branch に対して送っていたプルリクを直接 Main Branch へ送るようにし,開発途中の機能についてはフラグをつけることで,本番環境では実行されないようにするというものです.これにより,コンフリクトサイズの縮小,リリース計画のスムーズ化,機能の有効/無効の切り替えの簡易化,全員が開発中のコードを確認できるなどのメリットがありました.すごくわかりやすいメリットで数人での開発でも開発の内容によっては有効に利用できそうだと思いました.

次に Feature Flag の限界についてです.従来のライブラリのアップデート等に適用するのが難しかったり,プロトタイプなどを作成する際には過剰な管理になってしまったなどです.社内で実際に Feature Flag を使っていた際のトラブルにも触れていて,flag 生成のコードがコピーされ参照関係で問題が起こったことなどが語られていました.

なんとこのセッションのタイミングで LINE のアンドロイド開発用の Feature Flag を用いる開発ツールが公開されました.以下の URL から利用することができます.

github.com

LINE Developer Community の歩み

LINE の開発者のコミュニティだと思ったら社外のコミュニティでした.こういうコミュニティがあったのは知らなかったので知ることができてよかったです.LINEDC から生まれた関連ツールもあり,C# SDK LINE Messaging API や LIFF CLI のサーバ API をいい感じに CLI から実行できるツールなどがそうらしいです.このコミュニティでは Bot を公開できたり,API Expert の方に質問できます.実際に会場でも Q&A が和気あいあいと行われて,コミュニティの熱が伝わってきました.自分も LIFF を使ってアプリ作りたいと思っているので,疑問があれば質問したいなと思いました.

おわりに

多くの新しい知識を得られたとともに同世代の学生にも出会うことができ,非常に刺激的な2日間となりました.ほとんど理解できなかったセッションもあり,もっと勉強しないとと思いました.また,もっと質問したりすればよかったというのが心残りなので,今後もこのようなイベントに参加して見聞を広めればと思います.改めて LINE 株式会社様,ありがとうございました.

f:id:ocucraqp:20191125151105j:plain
1日目の後で大井町で食べた美味しい味噌バターラーメン

f:id:ocucraqp:20191125151209j:plain
会場近くのUCガンダム デストロイモード

乱雑に保存された画像たちを供養!

はじめに

これはあくあたん工房お盆休みアドベントカレンダー6日目 (8月15日)の記事です.

僕は今まで,外で撮った写真やネットで集めてきた可愛いイラストなどを,スマホに適当に保存して,スマホの買い替え時にPCに移していました.そのため,PCの画像フォルダは訳の分からないフォルダ名に全然別の種類の画像が乱雑に保存されている状況でした(まさに画像の墓場).このままでは画像たちが浮ばれませんが手動でフォルダ分けは辛い……

f:id:ocucraqp:20190815132425p:plain
無意味なフォルダ名たち

ということで機械学習の勉強も兼ねて乱雑な画像フォルダを分類してくれる分類機を作成したいと思います.(機械学習全く理解できてないので解説だとはお思わず,ツッコミを入れながら読んでください.)

↓こちらの記事を非常に参考にさせていただきました. qiita.com github.com

環境

  • Google Colaboratory
  • Chainer 5.4.0

手順

  1. 画像の準備
  2. 標準化
  3. 学習
  4. 分類・評価

僕の画像フォルダはほとんどが風景・犬(ラブラドール・レトリバー)・萌え画像のどれかなのでこの3パターンに分類したいと思います.

画像の準備

学習用の画像と評価用の画像を用意します.

学習用画像

「風景」,「ラブラドール 茶色」,「イラスト」をGoogleで検索してでてきた画像を使うことにしました.ガバガバ検索ワードですが全然違うの大丈夫だと信じました.スクレイピングの知識もないので参考記事にあるこちらのdownload.pyを使い,各画像96枚ずつ用意しました.これらの画像はGoogle Driveのtraining-dataフォルダ内に0~2のフォルダを作り,0から順に「風景」・「犬」・「萌え画像」のフォルダとして保存しました.

qiita.com

f:id:ocucraqp:20190815162842p:plain
風景の画像
f:id:ocucraqp:20190815162858p:plain
ラブラドールの画像
f:id:ocucraqp:20190815162913p:plain
イラストの画像

評価用画像

最終的には自分の画像全てを分類したいのですが,時間がかかるので僕の画像中から3つの種類をそれぞれ20枚を用意して分類させ,だいたいの正答率を調べたいと思います.こちらの画像はGoogle Drive内のtest-dataフォルダ内に学習用画像と同じように保存しました.

ちなみに画像フォルダには少なくとも2万5千枚の画像があるっぽいです.中学生の頃にくだらない面白画像とかをダウンロードしてたのを死ぬほど後悔してます(消したいけど他の画像と混ざってて面倒).

標準化

まずは,GoogleDriveをColaboratoryにマウントします.

from google.colab import drive
drive.mount('/content/drive')

次に,データを読み込んで,そのままでは解像度もバラバラなので64x64にリサイズしました.最初はChainerのLabeledImageDatasetクラスを使ってリサイズしようとしてたんですが,上手くいかなかったため,参考記事の通りOpenCVで行いました.

import numpy as np
import cv2
import os

# 分類
words = ["風景", "犬", "萌え画像"]

# データフォルダ名
training_folder_name = "drive/My Drive/training-data/"
test_folder_name = "drive/My Drive/test-data/"

# wordsに対する辞書を作成
detection_words = {}
for i in range(len(words)):
    detection_words[words[i]] = i

# 学習用データ
x_train = []
# 学習用ラベル
t_train = []
# テスト用データ
x_test = []
# テスト用ラベル
t_test = []

# 学習用データとラベルを準備
for word in detection_words:
    path = training_folder_name + '/' + str(detection_words[word])
    imgList = os.listdir(path)
    img_num = len(imgList)
    for j in range(img_num):
        imgSrc = cv2.imread(path + "/" + imgList[j])
        if imgSrc is None: continue

        # 画像を64x64にリサイズ
        imgSrc = cv2.resize(imgSrc, (64, 64))
        x_train.append(imgSrc)
        t_train.append(detection_words[word])

# テスト用データとラベルを準備
for word in detection_words:
    path = test_folder_name + '/' + str(detection_words[word])
    imgList = os.listdir(path)
    img_num = len(imgList)
    for j in range(img_num):
        imgSrc = cv2.imread(path + "/" + imgList[j])
        if imgSrc is None: continue

        # 画像を64x64にリサイズ
        imgSrc = cv2.resize(imgSrc, (64, 64))
        x_test.append(imgSrc)
        t_test.append(detection_words[word])

# データは1/255して値を0~1にする
x_train = np.array(x_train).astype(np.float32).reshape((len(x_train), 3, 64, 64)) / 255
t_train = np.array(t_train).astype(np.int32)
x_test = np.array(x_test).astype(np.float32).reshape((len(x_test), 3, 64, 64)) / 255
t_test = np.array(t_test).astype(np.int32)

学習用ネットワーク

2層の畳み込み層+3層の全結合層です.画像には畳み込みが効くそうです.

import chainer.links as L
import chainer.functions as F
from chainer import Chain


# モデル
class CNN(Chain):
    def __init__(self):
        super(CNN, self).__init__(
            # 畳み込み層
            conv1=L.Convolution2D(None, 20, 5), 
            conv2=L.Convolution2D(None, 50, 5), 
            # 全結合層
            l1=L.Linear(None, 500),
            l2=L.Linear(None, 500),
            l3=L.Linear(None, len(detection_words), initialW=np.zeros((len(detection_words), 500), dtype=np.float32))
        )

    def forward(self, x):
        h = F.max_pooling_2d(F.relu(self.conv1(x)), 2)
        h = F.max_pooling_2d(F.relu(self.conv2(h)), 2)
        h = F.relu(self.l1(h))
        h = F.relu(self.l2(h))
        h = self.l3(h)
        return h

学習

最適化関数にAdamというのを使い,エポック数を30,バッチサイズを15とし

from chainer import optimizers

model = CNN()
# 最適化関数
optimizer = optimizers.Adam()
optimizer.setup(model)

n_epoch = 30
batch_size = 15
N = len(t_train)

# accuracyとlossの推移をみるために用意
accuracy_histry = []
loss_histry = []

各種設定を終えたら次のコードで学習が始まります.

from chainer import Variable

for epoch in range(n_epoch):
    # train
    sum_loss = 0
    sum_accuracy = 0

    perm = np.random.permutation(N)
    for i in range(0, N, batch_size):
        x = Variable(x_train[perm[i:i + batch_size]])
        t = Variable(t_train[perm[i:i + batch_size]])
        y = model.forward(x)
        model.zerograds()
        loss = F.softmax_cross_entropy(y, t)
        acc = F.accuracy(y, t)
        loss.backward()
        optimizer.update()
        sum_loss += loss.data * batch_size
        sum_accuracy += acc.data * batch_size
    accuracy_histry.append(sum_accuracy / N)
    loss_histry.append(sum_loss / N)
    print("epoch: {}, mean loss: {}, mean accuracy: {}".format(epoch, sum_loss / N, sum_accuracy / N))

分類・評価

import matplotlib.pylab as plt

# グラフ化
X_axis = np.arange(n_epoch)
plt.plot(X_axis, accuracy_histry, label="mean-accuracy")
plt.plot(X_axis, loss_histry, label="mean-loss")
plt.xlabel("epoch")
plt.title("accuracy,loss-epoch")
plt.legend()
plt.show()

cnt = 0
testsize = len(t_test)
count = {}
for i in range(testsize):
    x = Variable(np.array([x_test[i]], dtype=np.float32))
    t = t_test[i]
    y = model.forward(x)
    y = np.argmax(y.data[0])

    try:
        count[t]
    except:
        count[t] = [0, 0]
    if t == y:
        cnt += 1
        # それぞれのラベルの正解数をカウント
        count[t][0] += 1
    # それぞれのラベルの合計数をカウント
    count[t][1] += 1
    # print(t,y)
print("accuracy: {}".format(cnt / testsize))
# それぞれのラベルの正解数
for i in count:
    for word in detection_words:
        if detection_words[word] == i:
            print(
                "{}の正当数:{}、誤答数{}、正解率{}".format(word, count[i][0], count[i][1] - count[i][0], count[i][0] / count[i][1]))

出力は次のようになりました. f:id:ocucraqp:20190815203436p:plain

accuracy: 0.6333333333333333
風景の正当数:10、誤答数10、正解率0.5
犬の正当数:16、誤答数4、正解率0.8
萌え画像の正当数:12、誤答数8、正解率0.6

感想

こんな精度では画像たちが報われない!今後も地縛霊のごとくHDDに残っていくことでしょう.

いろいろ頑張ろうと思ってたのですが,最終的に分からないところが多すぎて参考の記事からコードをそのまま使わせてもらうことが多くなってしまいました.

やはり機械学習は難しい……

これからもっと精進して来年には悪霊,もとい画像フォルダを供養したいと思います.

snapでインストールしたJetBrainsのIDEでの組み込みterminalでfishを使う

snapでインストールしたPyCharmとCLionの組み込みターミナルでfishを使うと次のようなエラーが大量に出まくりました.

<E> fish: Unable to open universal variable file '/snap/pycharm-professional/136/plugins/terminal/fish/fishd.<username>-desktop': 読み込み専用ファイルシステムです

snapコマンドでインストールした他のJetBrainsのIDEでもこのエラーが出るっぽいです.

一応解決したっぽいので,解決策を書いておきます.

File>Settings>Tools>TerminalのShell integrationのチェックを外すとこのエラーは消えました.

Shell integrationの場所
Shell integrationの場所

Shell integrationが有効になっていると,どうやらIDE内にあるShellの設定ファイルを読もうとするらしいんですが,snapでインストールするとこの設定ファイルが読み込み専用になってて,エラーが出るらしいです.

www.jetbrains.com

Shell integrationを無効したときのデメリットとかはよく分かってないのでご存知の方は教えて下さい.

QMK Firmwareでテンキーレイヤーを追加

はじめに

前々回と前々回では,Mint60を作成し,キーマップを自分用に変更しました.

前々回 [ 電子工作初心者が思ったMint60製作注意点 - 趣味を語りたいブログ ]

前回 [ WSLでのキーマップ変更方法と分割キーボードで右をマスターにする方法 - 趣味を語りたいブログ ]

自作キーボードを作った後,たまに使うしテンキーも買おうかなと思っていました.でもテンキーのレイヤーを追加すれば場所もとらないし完璧ではと思い,今回作成しました.

キーマップの焼き方は前回の記事に書いてるので,そちらをご覧ください.

作成するキーマップ

作成するキーマップは次のようにしました.

f:id:ocucraqp:20190629021040p:plain
標準のレイヤー(レイヤー0)
f:id:ocucraqp:20190629021125p:plain
ファンクションレイヤー(レイヤー1)
f:id:ocucraqp:20190629021203p:plain
テンキーレイヤー(レイヤー2)
レイヤー0が標準のレイヤー,レイヤー1がfnキーを押したときに使うレイヤー,レイヤー2がテンキー用のレイヤーにしています.

テンキーレイヤーはfn+Aで呼び出せるようにしています.レイヤー1のTO(2)という部分です.TO(X)とすると,それを押したときにXのレイヤーに切り替わります.MO(X)は押している間だけそのレイヤーに切り替わるのですが,テンキー使用中にどこかのキーを押しっぱなしにするのは辛いので,TO(X)を使いました.

ソースコード

このキーマップのコードは次のようになります.

const uint16_t PROGMEM
keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = 
LAYOUT( \
    KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
 MO(1), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
 KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RCTL, KC_UP, MO(1),   \
    KC_LCTL, KC_LGUI, KC_LALT, KC_F7, KC_SPC, KC_SPC, KC_RALT, KC_RGUI, KC_LEFT, KC_DOWN, KC_RGHT \
),
[1] =
LAYOUT( \
    KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
 RGB_TOG, XXXXXXX, XXXXXXX, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, KC_UP, XXXXXXX, XXXXXXX, KC_CAPSLOCK, KC_PSCREEN, KC_INSERT, \
 _______, TO(2), XXXXXXX, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, KC_LEFT, KC_DOWN, KC_RGHT, XXXXXXX, XXXXXXX, _______, \
 _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, KC_PGUP, _______, \
 _______, _______, _______, _______,
LALT(KC_GRV), KC_DEL, _______, _______, KC_HOME, KC_PGDN, KC_END \

),
[2] =
LAYOUT( \
    KC_ESC, KC_KP_7, KC_KP_8, KC_KP_9, KC_PSLS, KC_BSPC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
 KC_TAB, KC_KP_4, KC_KP_5, KC_KP_6, KC_PAST, KC_DEL, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
 _______, KC_KP_1, KC_KP_2, KC_KP_3, KC_PMNS, KC_NUMLOCK, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, _______, \
 _______, KC_KP_0, KC_KP_DOT, KC_PENT, KC_PPLS, TO(0), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, _______, KC_UP, _______, \
 _______, _______, _______, _______, KC_SPC, KC_SPC, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT \
)
};

KC_KP_Xというのが,テンキー用のキーコードになっています.テンキーは左のキーボードにだけ割り当てて,右のキーボードは適当なキーコードにしておきました.

最後に

Mint60は格子状の配列ではなく,行ごとにずれているため,普通のテンキーの感覚で使うと使いづらいです(ノーパソでテンキーを使うときのような感覚).テンキーの使用頻度が高い人は普通にテンキーを購入した方がいいと思います.僕はそんなに使用頻度が高くないのと,机が狭いのでテンキーを置きたくないという理由でしばらくこれで頑張ろうかなと思っています.

(もっと玄人っぽいキーマップにしたいけど,これ以上すると普通のキーボード使うときに辛くなりそう……)

WSLでのキーマップ変更方法と分割キーボードで右をマスターにする方法

はじめに

先日Mint60を作りました.

ocucraqp.hatenablog.com

自分用にキーマップを変更したので,その方法について書きたいと思います. WSLの導入方法やgit,makeのインストール方法についてはここでは書きませんが,ググればすぐ出てくると思います.

また今回自分はWindowsにDockerを入れるのが面倒だったのでmakeでビルドしたのですが,Dockerでもビルドできます(WSLでDocker使えるようになるのはいつ......). また,QMK ToolboxのLinux版は更新がかなり前に止まっているっぽかったので,QMK Toolboxを使う場合はWindowsMacでやりましょう.

以下の記事を参考にさせていただきながら書きました. www.urong-answer.org

環境

必要な物のインストール

キーマップを変更するのに必要なソフトは

の二つです.

QMK Firmware

QMK Firmwareオープンソースの自作キーボード用ファームウェアです. c言語でキーマップを自由に作ることができます. QMK Firmwareはgitでローカルにクローンします. WSL上で適当なディレクトリに移動してから以下のコマンドを入力してください.

git clone https://github.com/qmk/qmk_firmware

他に必要な物をまとめてインストールしてくれるスクリプトがあるので,次のコマンドで実行します.

./util/qmk_install.sh

QMK Toolbox

QMK ToolboxはQMK Firmwareで作ったキーマップをキーボードに焼くために使います. まず以下のページからqmk_driver_installer.exeをダウンロードしてドライバをインストールしてください. github.com 次に以下のページからqmk_toolbox.exeをダウンロードしてください. github.com 特に理由がなければどちらも最新版でいいと思います.

キーマップの焼き方

まずqmk_firmwareディレクトリに入ります.

cd qmk_firmware

Mint60のデフォルトのキーマップはqmk_firmware/keyboards/mint60/keymaps/default/keymap.cに書かれています. このキーマップ試しにキーボードに焼いてみます.

焼くときは,まずqmk_firmwareディレクトリ下でキーマップをビルドします.

make <keyboard name>:<keymap name>

Mint60のデフォルトキーマップの場合は

make mint60:default

です.

エラーが出た場合は,必要に応じてエラーに表示されているソフトをインストールすれば解決するかもしれません. コンパイルできていればqmk_firmware下にmint60_default.hexというファイルが生成されているはずです.

次にqmk_toolbox.exeを起動します. 起動したら,左上のlocal fileという部分に先程生成したmint60_default.hexを選択します. キーマップを焼くキーボードを接続して,リセットボタンを押してください.

*** Caterina device connected: Arduino Micro bootloader ~~~***

という風な文字が表示されると接続されています. 右上のFlashボタンを押すとキーマップを焼いてくれます. Thank youと表示され,接続が切れると完了です.

キーマップ変更方法

defaultのキーマップを元にオリジナルのキーマップを作成するので,まずはdefaultをコピーします.今回はオリジナルのキーマップ名はcustomとします.

cp -r keyboards/mint60/keymaps/default keyboards/mint60/keymaps/custom

次にcustom内のkeymap.cを編集します. 34行目以降を変えていきます. defaultのkeymap.cでは次のようになっています.

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [0] = LAYOUT( \
    KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,      KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_MINS, KC_EQL,    KC_BSPC,  \
    KC_TAB,    KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,      KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_LBRC, KC_RBRC, KC_BSLS,  \
    KC_CAPS,     KC_A,    KC_S,    KC_D,    KC_F,    KC_G,      KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,        KC_ENT,   \
    KC_LSFT,       KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,      KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_RSFT,   KC_UP,  MO(1),   \
    KC_ESC,    KC_LCTL,    KC_LGUI,    KC_LALT,    KC_SPC,        KC_BSPC, KC_ENT,  LALT(KC_GRV),               KC_LEFT,KC_DOWN,KC_RGHT \
  ),
  [1] = LAYOUT( \
    KC_ESC,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,     KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,    KC_DEL, \
    RGB_TOG,   RGBRST,  RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX,   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, \
    XXXXXXX,     RGB_MOD, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX,   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,        XXXXXXX, \
    _______,       XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,   XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, KC_PGUP, _______, \
    XXXXXXX,   _______,    _______,    _______,    XXXXXXX,       XXXXXXX, XXXXXXX, XXXXXXX,                   KC_HOME, KC_PGDN, KC_END \
  )
};

[0]とか[1]がレイヤーになっていて,MO(1)が割り当てられているキーを押しながら押すと[1]のレイヤーのキーになるという感じです. キーは左上から右に順に書かれていてキーボード上の位置と対応しているのですぐ分かると思います.

KC_から始まるキーコードがどのキーか表しているので,ここを書き換えればキーマップを編集できます. キーコードは以下のサイトで確認してください. Keycodes Overview

編集できたら,defaultのキーマップ同様以下のコマンドでコンパイルします.

make mint60:custom

コンパイルできたら,qmk_toolboxでmint60_custom.hexを選択し,キーボードに焼いて完了です.

右をマスターにする方法

分割キーボードは普通は左のキーボードをマスターとしてUSBを挿して使用するそうですが,右に挿して使いたい場合もあります. keyboards/mint60/keymaps/custom/config.hの23行目のコメントを外すと右がマスターになります.

#define MASTER_RIGHT

また,左右にそれぞれをマスターにしたキーマップを焼いてやることで,それぞれを独立したキーボードとして使うことができるようになります. TRSケーブルやコネクタが壊れた時や,左右の間隔をTRSケーブルを無視して広げたい時にするといいと思います.

最後に

TRSケーブルが奥まで挿さっていないのに気づかず,普通の状態で使えなかったときに,左右それぞれをマスターにして使っていました. Fnキーは左右それぞれ押さないといけないので,左のFnを押しながら右のキーを押したりできないのが辛かったです. あとUbuntuで使ったときに,左右のキーボードを順番に入力すると一瞬入力がフリーズしてしまっててUbuntuでは使い物になりませんでした. もしかしたら,複数キーボードを快適に使う方法があるかもしれませんが……

あと,QMK Toolboxを使わなくても

make mint60:custom:avrdude

とかで焼き込みできるって書いてる記事もあったんですが,自分の環境ではうまく行かなかったです.

電子工作初心者が思ったMint60製作注意点

完成図
Mint60完成図

TL;DR

・キーマップを決めて作る
・こまめに動作確認
・TRSケーブルは思いっきり挿す

はじめに

ずっと1000円ぐらいの安物キーボードを使っていて,そろそろHHKBやREALFORCE買うかと思っていたところ友人に自作キーボードを勧められました. その友人が2台目を作るということで,じゃあ一緒に作るかということになり,ゆかりキーボードファクトリー さんのMint60に挑戦しました.

今回は作っていて自分が難しかったところを書いていきたいと思います.

ちなみに自分は,スターターセット(マットクリア,静音赤軸,ABS Cubic Miami Blue)を購入しました.

eucalyn.hatenadiary.jp

組み立て

公式の組み立て手順や,先駆者のブログを確認しながら組み立てました.

eucalyn.hatenadiary.jp

qiita.com

道具を借りての人生初はんだでしたが,Mint60組み立て経験者と一緒に作ったので安心して進めることができました.

キースイッチの取り付けの際,キーを押し込みながら,はんだ付けしないとプレートから浮いてしまうので気を付けてください. 自分のは結構浮いてしまって,キーによって微妙に高さがずれてしまったので......

組み立て風景
組み立て風景1組み立て風景2

問題発生

全てのキースイッチをはんだ付けしたところで,確認のために,PCに接続したら全てのキーが問題なく動いていたので,完成した!と思って安堵していたら,TRSケーブルを接続したところ反応がなくなってしまい,めちゃくちゃ焦りました. 友人のMint60も似たような症状がでていたのですが,知り合いのはファームウェアの書き換えをしたりしているうちに直りました.

最初ははんだミスったのかとか,ファームウェアに何か問題があるのかとか考えてました.

4日間原因を探っていたところ,TRSケーブルを挿した状態でTRRSコネクタをテスターで導通チェックしているときに,導通しないはずの所が導通しているのに気づきました. もしかしてTRSケーブルが奥まで挿さってないんでは?と思い,結構力入れて挿してもやっぱり挿さらないので,そんなわけないよなって思ったんですが,ネットに上がってる写真を見たり,友人のMint60の写真を見るとやっぱり挿さってる......

もうこれで(TRRSコネクタが)終わってもいい...だからありったけを... と思いながら思いっきり挿したら挿さりました.

今までの苦労は何だったのか...... と思いましたが,テスターの使い方や,コネクタについてちょっと知ることができたので結果オーライだと思うことにしました.

ちゃんと挿さっていないTRSケーブル
ちゃんと挿さっていないTRSケーブル
奥まで挿さっているTRSケーブル
奥まで挿さっているTRSケーブル

もっと早く問題に気付くためには,やはり製作中にこまめに動作確認する必要があります. キースイッチを付けたあとはもちろんですが,TRRSコネクタとProMicroを付けたら1回USBケーブルとTRSケーブルに繋いでみた方が安心でしょう.

また,テスターを持っているのであれば,できるだけパーツ全てを導通チェックしてみるとより安心です. Mint60ではないですが,この記事に自作キーボードの導通チェックはこの記事を参考にしました.

x1.inkenkun.com

完成後に思ったこと

スターターセットには購入したキースイッチの他におまけで別の種類のキースイッチが一つづつ付いています. せっかくなのでこれを使って,バックスペースはミスって押さないように静音黒軸にしようとか,エンターは達成感を感じるように青軸にしようと何箇所か静音赤軸から変えてみました.

しかし,最初にキーマップをちゃんと決めずに,初期のキーマップの内容でキースイッチを付けてしまったため,キーマップを変えてから思ってたのと違うって箇所が出ちゃいました.

他にもやっぱり,スペースの位置変えた方が良かったとか後から思っても,変更するのは大変なので,最初にこれだっていうキーマップを決めておいてから作り始めた方がいいと思います.

今後

キーマップの改善とパームレストの自作,キーキャップの交換,キーボードケースの作成をしたいですね.

今までフルサイズのキーボードを使ってて,60%のキーマップに慣れてないので,慣らしつつ効率の良いキーマップを作っていけたらと思います.

パームレストについては,何も考えてなくて用意してなかったので,現在は代替案といて小説を置いています. 正直ジャストフィットしててもうこれでいいじゃんって思ってるんですが,さすがに見栄えが悪いのでなんとかしたいと思っています.

小説パームレスト
小説パームレスト

キーキャップについては,一部のキーがキーマップにあってなかったり,角度があってなかったりするので,どうにかしたいと思っています.

できればケースをCADとかで作って3Dプリンタで印刷とか......夢が広がリング!

後,TRSケーブルが挿さるようになるまで,左右のキーボードを別々にUSBで繋いで使ってたんですが,それについても記事をかけたらと思います.