OmniAICreator/Qiita-1.07M huggingface dataset:
【Linux】ネットワーク状態を調べるコマンド3つ

## はじめに
ネットワーク状態を調べる際によく使われるコマンドを３点ピックアップし、役割別に記載してみました。

## この記事が役に立つ方
- ネットワーク関連のコマンドは良く分からずコピペで済ませてしまっている方

## この記事のメリット
- 代表的なネットワーク状態を調べるコマンドの使い分けが出来るようになる


## 1.ネットワークが接続されているかを調べる`ping`
指定した宛先にパケットを送信し、返ってくるかを確認するため、**応答速度**を確認することも確認出来る。

パケットが返ってこないということは、ネットワークが正しく接続されていないと判断出来る。

```shell
$ ping 宛先ホスト名 or 宛先IPアドレス
```
止めない限り永遠に続いてしまうので、`Ctrl + c`で抜ける。

## 2.ポート番号の確認を行う`lsof`
**list open files** の意味。

どのポートを待ち受けているかの確認などで使用。
多機能で、オプションなしで使うと出力が多すぎるため`grep`コマンドと併用して絞り込んで使う例が多い。

```shell
lsof オプション 対象
```
以下のような使い方を良く見かける。

`-i`オプションでネットワークコネクションを出力。
`grep`で`LISTEN`を指定することで、外部からのアクセスを待ち受けている状態のものだけを抽出する。

```shell
lsof -i | grep LISTEN
```

多機能すぎるコマンドなのでもう一歩踏み込んだ内容はこちらの記事でご確認下さい。

代表的な使い方が端的にまとまっているので、実際にコマンドを試してみると分かりやすかったです。
[lsofコマンド入門 - Qiita](https://qiita.com/hypermkt/items/905139168b0bc5c28ef2)
@hypermktさんありがとうございます。

## 3.DNSで名前解決出来るかを確認する`nslookup`
DNSサーバーに対して**名前解決リクエスト**を送信する。

```shell
$ nslookup ホスト名 or IPアドレス
```

`DNS request timed out.`などのエラーが出ていれば、DNSの設定がおかしいかDNSが動作していないと判断出来る。

→より詳細に見たいときは`dig`コマンドを使用。

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

より詳細な情報については、下記書籍が大変分かりやすかったのでご一読下さい:relaxed:

おかげでイマイチ実感が沸かないまま使っていたコマンドの理解が進みました。

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [Amazon Web Services 基礎からのネットワーク＆サーバー構築 改訂版 | 玉川憲, 片山暁雄, 今井雄太, 大澤文孝 | 工学 | Kindleストア | Amazon](https://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%86%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89-%E6%94%B9%E8%A8%82%E7%89%88-ebook/dp/B06Y5ZSYY4/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)
- [lsofコマンド入門 - Qiita](https://qiita.com/hypermkt/items/905139168b0bc5c28ef2)
年末まで毎日webサイトを作り続ける大学生 〜45日目 JavaScriptで位置情報を取得する〜

##はじめに
こんにちは！@70days_jsです。

JavaScriptで位置情報を取得してみました。

今日は45日目。(2019/12/2)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day45.html

##やったこと
JavaScriptで位置情報を取得してみました。
取得した情報は
1. 緯度
2. 経度
3. 緯度/経度の精度
4. 高度
5. 方角
6. 速度
です。

実際にpcでやってみると、上3つだけ表示することができました。

![スクリーンショット 2019-12-02 23.49.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/ebd667c7-7013-4ec9-039e-75bcdafc2bd1.png)

```html
<body>
    <div id="test">緯度: </div>
    <div id="test2">経度: </div>
    <div id="test3">緯度/経度の精度: </div>
    <div id="test4">高度: </div>
    <div id="test5">方角: </div>
    <div id="test6">速度: </div>
</body>
```

```javascript
let geolocation = window.navigator.geolocation;

let option = {
    enableHighAccuracy: true
};

function error() {
    alert('エラーです。');
}

function success(position) {
    test.innerHTML += position.coords.latitude;
    test2.innerHTML += position.coords.longitude;
    test3.innerHTML += position.coords.accuracy;
    test4.innerHTML += position.coords.altitude;
    test5.innerHTML += position.coords.heading;
    test6.innerHTML += position.coords.speed;
}

if (geolocation) {
    geolocation.getCurrentPosition(success, error, option);
}
```

getCurrentPositionメソッドは引数を3つ用意してます。
第一引数は取得時の関数
第二引数は取得失敗時の関数
第三引数はオプションです。

##感想
位置情報はモバイルアプリを作るときには便利かもしれませんね。
いずれJavaScriptで作りたいと思っているので、そのときに利用しようと思います。

最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願い致します。

##参考
1. JavaScriptで位置情報を取得する方法(Geolocation API) (https://syncer.jp/how-to-use-geolocation-api)

とても分かりやすかったです。ありがとうございます！
誤り検出方法 Checksumについて


ブロックチェーン関連の実装を行なっていた際に、チェックサムで引っかかり「アドレスがinvalidです」と表示されることがあった。その際に、「チェックサムって誤り検出のやつだよな?仕組み知らないわ」となったので、少し調べて簡易的に実装してみた。

## チェックサムとは?
チェックサムとは、データの信頼性を検査するための算出した値のことを言う。この値を元に、データが適切なものであるかを調べることができる

非常に単純な誤り検出方法の１つで、誤り検出の精度は低いが原理が簡単で容易に実装でき、計算コストも低いため、簡単な誤り検出方法として広く普及している

データの誤り検出の方法としてハッシュ関数を利用する方法もあるが、誤り検出のために送信する必要のあるデータのサイズが大きく、処理負荷が大きい。しかし、誤り検出の信頼性はチェックサムを利用する場合よりも高い。

## チェックサムの求め方
チェックサムの求め方については、様々な手法があるが簡単な方法としては、データ列を整数値の列としてみなし和を求め、これをある定数で割った余りを検査用データとするものがある。

### チェックサムの計算の例
`[0xc0 0xA8 0xFF 0x58]` から1バイトのチェックサムを算出するのは、
```0xc0 + 0xA8 + 0xFF+0x58 = 0x2BF```を求め、0x100で割った余りの0xBFがチェックサムになる

データのサイズが大きい場合は、一定の大きさごとに区切ってチェックサムを算出付加する方法が利用される

## チェックサムを利用した誤り検知の実装
文字列に関してチェックサムを利用したデータの作成の関数と、誤り検出を行う関数を簡易的に実装した。

### チェックサムを付加したデータを作る関数

文字列を整数値に変換して、その和を100で割ったものをチャックサムにし、データに付加して送信用のデータを作成する関数

```ruby

def make_data(raw_data)
    checksum = 0
    raw_data.unpack("C*").each do |byte|
        checksum += byte
    end
    return raw_data.unpack("C*").push(checksum / 100)
end
```

### 付加されたチェックサムを確認する関数

受信したデータのチェックサムを確認し、適正なデータであれば表示し、データが破損していれば、その旨を表示する関数

```ruby

def check_data(data)
    sent_checksum = data.pop
    checksum = 0
    data.each do |byte|
        checksum += byte
    end
    return sent_checksum == checksum / 100
end

def show_data(hex_data)
    data = ""
    if(check_data(hex_data)) then
        hex_data.each do |byte|
            data += byte.chr
        end
        p data + ":データは破損していません"
    else 
        p "データが破損しています"
    end
end
```

### 利用例

```ruby

raw_data = "Hello"
send_data = make_data(raw_data)

show_data(send_data) # => "Hello:データは破損していません"


raw_data = "Hello"
send_data = make_data(raw_data)

send_data[1] = 0 # 通信経路で意図的にデータを書き換える

show_data(send_data) # =>"データが破損しています"
```

今回の例では、利用できるchecksumは0から99の100通りである。そのため、通信経路で改ざんや破損があった際に、必ず検出することができるとは限らない。和を割る数を100から大きいものにすれば、誤りを検出できる確率は高くなるが、検出に必要なデータサイズが大きくなってしまう。そうなってしまうと、データのハッシュ値を利用する方がより信頼性の高い誤り検出ができる。あくまで簡易的な誤り検出であることがわかった。
<br>また、アルゴリズム的にもチェックを用いる方法では矛盾が生じないような改ざんも行うことができる。これに対して、ハッシュ関数では基本的にこのようなことを行うことができない。

## まとめ
個人的に気になったことを簡単にまとめた。誤り検出に関しての知識がほとんどないので、これを機に理解を深めたい。
TJBot / TJBot zeroってなぁに？

この記事は[TJBot Advent Calendar 2019](https://qiita.com/advent-calendar/2019/tjbot) １日目の記事です。

１日遅れですが、寄稿します。

# TJBotって何？
IBM US ResearchがIBM Watsonを利用・学習するため制作した
ダンボール紙を利用したロボットをDIYするためのプロジェクトです。
[TJBot - IBM Research](https://www.research.ibm.com/tjbot/)

[![TJBot Hello world](http://img.youtube.com/vi/X9ZmcTP_QJI/0.jpg)](http://www.youtube.com/watch?v=X9ZmcTP_QJI)

この動画の子は2017年のBMXUG冬の勉強会 ハンズオンイベントでハンズオン参加者へ配布された日本版のTJBotダンボールをもとにして制作したものです。

3Dプリンタで出力できる3Dモデルデータや、レーザーカッターで自分でダンボールをカットすることができる図面データがオープンソースで公開されている為、ご自身で同じものを出力・カスタマイズしてロボットを作ることができます。

## 何がはいっているの？

**夢が詰まっています**

TJBotには、Raspbeery pi 2Bがメインにキットとして組み込まれ、
RaspbianをベースにPython / Node.js / Node-REDなど好きな言語でプログラムを書けるようにチュートリアルが公開されています。

# TJBot zeroって何？
TJBot zeroは2018年冬に発表、IBM Cloud Community Summit 2018で初めてコミュニティでの提供が始まったボール紙を利用したロボットをDIYする為のプロジェクトです。
[IBM Developer - 日本版 TJBot - プログラム可能なロボット (TJBot zero)](https://ibm.biz/tjbotjp/)

[![こんにちは、ぼくの名前はTJBotです](http://img.youtube.com/vi/d2wof2XLJUw/0.jpg)](http://www.youtube.com/watch?v=d2wof2XLJUw)

IBM Cloud Community Summit 2018のイベントからIBMさまのスポンサーシップにより、型紙を無料で提供いただきハンズオンを定期的に開催しています。

この動画の子はレーザーカットしたボール紙をベースに組み立てたTJBotで、
ハンズオンで配布している版とは紙の強度が異なりますが、中身はすべて同じものです。

## 何が違うの？

次の写真を見てください。
執筆者がお気に入りで使用させていただいている写真なのですが、
左からTJBot zero、TJBot、ステンドグラス版TJBotで、
ほぼ同じ位置にならんでいますが、背の高さが違いますね。
そうです。85%のサイズで日本版TJBotはコンパクトになっているんです。

TJBot zeroはIBMerの有志と、コミュニティーメンバーが手を取り合ってハンズオンを実現するために作ったキットで、85%への縮小化、Raspberry pi Zero WHを使用したメイン基板のサイズ縮小化、ブレッドボードを使用した音源の安定・サイズ縮小化を行っています。
そして日本のハンズオンでは、Node-REDを利用したフローとSDカードイメージを公開することで均一的なハンズオンができるようになりました。

![D2TnmYGU8AAnVwx.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126158/bca277cd-d7c8-e543-6efa-0f0df2d25eeb.jpeg)

# TJBotってなにができるの？

TJBotzeroハンズオンで主にやっていることを上げていきます。

- 頭のLEDを光らせる
- 左目のカメラで顔に反応して腕をふる
- 音声をしゃべる
- 翻訳を行う
- 画像を認識する

Raspberry pi 上でのみ完結する機能と、Cloudを利用して動く機能と複数の組み合わせで機能を実現しています。

# ご自身でやりたいことを試しに作ってみませんか？

TJBot / TJBot zeroは自由にカスタマイズすることができるキットです。
もちろん表面を可愛くデコレーションしたすることもできます。

１１月に実施したハンズオンでは小学生の女の子が余った型紙でこんなにかわいくデコレーションしてくれました
![P_20191124_155920_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126158/c615b8bc-cf4f-647c-e145-337f8c7f604a.jpeg)

[TJBot Advent Calendar 2019](https://qiita.com/advent-calendar/2019/tjbot)では、こんなデコレーションしたよ！こんな機能試してみたよ！をはじめ、ハンズオンでのノウハウなどもアウトプットできればと思います。

ぜひTJBot / TJBot zeroで工作・IoT・AIを使って遊んでみてくださいね
CELOG(.clg)ファイルをEvent Tracing for Windows(.etl)ファイルに変換する

[Windows Embeded Compact 7で出力されるCELOG(.clg)ファイル](http://www.stprec.co.jp/ceblog/2012/08/16/celogflush-exe-%e3%81%a8-kernel-tracker/)のグラフィカルに内容を表示するには、Remote Timeline Viewerが必要です。

Windows Performance Toolkitに含まれるcelog2etw.exeは、(今は亡きWindows Phone用として)CELOGファイルをETWファイルに不完全ながら変換できるようです。
ETWに変換すると、[Windows Performance Analyzer](https://www.microsoft.com/ja-jp/p/windows-performance-analyzer/9n0w1b2bxgnz)で開けるようになります。
変換してもカーネルのイベントは完全には変換できず、CPU使用率ぐらいしか有用な情報は得られませんでした。
(機密ではないCELOGが無いので、残念ながらスクリーンショットはありません。)

## Windows ADK のダウンロード
Windows Performance ToolkitはWindows アセスメント & デプロイメント キットに含まれています。
ADK for Windows 10からはcelog2etw.exeが含まれないので、Windows 8/Windows 8.1用をダウンロードします。

[Windows(R) 8 用 Windows アセスメント & デプロイメント キット](https://www.microsoft.com/ja-JP/download/details.aspx?id=30652)

[Windows 8.1 Update 用 Windows アセスメント & デプロイメント キット (Windows ADK) ](https://www.microsoft.com/ja-jp/download/details.aspx?id=39982)

## CeLog2ETW の使用方法
コマンドラインなので、下記のように実行します。

```
celog2etw celog.clg
```

詳しくはC:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\CeLog2ETW.chm
にヘルプがあります。

## Windows Performance Analyzer
Windows Performance Toolkitに含まれるWindows Performance Analyzerでもいいかもしれませんが、最新バージョンは[Microsoft Store](https://www.microsoft.com/ja-jp/p/windows-performance-analyzer/9n0w1b2bxgnz)にあるので、それを使うのがいいでしょう。
[exercism.io]VSCodeでJestのデバッグをする方法


## 概要
[exercism.io](https://exercism.io/)のJavaScriptコースでJestのデバッグをする方法を紹介します。
といっても結局はVSCodeでJestのデバッグをする方法です。

## 方法
**1.launch.jsonに以下の記述をする。**
`program`のパスはjestの実行ファイルがある場所に変えてください。

```json

{
	"version": "0.2.0",
	"configurations": [
		{
			"type": "node",
			"request": "launch",
			"name": "Jest Debugger",
			"program": "${workspaceFolder}/javascript/list-ops/node_modules/.bin/jest",
			"args": [ "${fileBasenameNoExtension}" ],
			"cwd": "${workspaceFolder}/${relativeFileDirname}",
		}
	]
}

```

**2.デバッグしたいファイルを開いた状態でDebugを実行する**

<img width="441" alt="how to debug.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215694/04d0a5f4-5f74-2ada-1bbb-52b2f658ea68.png">


## 解説
気が向いたときに補足します。

`program`がデバッグ実行時に呼ばれる処理です。
`args`が処理が呼ばれる際に渡される引数です。

なのでデバッグ実行時にはjestに現在開いているファイル名を渡しています。

とりあえず雑に参考資料を貼っておきます。
https://code.visualstudio.com/docs/editor/variables-reference
https://code.visualstudio.com/Docs/editor/debugging
ReactでChrome拡張を開発して公開したお話

## はじめに
この記事は、[KIT Developer Advent Calendar 2019 2日目](https://qiita.com/advent-calendar/2019/kitdev)になります。
Advent Calendarの時期が来ると、今年ももう少しで終わるな〜っていう実感が湧いてきますね。

それでは、ReactでChrome拡張を開発して公開したお話について書いていきます!

## 今回開発したもの

タブを管理する[Active Tab Lister](https://chrome.google.com/webstore/detail/active-tab-lister/iknnnkjhaepgeeakmlpenangddfckdca)というChrome拡張になります。

![tab.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190875/a0ee975f-a24f-c374-eb92-369e42c5089a.jpeg)

## 開発背景

Chromeを使っていて、以下のことに困っていました。

1. 前に見ていたページを探したいと思った時に、開いているタブが多いと、ページタイトルが見切れてしまい切り替えることが困難
1. 見ているページをスマートフォンやiPadですぐに見たいときに、Slackなどで送るのは手間
1. Chromeのタブをたくさん開いていると、メモリを沢山消費しているので開いているが不要なタブをサクッと削除したい
  - しかし、タブを沢山開いているとFaviconしか表示されないような状態になってしまい、不要なタブの判断がしづらい

これらの問題を解決するため、

1. 開いているタブの一覧を表示して、タップするとそのページに遷移できるようにする
1. 開いているタブのQRコードを読み取ることで、スマートフォン・iPadでも別のサービスを経由することなく瞬時に開くことができるようにする
1. 複数ページを開いている際に「いくつタブを開いているのか」すぐに見ることができ、タイトルを見て不要だと思ったタブはDELETEボタンで削除できるようにする

という仕様を満たすように開発を進めていきました。


## manifestファイルの書き方

Chrome拡張の開発において記入が必須のマニフェストファイル(manifest.json)の書き方については、以下の記事が大変分かりやすかったです。

- [Chrome 拡張機能のマニフェストファイルの書き方
](https://qiita.com/mdstoy/items/9866544e37987337dc79)


## Chrome拡張の実行方法

1. `npm run build`をすると、ルートディレクトリに`build`ディレクトリを作成
2. `chrome://extensions/`へアクセスし、`パッケージ化されていない拡張機能を読み込む`をクリックします。
3. 拡張機能のディレクトリを選択できるので、先ほど作成された`build`ディレクトリを追加します。
(manifest.jsonは`public`ディレクトリにもありますが、`build`ディレクトリを選びます)

※ 普段のフロントエンド開発の要領で`npm start`, `yarn start`をしてもChrome拡張の動作確認は出来ないので注意です。

## デバッグについて

### Webアプリ開発と同じ点
- Chrome拡張のアプリでも[Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools?hl=ja)を使って検証することが出来ます

### 異なる点
- [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja)を使用することが出来ない
  - そのため、Stateの確認などは少々手間になってしまいます

## 公開手順

公開手順は以下のようになっています。 
[Publish in the Chrome Web Store](https://developer.chrome.com/webstore/publish)より

1. 作成された`build`ディレクトリをzip形式に圧縮する
2. [ChromeDeveloperDashboard](https://chrome.google.com/webstore/developer/dashboard)にアクセスし、5ドルの登録料を払います(年会費制ではないので一度支払えばOKな点も良いですね)
3. 「新しいアイテムを追加する」をクリックして、zipファイルをアップロードします
4. アプリケーションの詳細な説明を追加します。

また、少なくとも以下の画像が必要です。  

  - ストアに表示する128x128のアイコン(ファビコンを再利用できます)
  - アプリの動作を示すために、1280x800または640x400のスクリーンショット,YouTubeビデオのいずれか
  - Chromeウェブストアの壁に表示される440x280のタイルアイコン 

(ここがちょっと大変ですが公開まであと少しなので、もうひと頑張りです!!)
その後、1~2日ほど待って審査が通れば、公開されます。

## 終わりに
Chrome拡張は公開する際に厳しい審査もなく、自分のアイデアを簡単に形にして届けることが出来ます。
普段Chromeを使っていて、こんなものがあれば便利だなって思うことがあれば作成してみるのも良いですね！

開発リポジトリは[こちら](https://github.com/tomu28/ActiveTabLister)になります。
IssuesやPR大歓迎です😄
android開発で実機デバイスからAPIを叩けないときのトラブルシューティング

こんにちは

最近ノリでdjangoAPIを作り始めた雰囲気エンジニアです。

ラズパイでサーバー構築したのですが、djangorestframeworkをうまくインストールできず、まずはローカルで環境構築してdockerでデプロイしたいななんて思ってます

…情弱の僕には厳し（ｒｙ


とまあそんなこんなで、ローカルにてAPIを作り始めたのですが、お決まりの
python3 manage.py runserver
で、サーバーを動かすじゃないですか
WEBからならAPIを叩けるのに実機ANDROIDからは叩けません

①python3 manage.py runserver 0.0.0.0:80でサーバーを起動すること
~~理由はよくわかりません~~
android側では192.168.x.xなどのパソコンのプライベートIPを叩きます

②<font color="red">Error: That port is already in use.</font>
ポートがすでに使われていますというエラーが出たら（①のあとによく出てきます）

sudo lsof -i:80

これで起動中の80番ポートを使っている機器が出てきます。

そしたら

sudo kill -9 \<PID>(4, 5ケタの数字）

これで全部ころしてください

③java.net.ConnectException: failed to connect to /192.168.x.x (port 80): connect failed: ENETUNREACH (Network is unreachable)

それでもまだしつこく出てくるエラーがあります
とくにうちはwifiの調子が悪いので

この場合は
・実機デバイスがWIFIにつながっているか（ネットに繋ぐなりしてみてください）
・パソコンがWIFIにつながっているか
・パソコンのプライベートIPが変更されてしまっていないか


備忘録的に活用したいと思います
Pythonで最新のMACアドレスベンダーDBをoui.txtから生成する

## はじめに
- MACアドレスは機器固有のものであり、識別するのに便利
- MACアドレスの最初の6桁はベンダーコードといい製造メーカーのIDになっている
- IEEEが管理していて、IEEEのサイトで調べることができる

## やりかた
以下のIEEEのページからベンダー一覧をダウンロード

http://standards.ieee.org/develop/regauth/oui/oui.txt

あとは以下の動けばいいコードを実行するとMACアドレス6桁がキーの辞書型が出来上がります。

```python
data = {}
with open('oui.txt') as f:
    i = 0
    for s_line in f:
        i = i + 1
        if i < 5:
            continue
        p = i % 6
        if p == 0:
            mac = s_line.split("     (base 16)\t\t")[0].strip("\n")
            inc = s_line.split("     (base 16)\t\t")[1].strip("\n")
            data[mac] = [inc]
            if inc == "Private":
                i = i + 3
        if p == 3:
            ccltd = s_line.strip()
            data[mac].append(ccltd)         


print(data["000C29"])
```

実行結果

```
[root@pc python]# python3 mac.py 
['VMware, Inc.', 'US']
```

あとはjsonにするなり、DBに格納するなり自由に


## おわりに
　検索できるサイトはあってもローカルで保持したい場合とかはあると思うので（あったので）
サーバー上で起動したJupyter notebookをリモートで開く

#sshでサーバーに繋ぎ
```
nohup jupyter notebook >/dev/null 2>&1 & --no-browser --port=00000
```

#手元のTerminalで
```
ssh -N -f -L 12345:localhost:12345 -i ~/.ssh/id_rsa -p 00000 tapioca@000.000.00.000
```

#Chrome
```
localhost:12345
```
driver failed programming external connectivity on endpointとなった時の対処法（redwood-broker 編）

# 概要
`docker-compose` でなんらかの理由により強制終了し、再度起動しても `driver failed programming external connectivity on endpoint` と言われる時の対処法

# 原因
他のプロセスが使用しようとしているポート番号とかぶっています。

# 多くの場合
まずは[こちら](https://qiita.com/ponsuke0531/items/f3490f571b5eee16ea87)をご覧ください。

# それでも解決しない時
1. 何がプロセスを利用しているのか調べる
1-1. ネットワークユーティリティを起動（mac OS High Sierraでは、 `/System/Library/CoreServices/Applications/` にあります）
1-2. Portscanタブをクリック
1-3. 確認したいポートを指定して、 `scan` を実行
2. `redwood-broker` が出て来たら、 `Docker` を再起動、Macを再起動しても `redwood-broker` は消えませんでしたが、 `Docker` を再起動すると消えます。
3. その他の場合は、Googleさんに聞いてください。
Markdown記法、はじめました。


#はじめに
Advent Calender面白そう！でもMarkdown記法なんもわからん...ってなったので、備忘録がてら記録に残しました
みんなもMarkdown記法覚えて記事投稿してほしい(同級生のみんな）
これだけできれば書けるから。たぶん。  

##見出し
「#」を使います。#が増えるとどんどん小さくなります  

    #見出し
「#」が増えると小さくなります。HTMLでいうh1,h2,h3...と同じです  
#見出し
##小見出し１
###小見出し2  

    #見出し
    ##小見出し１
    ###小見出し2  
1段階目と2段階目は==とか--で区切るのでもいけるらしい

##段落と改行
段落は改行して一行空け、改行は文末に半角スペース二つを入力
(-は半角スペース)

    一段目--
    二段目  

一段目  
二段目
##強調  
アスタリスクで挟む  

    *もっとだ...!*
    **もっと強く...!**  

*もっとだ...!*
**もっと強く...!**  

##リンクの貼り付け  
[]でタイトル(?)、()でURLを囲みます  

    [ぼくのTwitter](https://twitter.com/chaha_____n) 

 [ぼくのTwitter](https://twitter.com/chaha_____n) 

##ソースコード
一番大事なやつ。先頭に半角スペースを四つ入れる  
-を半角スペースとして
----print("Hello,World!")    

    print("Hello,World!")

##引用
「>」と半角スペースを置くといける 二つ重ねるとネストできる  

    >引用元1
    >>引用元2 
    >>>引用元3 

>引用元1
>>引用元2
>>>引用元3  

#終わりに
初めてのMarkdown記法、初めてのQiitaなので、いろいろ調べつつなんとか
書き終わりました...それでも一時間弱くらいでこの記事できたし積極的に投稿したい！
MIDIって

#MIDIのMの字も知らない人の備忘録
##MIDIって
###要するに音声、音楽に関するあらゆるもの（ハード、ソフト問わず）の規格
例えばMIDIメッセージと呼ばれるものは楽器を使った演奏の際の音程、長短、鍵盤の押し方など
細かく定義されたデータを送信する仕組みであったり

MIDI端子といわれるレガシーデバイス（自分がそういうハードに触れないせいかも）
としか思えない端子による通信方法の規格が存在する（贅沢に5pinもある）

##おしまい
Amazon SQSからAWS Lambdaを起動する構成のTerraform

## はじめに
SREエンジニアやってます。@hayaosatoです。
今回はサーバレスなアーキテクチャを組む上で超便利なAWS Lambda(以下、Lambda)をAmazon SQS(以下、SQS)から呼び出してみたいと思います。
コードは[こちら](https://github.com/hayaosato/aws-sqs-lambda)

## アーキテクチャ

## Lambda
Lambdaのリソースは以下のように作ることができます。
アプリケーションはslack通知のスクリプトにしました。

```tf
// IAM Role for Lambda Function
resource "aws_iam_role" "default" {
  name               = var.service_name
  description        = "IAM Rolw for ${var.service_name}"
  assume_role_policy = file("${var.service_name}_role.json")
}

resource "aws_iam_policy" "default" {
  name        = var.service_name
  description = "IAM Policy for ${var.service_name}"
  policy      = file("${var.service_name}_policy.json")
}

resource "aws_iam_role_policy_attachment" "default" {
  role       = aws_iam_role.default.name
  policy_arn = aws_iam_policy.default.arn
}

// Lambda Function Resources
resource "aws_cloudwatch_log_group" "default" {
  name              = "/aws/lambda/${var.service_name}"
  retention_in_days = 7
}

data archive_file "default" {
  type        = "zip"
  source_dir  = "src"
  output_path = var.output_path
}

resource "aws_lambda_function" "default" {
  filename         = var.output_path
  function_name    = var.service_name
  role             = aws_iam_role.default.arn
  handler          = "lambda_function.lambda_handler"
  source_code_hash = data.archive_file.default.output_base64sha256
  runtime          = "python3.6"
  environment {
    variables = {
      SLACK_API_KEY = var.SLACK_API_KEY
    }
  }
}
```
Lambda関数をTerraformで作成する際は是非ともarchiveリソースの`archive_file`を利用していただきたいです。
これを利用することでzipを生成してそれをそのままLambda関数に適応できるので非常に楽です。
つまりはこの構成をそのままCIに組み込んでCIツールから`terraform apply`すればいい感じですね。

## SQS
SQSのリソースは以下のように作ることができます。

```tf
resource "aws_sqs_queue" "default" {
  name                        = "${var.service_name}.fifo"
  fifo_queue                  = true
  content_based_deduplication = true
}
```

## SQSとLambdaの連携
TerraformにはLambdaのトリガ設定のためのリソースとして[lambda_event_source_mapping](https://www.terraform.io/docs/providers/aws/r/lambda_event_source_mapping.html)というものがあります。
今回はこれを使います。

```tf
resource "aws_lambda_event_source_mapping" "default" {
  event_source_arn = aws_sqs_queue.default.arn
  function_name    = aws_lambda_function.default.arn
}
```
また、このリソースは現在SQSとDynamoDB,Kinesisにしか対応していないため、SNSからの連携はできません(コードにSNSと連携させようと作ったリソースの残骸が。。。)
`event_source_arn`に指定できないリソースのARNを入れてしまうと、無限に`creating...`になります。
ただ、S3からのイベントは普通に実行できます。



## 結果
作ったリソースで実際にキューを発行して実行してみます。
![スクリーンショット 2019-12-02 23.08.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/aef134c8-4264-e0e2-03cb-d7b3f1478a53.png)
できました
<img width="263" alt="スクリーンショット 2019-12-02 23.08.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/7bd50874-458b-d7b5-f8dc-8262fbaebc0a.png">


## 最後に
やっぱりサーバレスっていいですね

## 参考
- [Terraform Documentation](https://www.terraform.io/docs/index.html)
- [TerraformでLambdaをデプロイするときの小技](https://qiita.com/Pampus/items/038004afb606952e7cd6)
Ubuntu環境構築メモ_Tool

## 入れておきたいTool一覧

### CopyQ 
- クリップボード管理
- https://github.com/hluk/CopyQ

```
sudo add-apt-repository ppa:hluk/copyq
sudo apt update
sudo apt install copyqsudo apt-get update
```

### git
- レポジトリ管理
- https://linuxize.com/post/how-to-install-git-on-ubuntu-18-04/

```
sudo apt update
sudo apt install git
git --version
```

### VSCode
- エディタ
- https://qiita.com/yoshiyasu1111/items/e4db676e846897f8d554

### AzureDataStadio
- DBクライアント
- ダウンロードしたdebファイル名をdpkgで指定する
- https://docs.microsoft.com/ja-jp/sql/azure-data-studio/download?view=sql-server-ver15

```
$ cd ~
$ sudo dpkg -i ./Downloads/azuredatastudio-linux-<version string>.deb
$ azuredatastudio
$ sudo apt-get install libxss1
$ sudo apt-get install libgconf-2-4
$ sudo apt-get install libunwind8
```

### docker
- 環境構築用1
- https://docs.docker.com/install/linux/docker-ce/ubuntu/

```
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
$ apt-cache madison docker-ce
$ sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
$ sudo docker run hello-world

```

### docker-compose
- 環境構築用2
- https://docs.docker.com/compose/install/

```
$ sudo curl -L 
$ "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
```
UnityとスポナーとTerrainとわたし

# はじめに

[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の二日目の記事です。

今回はUnityのTerrainでフィールドを生成し、地面の高さにかかわらず地面から一定距離に敵をスポーンさせる方法を紹介します。

## じっそー

```spawner.cs

int posx = 500;
int posy = 500;
float height = Terrain.activeTerrain.terrainData.GetInterpolatedHeight(
                posx / Terrain.activeTerrain.terrainData.size.x,
                posz / Terrain.activeTerrain.terrainData.size.z);
```

これで、x座標:500,z座標:500 でのTerrainの地面の高さ(y座標)を変数heightに取得できます。

これを利用し、posx,posyを乱数などで指定することでTerrain上の(x,y,z)を取得し、Vector3型で三次元座標で値を返すことで、

```
Instantiate(target, spawnPos(), transform.rotation);
```
このようにすることで、targetという変数にはいった敵をスポーンさせることができますね。
第二引数がさきほどの、Vector3型の値を返す関数ですね。

## 注意

返すVector3型の値を`return new Vector3(posx,height,posy)` のようにしてしまうと、オブジェクトのサイズによっては埋まってしまう可能性が考えられるため、heightに少し値を加算し余裕を持たせる方が、安心できます。

良きUnityライフを
ARM64をターゲットとしたGoのクロスコンパイル

[SENSYN ROBOTICS](https://www.sensyn-robotics.com/)(センシンロボティクス)の中山です。
Webアプリやそのインフラ周り、Web側とドローンの接続を行うデバイスドライバ的なモジュールを担当しています。

今回は、ドローン内部で動かすソフトウェアにGoを使った話です。上記の担当範囲から外れているように見えますが、そういうこともあります。

# なんのために?

ドローンといっても色々あるのですが、今回はARM64のCPU(NVIDIA TX1)が載ったドローンです。CPUの上ではUbuntu 16.04が動いています。具体的には[SENSYN DRONE HUB](https://www.sensyn-robotics.com/solution/sensyndronehub)というドローンです。

このドローンは、あらかじめ設定しておいた時刻になると自動的に基地から離陸し、事前に設定しておいたルートを飛行して動画・静止画を撮影し、基地に返ってきます。返ってきたら自動的に充電して次回の飛行に備えつつ、撮影したデータを自動的にクラウドにアップロードします。

つまり、ドローンの存在を意識せずにドローンによる設備点検や警備・監視ができるソリューションです。

今回、Goを使ったのはデータをクラウドにアップロードするモジュールで、ドローンの内部で動いています。

# なぜGoなのか?

当初はGoを使うつもりはなく、Pythonで書く予定でした。ただ、Ubuntu上には既にドローンの制御機構が構築されており、そちらが一部にPythonを使っている都合上、既存の環境への干渉は絶対に避ける必要があります。ところが事前に入っているUbuntuにはpipすら入っておらず、環境分離ツールを入れること自体が難しい状況です。そのため、既存の環境を汚さずに新しいモジュールを入れるのは不可能ではないにしても、非常に面倒でした。

Pythonが使えないとなると…と悩んだ末、Goならシングルバイナリにできるので既存環境への干渉を避けたいときに理想的ではないか、と気づいて採用を決定しました。ARM64 Linux対応、というのも必須条件ですが、Goならこれも満たしています。

上記の理由だけならC++でも良かったのですが、Goの方がメンテできるひとが将来的に多くなりそう、というのもあります。

# 実際にやってみると?

環境を汚したくないので、コンパイル環境をドローンの中に作るわけにはいきません。そうなると、必然的にクロスコンパイルが必要になります。手元の開発環境で試行錯誤すると後が怖いので、Dockerを使いました。

```
docker run \
  -v $(pwd):/go \
  --rm \
  -it \
  dockercore/golang-cross:1.12.7 \
  sh -c 'GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build src/main.go'
```

(少し前の話なので、バージョンは古めです)

```
# runtime/cgo
gcc_arm64.S: Assembler messages:
gcc_arm64.S:27: Error: no such instruction: `stp x19,x20,[sp,'
gcc_arm64.S:28: Error: no such instruction: `stp x21,x22,[sp,'
gcc_arm64.S:29: Error: no such instruction: `stp x23,x24,[sp,'
gcc_arm64.S:30: Error: no such instruction: `stp x25,x26,[sp,'
gcc_arm64.S:31: Error: no such instruction: `stp x27,x28,[sp,'
gcc_arm64.S:32: Error: no such instruction: `stp x29,x30,[sp,'
gcc_arm64.S:33: Error: too many memory references for `mov'
gcc_arm64.S:35: Error: too many memory references for `mov'
gcc_arm64.S:36: Error: too many memory references for `mov'
gcc_arm64.S:37: Error: too many memory references for `mov'
gcc_arm64.S:39: Error: no such instruction: `blr x20'
gcc_arm64.S:40: Error: no such instruction: `blr x19'
gcc_arm64.S:42: Error: no such instruction: `ldp x29,x30,[sp],'
gcc_arm64.S:43: Error: no such instruction: `ldp x27,x28,[sp],'
gcc_arm64.S:44: Error: no such instruction: `ldp x25,x26,[sp],'
gcc_arm64.S:45: Error: no such instruction: `ldp x23,x24,[sp],'
gcc_arm64.S:46: Error: no such instruction: `ldp x21,x22,[sp],'
gcc_arm64.S:47: Error: no such instruction: `ldp x19,x20,[sp],'
```

エラーになりました…。

色々調べて、

```
FROM dockercore/golang-cross:1.12.7

RUN apt-get update \
    && apt-get install -y gcc-aarch64-linux-gnu
```

というDockerfileを作り、このイメージで`go build`しても、同じ結果…。

更に調べ回って、上記のDockerイメージに加えて`CC=aarch64-linux-gnu-gcc`をコマンドラインに足した

```
docker run \
  -v $(pwd):/go \
  --rm \
  -it \
  my-golang-image \
  sh -c 'GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build src/main.go'
```

で最終的に通るようになりました。

# 結論

* 環境を汚さないためにGoを使うのは有効
* クロスコンパイルはできるようになれば簡単けど、そこまでがちょっと大変
* Dockerを使うとトライ&エラーを気楽にできて便利
* ARM64 Linuxをターゲットにクロスコンパイルするなら`gcc-aarch64-linux-gnu`を入れて、`CC=aarch64-linux-gnu-gcc`を環境変数に設定する
初めてのBootstrap

#初めてBootstrapを使う際に確認するサイト
ブログやECサイトなどを作るときに、
cssが設定された状態であるBootstrapは大変便利です。
classを任意のものにすれば、デザインも幅も自由自在なので
手っ取り早くサイトを作りたい、
フロントデザインよりバックエンドやフロントエンドの開発を
作り込みたい人にはオススメでしょう。

今回はそんなBootstrap使い始めの人に対してBootstrapのサイトの見方を紹介します。

##Bootstrapのホーム
https://getbootstrap.com/
<img width="1103" alt="スクリーンショット 2019-12-02 23.05.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360753/c316d733-7f4b-e1f4-6a24-070779c2270e.png">
getstartedでhtmlコードをコピペするだけでBootstrapが導入可能なページへ、
downloadでbootstrapを構成しているファイルをDLすることができ、自分で好きなように変えられます。
初心者はgetstartに乗っているcssやjsを当てられるurlを使用する事をオススメします。

##Bootstrapのパーツ
https://hackerthemes.com/bootstrap-cheatsheet/#text-info
このチートシートを見る事で、
navvarやcontainerやbadgesなどclassが当たったパーツが一まとまりになっています。
極論これらを組み合わせる事で好きにサイトを作ることが出来るのでコピペしながら遊んで覚えましょう。

##Bootstrapで出来るサイトの例
https://getbootstrap.com/docs/4.4/examples/
blogやshoppingなど目的に合わせたサイトがまとまっています。
自分の目的に合わせたサイトのhtmlをみながら学ぶと効率が良さそうです。

##Bootstrapで使えるicon
https://icons.getbootstrap.com/
iconもBootstrapにはあります。
好きなアイコンを使ってみやすいサイトを心がけましょう。

##BootstrapのGrid
https://getbootstrap.com/docs/4.4/layout/grid/
Bootstrapでは有名なGridシステムがまとめられています。
簡単に言うと、横幅を12分割で考えるのがBootstrapです。
それらのうち幾つをcontainerに割り当てるかなどで占有面積を導き出すことができます。

#Bootstrapはまず使ってみるべし
htmlやcssの知識がつきづらいBootstrapですが、
目的に合わせるのであればサクサク作れて良いと思います。
初心者ほどまずは触って抵抗をなくすことも大事かと思います。
いま再びのシステムまぎちゃんへの道～並列処理環境を手に入れよう～

#並列処理環境をゲットする。その前に
前回、Fedoraのインストールまで行いました。
では、次に並列処理環境を入れたいのですが、
まずは、各種アプリケーションやライブラリのアップデートをします。

```
# dnf update
```

これで、環境がアップデートされます。

#やっと並列処理環境が入る

これも簡単です。

```
# dnf install mpich mpich-devel mpich-doc
```

をインストールすると自動的に依存関係があるパッケージを落としてきてくれます。
あとは、インストールが終わるのを待つだけ。

ついでなので、OpenMPIを入れます。これも楽勝

```
# dnf install oepnmpi openmpi-devel
```

もう一つおまけに libomp　をいれてスレッド並列環境を手に入れましょう。

```
# dnf install libomp libomp-test libomp-devel
```

とりあえずOpenMPだけテストしてみます。

```
[evakichi@localhost OpenMP]$ cat test.c
#include <stdio.h>
#include "omp.h"

int main()
{

#pragma omp parallel
{
int rank = omp_get_thread_num();
int size = omp_get_num_threads();
printf ("hello i am %d/%d\n",rank,size);
}
}
[evakichi@localhost OpenMP]$ gcc -fopenmp test.c
[evakichi@localhost OpenMP]$ ./a.out
hello i am 3/4
hello i am 0/4
hello i am 1/4
hello i am 2/4
[evakichi@localhost OpenMP]$
```

OKですね。

さて終了。MPIの動作確認はまた後程。というか全台変更しないといけないのですぐには試験できません。あしからず。
rails独学でポートフォリオを作成中

こんにちは！現在転職活動中のバスケンです。
初めての投稿です！

railsの独学を初めて3か月が経ちました。
この3か月間の私の学習経過は下記になります。

**1、progateでhtml,css,ruby,ruby on rails,githubを1周**
**2、ruby on rails チュートリアル2週**
**3、railsでオリジナルのポートフォリオを作成途中**

今日は**3**にて私が作成したポートフォリオの**概要**を説明します。

<h2>ポートフォリオ「KuiShare」の概要</h2>

私は人の**後悔**を聞いたとき似たような**後悔**が自分に起きないように気をつけるよにします。

このことから、みんなとたくさんの**後悔**が共有できればおのずと注意深くなり先々で自分に起きうる**後悔**を減らすことができるのではないかと考えました。

みんなと気軽に後悔を共有することができるのが今回作成した**「KuiShare」**です。

「KuiShare」のURL「https://kuishare.herokuapp.com/」

**「KuiShare」でできること**

・後悔したことを投稿/編集/削除
・後悔を共有したいユーザーをフォローする機能
★人の後悔にコメントをする機能
★人の後悔に『ドンマイ』(instagramでいういいね！)をつける機能
・プロフィールの編集機能

**利用している技術**
・rails
・heroku
・S3(画像置き場)

★印をつけている機能はこれから追加しようとしている機能です。

今回は初投稿でしたのでただ自分の学習経過を記しただけになってしまい申し訳ございません！！
明日からはちゃんとした技術ブログを投稿していきたいと思います！
Nuxt.jsで作っているサイトにKARTEのタグを入れてみるメモ


Nuxt.jsで作っている[Webサイト](https://protoout.studio)に[KARTE](https://karte.io/)を入れてみたときのメモです。 

## NuxtにGoogle アナリティクスを導入する手順とほぼ同じで出来た

公式の[Google アナリティクスを使うには？](https://ja.nuxtjs.org/faq/google-analytics/)が参考になります。

読んでみると 

> **`他のトラッキングサービスでも、同様の方法を使うことができます。`**

って書いてますね。

### 1. plugins/karte.jsを作成

こんな雰囲気で`plugins`の中に`karte.js`を作成します。

> ![スクリーンショット 2019-12-02 22.53.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/21589869-60f9-2bd4-45e7-83fb23f66d9a.png "スクリーンショット 2019-12-02 22.53.40.png")

KARTEの管理画面で計測タグを探してスクリプトタグの内部を見つけましょう。

> <img src="https://i.gyazo.com/cd1b17ad829696714cbcb3a5197a4574.png" width="400px">

```plugins/karte.js

export default ({ app }) => {
    /*
    ** クライアントサイドかつプロダクションモードでのみ実行
    */
    if (process.env.NODE_ENV !== 'production') return
    /*
    ** karteのスクリプトをインクルード
    */
    (function(){var t,e,n,r,a;for(t=function(){var t;return t=[],function(){var e,n,r,a;for(n=["init","start","stop","user","track","action","event","goal","chat","buy","page","view","admin","group","alias","ready","link","form","click","submit","cmd","emit","on","send","css","js","style","option","get","set","collection"],e=function(e){return function(){return t.push([e].concat(Array.prototype.slice.call(arguments,0)))}},r=0,a=[];r<n.length;)t[n[r]]=e(n[r]),a.push(r++);return a}(),t.init=function(e,n){var r,a;return t.api_key=e,t.options=n||{},a=document.createElement("script"),a.type="text/javascript",a.async=!0,a.charset="utf-8",a.src=t.options.tracker_url||"https://static.karte.io/libs/tracker.js",r=document.getElementsByTagName("script")[0],r.parentNode.insertBefore(a,r)},t},r=window.karte_tracker_names||["tracker"],e=0,n=r.length;n>e;e++)a=r[e],window[a]||(window[a]=t());tracker.init("xxxxxxxxxxxxxxxxxxxxxxxxxx")}).call(this);
   /* ↑計測タグの中身をコピペ*/ 
   
}
```

IDっぽいところを`xxxx~~`にしてますが、こんな感じで入れ込みます。

ここのタグは人によって権限っぽい指定の箇所が変わるかもしれないので、この記事からよりは、大元からのコピペが良いと思います。

### 2. nuxt.config.jsの設定

利用するにあたり、`nuxt.config.js`にも以下の記載をします。

```nuxt.config.js
省略

  plugins: [
    { src: '~plugins/karte.js', mode: 'client' }
  ],
  
省略
```

以上！

## 所感

割と簡単に出来ました。

実際に僕の場合は`nuxt generate`で静的サイトにしてホスティングしていますが、静的ホスティングじゃない場合でも同様に動くと思います。(たぶん)
javascript　基本その4 ライブラリ

今日は発展形であるライブラリについて書きます。

# ライブラリ
Rubyにおいてgemにあたります。

汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたもの
他のプログラムに何らかの機能を提供するコードの集合体です。

JavaScriptで開発を行うのを簡単にするツールです。 

# ライブラリの種類
色々種類があるので
それぞれ紹介していきます。

まず大元のjavascriptを例文として紹介します。

```js:javascript
var btn = document.getElementById("title");
btn.addEventListener("click", function() {
  console.log("Hello world");
});
```

# jQuery
DOM操作（DOM要素の取得や追加削除など）をもっと短く簡単に書くことができます。
Webサイト制作などをやりたい場合は、jQueryの知識が必要になります。

```js:jquery
$(function() {
  $("#button").on("click", function() {
    console.log("Hello world");
  });
});
```

# React
Facebookが開発をしたライブラリです。

仮想DOMの概念によって、より早い高速なアプリケーション実装が実現できます。
AndroidやiOSに対してもReact Nativeを使用すればReactを適用でき
柔軟性も高いことから、最近大きく人気が増しています。

書き方は、JavascriptとHTMLを合わせて書きます。

```jsx:React
class Hoge extends React.Component{
    render(){
        return (<div onClick={() => console.log('Hello world') }>
        </div>)
    }
}
```

## 仮想DOM
jQueryの場合、データを更新したらDOMを操作してビューを更新します（クラスの追加や削除など）。

実は、DOMを直接操作するのは思っているよりも処理が遅いです。
そこで、構造化した仮のDOMを作成し、データ更新したら
仮想DOMの差分だけをDOMに反映させるのが基本的な考え方です。

これで処理を速くすることができます。

# Vue.js
Reactと同様に仮想DOMの概念があり
記述を減らして、HTML,CSSを中心にしたWebアプリ開発が可能です。

```js:Vue.js
new  Vue({
  el:  '#button',
  methods: {onClick:  function() {
    console.log('Hello world');
  }}
})
```
Nginx で WEB サーバを構築してみる

# はじめに
Advent Calender の枠が埋まらないから、無理矢理投稿してみます。
初めてやるけど、これって普通毎日枠埋まる（埋める）ものよね...??

[1 日目: [初心者向け]色んなサーバ達の役割を知る](https://qiita.com/ECOHOHOHOO/items/5afee6f8d4827aebb0a4)
さて、そんなことはどうでもよくて、みなさん、1 日目の記事は読みましたか??
(特に最近飲みに行っていない後輩のお前。忘年会しよ。)

ここに出てきた、WEB サーバをサクッと構築してみます。
ただ、個人的に Virtual Box で仮想マシン作って〜、Nginx インストールして〜
ってのはめんどくさいので Docker でやってしまいます。（ごめんね）
Docker も大きな括りで言えば仮想マシンなので気にしないでください。()

#  WEB サーバ
[実行環境] 
OS: macOS Mojave ver.10.14.6

まず、2 つのファイルを用意します。

```dockerfile:Dockerfile
FROM nginx:latest
COPY index.html /usr/share/nginx/html/
```

```html:index.html
<html>
  <head>
    <title> web1 </title>
  </head>
  <body>
    <h1> web1 server </h2>
  </body>
</html>
```
これらを、web1 という名前のディレクトリに突っ込んで、以下のコマンドを実行してください。

```
docker build -t web:01 .
docker run --rm -d -p 8080:80 web:01
```
さて、これで仮想マシンが起動するはずです。
ブラウザから、`http://localhost:8080` にアクセスしてみてください。
おそらく、**web1 server** とでっかく表示されるはずです。
これは、先ほど作った `index.html` が WEB サーバを介して表示されています。

WEB サーバの構築はこれで以上です。
...簡単ですね ??

# リバプロ
これだけでは物足りないので、発展系として "リバプロ" こと リバースプロキシを構築してみます。

### プロキシ
まず、プロキシ(proxy) とは、英語で "代理人" という意味で、クライアントからサーバへのリクエストを
そのクライアントの代わりに行ってくれるサーバのことです。 (**リクエストを"する側"の代理人**)

何がいいかというと、セキュリティの観点から社内の PC の情報を外に出さないようにであったり、
こいつのおかげで業務中に YouTube をこっそり見たりができないよに監視したりできます。

### リバプロ
さて肝心の リバースプロキシ(reverse proxy) は、先ほどとは逆で、リクエストを受ける立場である WEB サーバにアクセスする前にこいつを経由するように置かれます。
(**リクエストを"受ける側"の代理人**)

何がいいかというと、複数台の WEB サーバを運用している時に満遍なくリクエストをバラつかせたり、
様々な役割をもつサーバ軍の拡張がしやすかったりします。

今回は、シンプルにこんな構成を作ります。
proxy の 8081 ポートヘのアクセスを web1 サーバに、
proxy の 8082 ポートヘのアクセスを web2 サーバに流します。
![ELB-ページ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/353538/302b3f40-f825-8f0b-204e-82391abb9d5f.png)

## 構築
```
$ tree
.
├── docker-compose.yml
├── proxy
│   ├── Dockerfile
│   └── default.conf
├── web1
│   ├── Dockerfile
│   └── index.html
└── web2
    ├── Dockerfile
    └── index.html
```
新しく用意するのは、`docker-compose.yml` と `dafault.conf` です。
docker-compose は、複数の仮想マシンを一括で管理できてしまう便利なやつです。

```dockerfile:docker-compose.yml
version: '3'
services:
  proxy:
    build: ./proxy
    ports:
      - 8081:8081
      - 8082:8082

  web1:
    build: ./web1

  web2:
    build: ./web2
```

```conf:default.conf
server {
    listen 8081;
    server_name localhost;

    location / {
        proxy_pass http://web1;
    }
}

server {
    listen 8082;
    server_name localhost;

    location / {
        proxy_pass http://web2;
    }
}
```
web2/index.html は、わかりやすいように、`web2 server` とか表示されるようにしてください。
準備ができたら、以下のコマンドを実行します。

```
docker-compose up -d
```
ブラウザから、http://localhost:8081 、 http://localhost:8082 にアクセスしてください。
この場合、アクセス自体は、proxy に対して行っていますがコンテンツを返すのはそれぞれの WEB サーバです。

Docker に慣れてしまったら、Virtual Box には戻れないね

# おわり
明日は誰か(先輩)、頼んだで

以上
【Docker】crond専用のコンテナからHTTPリクエストを送ったり他コンテナのコマンドを実行してみたりする【cron】

こんにちは！
鍋が美味しくてごきげんな季節になってまいりました。おさむです。

Dockerコンテナでcronによる定期処理を実行したいなあと思いたち、
いろいろ試してみた結果をまとめてみます。

# この記事のゴール
粛々と時を刻み続けるDockerコンテナを手に入れる

# 前提
- Dockerがインストールされており、hello-worldが動作する状態になっていること

# 試したこと

## ①あるURLに対して定期的にリクエストを送ってみる
AlpineLinuxはapkというパッケージマネージャにより、コマンドを追加することが出来ます。
この項ではcurlコマンドを追加でインストールし、
それを用いてGoogleのトップページにリクエストを送ってみます。

```dockerfile:Dockerfile
# 公式版でもたぶんOK
FROM gliderlabs/alpine:latest

# 必要パッケージの取得とタイムゾーンの変更処理（Asia/Tokyo）
RUN \
  apk add --no-cache curl tzdata && \
  cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
  apk del tzdata

# あらかじめ用意しておいたcrontabs用ファイルをコンテナへコピーする
RUN mkdir -p /var/spool/cron/crontabs
COPY ./resource/cron/crontabs/root /var/spool/cron/crontabs/root

CMD busybox crond -l 2 -L /dev/stderr -f
```

```crontab:root
# GoogleへGETリクエストを送信し、帰ってきたレスポンスのヘッダをひたすら追記していく
* * * * * curl https://www.google.co.jp/ -I >> /root/header.txt

# POSTも出来る。JSONを特定のAPIに流し込んだり。
# * * * * * curl -X POST -H "Content-Type: application/json" -d '{"id":"114514", "num":"810"}' localhost:8080/api
```

## ②定期的に別コンテナのコマンドを実行してみる

コンテナの中にdockerのバイナリを配置し、ホストマシンにある/var/run/docker.sockをマウントすると、
Dockerコンテナの中からでも別コンテナの操作が可能になります。
これを利用して他のコンテナのコマンドを実行してみました。

ただし、ちょっとトリッキーな方法であるため、[こちら](https://teratail.com/questions/186433)で言及されている通りWebAPI化し、
①の方法でリクエストを発行したほうが良いかもしれません。お好みで。

今度は複数のコンテナで連携するため、docker-composeも使用していきます。

```yaml:docker-compose.yml
version: '2'
services:
  app:
    build: ./app
  cron:
    build: ./cron
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
volumes:
  db-data:
```

```dockerfile:Dockerfile
# 公式版でもたぶんOK
FROM gliderlabs/alpine:latest

# 必要パッケージの取得とタイムゾーンの変更処理（Asia/Tokyo）
RUN \
  apk add --no-cache tzdata && \
  cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
  apk del tzdata

# dockerのバイナリを取得し、クライアントのみを/usr/local/binへコピー
RUN apk add --no-cache ssl_client && \
  mkdir -p /usr/local/bin && \
  wget https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz -O - | tar -xzC /usr/local/bin --strip=1 docker/docker

# あらかじめ用意しておいたcrontabs用ファイルをコンテナへコピーする
RUN mkdir -p /var/spool/cron/crontabs
COPY ./resource/cron/crontabs/root /var/spool/cron/crontabs/root

CMD busybox crond -l 2 -L /dev/stderr -f
```

```crontab:root
# appコンテナにあるコマンドを実行する
* * * * * docker exec example_app_1 /root/example.sh

# ちなみに、Laravelのスケジュール実行も同じ要領で起動できる
# * * * * * docker exec example_app_1 php artisan schedule:run
```

# 余談
なんでこんな事してるかと言うと、↑の「Laravelのスケジュール実行」を実現したかったから。
php-fpmをFROMに書いたDockerfileの中で無理やりbusyboxを起動するというのもアリなんですが、
それをするとphp-fpmのプロセスが上がってこないという現象が発生したりで色々と難があったため。

# 参考
[Dockerコンテナ上でCronを動かしたい](https://qiita.com/nanamen/items/5c4ef45e2ee84bafdd1d)
[curlコマンドを実行するだけのDockerfile](https://qiita.com/NaokiIshimura/items/c5f2c6e398ab0105d71e)
[Alpine Linux でタイムゾーンを変更する](https://qiita.com/dtan4/items/8359e389b95cbc60952d)
[Alpine LinuxでDockerコンテナ開発を加速する](https://dev.classmethod.jp/tool/docker/apline-accelerates-docker-dev/)
[Docker コンテナから別のコンテナへコマンドを実行し、返り値を得る](https://teratail.com/questions/186433)
C# - Windows.Data.Jsonの謎 / winmdの中身をILSpyで確認する

[Microsoftのドキュメント](https://docs.microsoft.com/ja-jp/uwp/api/windows.data.json.jsonobject.insert
)に書いてあるJson関連クラスのメンバが、一部そのままの名前だとコンパイルが通らない。
参照設定しているファイルが間違っているのか？


適当にそれっぽい名前に変えてみると動いた。謎・・・

|クラス     |ドキュメント上のメンバ | 実際（？）のメンバ|
|----------|--------------|-------|
|`JsonObject` | `Insert` | `Add` |
|`JsonArray` | `Append` | `Add` |
|`JsonArray` | `Size` | `Count` |
|`JsonValue` | `CreateNullValue` | ない？ |


# 環境

Windows10で下記を`/r:`オプションで指定してコンパイル
※visuals studio等でwindows sdk入れてないとwindows.winmdファイルがなくてコンパイルできないっぽい。

```

csc /r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\system.runtime.windowsruntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll ^
"/r:C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd" %*
```

# ILSpyで確認する方法

C:\Windows\System32\WinMetadata に下記のようにメタデータ(winmdファイル)が居る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/e631ee5a-660f-e7a5-8498-5bf6b46f8156.png)

上記の特定のファイル1個をILSpyにDrag&Dropすると見れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/a76d1a4c-daee-455b-43bd-58196c05cbe8.png)

ただ、`JsonValue`に`CreateNullValue`がなぜか居る・・。

ちなみに、クラスの直下にメンバーがいなくても、継承元(Base Types)に居たりする場合があるので注意。

# 脱線編 - 気になるWinRTの機能たち

- Windows.Data.winmd をILSpyで見てみると、`Windows.Data.Pdf`なるものが居て、PDFの読み書きに使えそう。→ [試してみた](https://qiita.com/kob58im/items/c50761db0590f3394c8e) →画像としての読み込みにしか使えないっぽい。
- Windows.AI.winmd をILSpyで見てみると、`Windows.AI.MachineLearning`なるものが居る。VisualStudioでnugetしなくても`csc.exe`で機械学習やれちゃう？(Visual Studio自体は入れないとダメかもですが・・)
FileMakerでペルソナ5風デザインを再現してみた：パーソナル情報編

# はじめに
## 対象読者
* FileMaker Pro / ProAdvanced ( 以下 FMPA と略す ) ユーザー
* ペルソナ 5 好きな人
* 一発ネタ記事が嫌いじゃ無い人

## 要旨
ペルソナ 5 ザ・ロイヤルも発売されたことですし、記念に FMPA のレイアウトでステータス画面を再現してみよう、という一発ネタです。

以下の情報を持ったパーソナルデータを表示するためのレイアウトを用意しました。

* 氏名
* メールアドレス
* 電話番号
* 郵便番号
* 住所

FMPA というのはデータベースソフトウェアなのですが、こんなことまでやろうと思えばできちゃうんだぜ、ということが分かります。



# 本題
## キャプチャ画像
さて、さっさとキャプチャ画像を見ていただくのが良いですね。三人分用意しました。

* 一人目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/fc889ee2-866b-2365-53a5-1ee09c876ba6.png)

* 二人目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/a2a88e6d-96f7-584f-2c98-1f9d6bf04282.png)

* 三人目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/2fd4f1fc-e826-2352-8c2a-5ecf419b6857.png)


## 補足説明
ほぼ不要と思いますが……

レイアウトの背景色を黒にして、四角形オブジェクトと線オブジェクトを変形／重ね合わせて表現している、というのが基本です。

フォントは Arial にしています。もっと凝ったフォントを選べば、もう少し雰囲気が近くなるはず。

背景の赤い部分、オブジェクトフィールドになっていて、写真の挿入ができるようにもしてあります。

「前へ」「次へ」 ボタンの表示／非表示切り替えは、レイアウトのオブジェクトを隠す条件で処理しています。以下の条件が満たされる場合、非表示となります。

```
/* 前へ */
Exact ( Get ( レコード番号 ) ; 1 )
```

```
/* 次へ */
Exact ( Get ( レコード番号 ) ; Get ( 対象レコード数 ) )
```

開発環境は以下の通りです。

* Windows 10 Pro
* FileMaker Pro Advanced 18.0.1.122

二時間くらいかかったかな……アホですね。


## 疑念を晴らす
「本当に FMPA で作ったんですか……？」
「画像がないと印象がイマイチ……」

本当ですよ！　証拠の代わりにレイアウトモードのキャプチャ画像、それからオマケでオブジェクトフィールドに画像を入れたものも貼っておきます。

* レイアウトモード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/b488257b-b4c6-6c47-d8a8-e9c554edaf7e.png)

* オブジェクトフィールドに画像はめこみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/30aad450-435d-66dc-c3de-f81680242688.png)

信じていただけましたでしょうか。


# おわりに
淡々としたありきたりなレイアウトデザインで名簿つくっても、面白くも何ともないけれど、こうした工夫次第で業務が楽しくなったりするかもしれません？

今回の記事タイトルで「パーソナル情報編」と銘打ってはいますが、続編があるわけではありません。むしろ誰か他の人にやっていただきたい所存。その際は以下の Appendix をご参照ください。


# Appendix
FMPA をお持ちの方へ。
fmp12 ファイル本体を GitHub へあげておきますので、よろしければどうぞ開いて見てやってください。
Mac だと崩れるかもしれません。未確認です。

https://github.com/hi-noguchi/like_persona5_layout_fmp

なお、テーマは申し訳ない程度に別名保存していますが、設置されているオブジェクト一つ一つをテーマに反映させていたりはしませんので（そこまでの気力が無かった……）悪しからず。
もしそのあたりやってくださって改善版を仕上げられたら、プルリクください……！
開発時やデバッグの時だけログを出力するさえないやり方

## はじめに

これは [Delphi Advent Calendar 2019](https://qiita.com/advent-calendar/2019/delphi) の 17 日目の記事です。

## 2019/12/17訂正

コメントで指摘されているとおり、インライン関数として定義することで、デバッグビルドのときだけログ出力が実現できるとのことです。

現存するオンラインドキュメントを眺めたところ、少なくともDelphi 2010以降は、確実にサポートしている模様です([see: プロシージャと関数の呼び出し](http://docwiki.embarcadero.com/RADStudio/2010/ja/%E3%83%97%E3%83%AD%E3%82%B7%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%A8%E9%96%A2%E6%95%B0%E3%81%AE%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97))

残念ですがDelphi7はインライン関数をサポートしていないので、それ以前のバージョンで頑張っている方は諦めましょう。

## ほんへ

デバッグ時だけにログ出力して、リリースでは出したくない場合、たいていは

```delphi
{$IFDEF DEBUG}
OutputDebugString('Hoge');
{$ENDIF}
```

な事をすると思う。

けど*IFDEF*や*ENDIF*が仰々しくてなんか嫌。

なら、「関数化すればいいじゃない」ということで、コードとしてはこんな感じか。

```delphi
procedure OutputDebugOnlyString(M: string);
begin
{$IFDEF DEBUG}
OutputDebugString('Hoge');
{$ENDIF}
end;

// .....

begin
  OutputDebugOnlyString('Uge');
end;

```

けどこの関数、ログ出力の有無にかかわらず、引数は評価されて渡されてしまう。
引数に渡す関数の実行が重い場合、リリース版なのに無駄に処理を食うのなんか嫌（2回目）

そんなわけで、いい方法はないかなと思案した結果がこちら

```delphi
program DevTimeOnlyLog;

{$APPTYPE CONSOLE}

{$R *.res}

{$IFDEF DEBUG}
  {$C+}
{$ELSE}
  {$C-}
{$ENDIF}

uses
  System.SysUtils,
  Windows;

function TryOutputDebugString(Msg: string): boolean;
begin
  OutputDebugString(PWideChar(Msg));

  Exit(true);
end;

function HeavyFunc(M: string): string;
begin
  OutputDebugString('Begin sleep 2000 ms');

  Sleep(2000);

  OutputDebugString('Complete sleep 2000 ms');

  Result := M;
end;

begin
  try
    Assert(TryOutputDebugString(HeavyFunc('Some Message')));

    Writeln('Press ANY Key');
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
```

ポイントは、ログ出力を**Assert**手続きでくくり、コンパイラ指令(*$C*)でログ出力の有無を切り替えるという残念な方法。
ここでは、説明のためコードで直接コンパイラ指令を指定してますが、通常はプロジェクトオプションで。

リリース版では、ログ出力のコードすら生成されなくなって心の平穏を取り戻しましたとさ。ちゃんちゃん。

## おまけ

実装・動作確認、**Delphi XE5**にて行ったのですが、なーぜーかリリースビルドであるにもかかわらず、Assertの生成がONになってた。
リリースビルドではAssertのコードを生成しないのが一般的だと思ってたので、ちょっと驚いた。

まぁ古いバージョンだし、今は昔で変わってるのかな？
RustでHashMapの中身のVecを変更する

# TL;DR
Rustで`HashMap`の中身の`Vec`を変更するには`get_mut()`を使う．

# 本題
例えば，以下のような`HashMap`を作成したとする．

```rust:HashMapの作成
use std::collections::HashMap;

fn main(){
  let mut map: HashMap<char, Vec<usize>> = HashMap::new();
  map.insert('a', vec![1,2,3]);
  map.insert('b', vec![4,5,6]);
}
```

つまり，`map = {'a': [1,2,3], 'b': [4,5,6]}`のように`HashMap`の中身が`Vec`のものだ．
本稿では，中身の`Vec`の任意の要素を削除する方法を解説する．

## インデックスを求める

`map['a']`の要素`1`を消したいとき，まず`1`が`map['a']`の何番目にあるか求める必要がある．
ここで，`map['a']`に`1`が含まれることが既知であるとする．

```rust:Indexを求める
  // まずはIndexを取得する
  let index = map[&'a'].iter().position(|x| *x == 1).unwrap();
```

試しに以下のコードをコンパイルして実行してみる．

```rust:テストコード
use std::collections::HashMap;

fn main(){
  let mut map: HashMap<char, Vec<usize>> = HashMap::new();
  map.insert('a', vec![1,2,3]);
  map.insert('b', vec![4,5,6]);
  println!("{:?}", map);

  // まずはIndexを取得する
  let index = map[&'a'].iter().position(|x| *x == 1).unwrap();
  println!("{}", index);
}
```

```sh:実行結果
{'a': [1, 2, 3], 'b': [4, 5, 6]}
0
```

## 直感的な実装

`Vec`からインデックスを指定して要素を削除するメソッドとして，本稿では`remove()`を使用する．

このとき，筆者のような初学者であれば，以下のようなコードを書くと思う．

```rust
  // Indexを指定して要素を削除
  map[&'a'].remove(index);
```

これはコンパイラに叱られる．

```sh
error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/main.rs:13:3
   |
13 |   map[&'a'].remove(index);
   |   ^^^^^^^^^ cannot borrow as mutable
   |
   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<char, std::vec::Vec<usize>>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0596`.
```

メッセージを読むと，`HashMap`には`Vec`のように`IndexMut`が実装されていないことがわかる[^1]．

[^1]: もともとは実装されていたが削除されたらしい [参考1](https://stackoverflow.com/questions/30414424/how-can-i-update-a-value-in-a-mutable-hashmap) [参考2](https://github.com/rust-lang/rust/pull/23559)

## 実際に動く方法
TL;DRで記したとおり，`get_mut()`を使う．

```rust
  // Indexを指定して要素を削除
  map.get_mut(&'a').unwrap().remove(index);
```

実行してみる．

```rust:テストコード
use std::collections::HashMap;

fn main(){
  let mut map: HashMap<char, Vec<usize>> = HashMap::new();
  map.insert('a', vec![1,2,3]);
  map.insert('b', vec![4,5,6]);
  println!("{:?}", map);

  // まずはIndexを取得する
  let index = map[&'a'].iter().position(|x| *x == 1).unwrap();
  println!("{}", index);

  // Indexを指定して削除
  map.get_mut(&'a').unwrap().remove(index);
  println!("{:?}", map);
}
```

```sh:実行結果
{'a': [1, 2, 3], 'b': [4, 5, 6]}
0
{'a': [2, 3], 'b': [4, 5, 6]}
```
IoTデバイスへの定期的なイベント通知にはCloud Schedulerが捗るぞ

## とある開発にて

MQTTで接続している特定のIoTデバイスに、定期的にイベントを通知したいという要件がありました。

イベントの内容は、システム制御的なコマンドなので静的なものになります。

シンプルな要件です。

## 方針決定

今回の例で言うと、IoTデバイスがラズパイなので、当初はcron仕込んで定期実行させようかと思いました。

ただ、それだとスケジューリングを変更したい時にsshする必要があります。接続する必要がなければsshは極力したくありません。

また、IoTデバイスにcronが動くデバイスしか使えなくなります。

他にも、定期実行の責務をデバイスからはがせるのであればそれに越したことはありません。

ということで、クラウドベンダーにGCPを使っている理由もあって、Cloud Schedulerで実装することにしました。

## 実装

デバイスは、Cloud IoTにデバイス登録されており、MQTTで接続しています。そして、各デバイスへの通信は前段にAPI(GAE)が用意してあるので、Cloud Scheduler経由でAPI(GAE)を直接叩くだけで、既存の資産を活かしつつ最小限で実装できそうです。

なので、当初想定していた構成はこんなかんじでした。

<img width="482" alt="スクリーンショット 2019-12-02 21.08.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18114/6456f59b-2c2b-47dc-8213-8f67eaa1f977.png">

Cloud Scheduler の設定はUnix Cron形式をサポートしているので、そんなに迷うことなく設定が完了。

テスト実行させみました。


あれ？うまく動かない...


デバッグしたところ、Cloud Schdulerから送信したリクエストボディ(JSON payload)がAPI側でうまくハンドルできてないようでした。

いろいろと調べていった所、APIに使っていた`restify`のbodyParserがリクエストのContent-Typeをチェックしており、その分岐においてbodyParserが設定されないことが原因でした。

https://github.com/restify/node-restify/blob/master/lib/plugins/bodyParser.js#L166

ちなみに、Cloud Scheduler がGAEを呼び出したときのContent-Typeは`application/octet-stream`でした。

Cloud Schedulerにリクエストヘッダーを設定する方法をいろいろ探したのですが、時間がなく探すことを諦め、作戦を変更することにしました。

## ピボット
次の作戦は、Cloud SchedulerのターゲットにPub/Subを指定し、Functions経由でIoTデバイスにイベントを通知することです。

構成はこんなかんじ。

<img width="608" alt="スクリーンショット 2019-12-02 21.57.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18114/9a2b2451-b235-c279-dd53-f9293d55be69.png">

幸い、GAE側の実装が簡単に移行できるようにしてあった為、作戦を切り替えて10分もかからずに先程の問題を解決することができました。

## まとめ

Cloud Schedulerのいいところは、スケジュール対象を切り替えるのが簡単なところと、スケジューラー自体をデバイスに依存させない疎結合さだと思います。

再試行やロギングなども全部クラウド側で面倒みてくれるので、定期実行させるようなものは外から叩けるようにしてCloud Schedulerを使うのがオススメです。

ただ、Cloud Schedulerでヘッダーを自由に設定することができないのは解決していないので、だれか解決方法を知ってたら教えて下さい。