OmniAICreator/Qiita-1.07M huggingface dataset:
会社のインフラ環境をAWS構成図に落とし込んだら、めちゃくちゃ勉強になった件

### インフラ初心者は、現場で使っているクラウドサービスの構成図を書くのがおすすめ
- よくハンズオンなどで、作りながらインフラを学ぶパターンが多いと思う
- 一方で、すでにできているものをインフラ構成図に落とし込む、ということをやると、いろんな学びが得られる
- ドキュメント整備のきっかけにもなるし、一石二鳥だ！

### インフラ環境を構成図に落とし込むのが、なぜ勉強になるのか？
* 既存環境を図に落とし込む作業は、現状の構成を把握し理解する能力が求められる。ハンズオンで覚えた知識の復習にもなる。
    * 例えば、図を書いているうちに「ロードバランサーってなんだっけ？」「サブネットグループがprivateかpublicかどうかを決めるのってどんな設定だったっけ？」と、基礎知識を振り返るきっかけが生まれる
    * 普段、AWSのコンソール画面から操作していると、決まった流れの中で操作をしているため、あまり深く考えずに「そういうものだから」と浅い理解で進めてしまう。でも構成図に書き起こしていくと、「あれ、これってなんでこんな構成になってるんだ？」と考えるきっかけになる。
* インフラ構成図をたくさん書くことが、今後0からサービスを作るときの予行練習になる
    * サービスを最初から構築する場合、見切り発車で進めるよりも、落ち着いてこういったインフラ構成図をまず手書きしてみることが大事
    * 特にECSでコンテナサービスを構築するときとか……。あれは頭の中でぼんやり考えていてもなかなか実現できない……

### 他にはどんなメリットが？
* 新規参画者やPdMが喜ぶ
    * 作った図を取っておけば、他の人にとって役立つドキュメントになりうる
* インフラにおける問題点がわかる
    * サービスの可用性やセキュリティにおける課題を一目で見つけることができる
        * 「あれ、このサブネットグループ、publicになっているけどこれでいいのか……？」
    * インフラはサービス開発を進めていくうちに、自分たちでもわからないような形に変貌を遂げていることがよくあるので、それを見直す良い機会になる

### 作る上でのポイント
* できる限り簡略化しない。とくにサブネットグループの境界はきっちりと区別する。ネットワークの勉強にもなるし、セキュリティ的にも大事な要素だ。
* 図としてのキレイさよりも、「必要な情報がきちんと入っているかどうか？」を重視する
    * EC2インスタンスの数やそれぞれの役割、DBとの関連など。マイクロサービスであれば、各サービスとDBは1:1で紐付いているはずだが、果たして……
    * 社内用ドキュメントであれば、各リソースのNameを図の中に記載しておくと、それを読んだチームメンバーがコンソール画面上から簡単に見つけ出すことができるのでおすすめ
* draw.ioで作るのがおすすめ
    * テンプレが豊富にあるので、作図の手間を減らすことができる
* 作ったらドヤ顔でチーム内に共有しよう。

### まとめ

* みんな、クラウドサービスの構成図書こうぜ！ 勉強になるよ！ いつか絶対役に立つよ！
* チームの人も喜ぶよ！
【Windows：ファイル削除】俺を削除してみろよ (´ﾟдﾟ｀)？

# ファイルが削除できない！！
調子に乗っているやつがいたので、削除することにしました...。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/8b6e9f89-6e08-4e4a-b813-0886a536b430.png)
「右クリック」して「削除」をぽちっと・・・。
は…？ 削除ができないだとおおお！！？

<font color="Red">**※ 何かのプロセスがファイルやフォルダを使用している為、削除ができない状況です。**</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/a8b2103a-400a-aa3f-d711-601d6d1c198a.png)

# 使用しているプロセスを捜索してみるか・・・。
どこぞのだれだ？ こいつらの削除を邪魔している仲間（[プロセス](https://wa3.i-3-i.info/word11032.html)）は！？
そうだ！ こういう時は、この辺を取り締まっている「[リソースモニター」](https://ssaits.jp/promapedia/technology/resource-monitor.html)さんの出番だ！

:::note 
**【リソースモニターの起動方法】**

１. デスクトップ画面で、「Windowsキー」+「R」を押す。
２.「ファイル名を指定して実行」のダイアログボックスが開く。
３.「perfmon.exe /res」または「resmon.exe」または「resmon」を入力。
４.「OK」を押すと起動。
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/5b99439d-a39e-82c1-7e31-b3ac37f8837b.png">
:::

リソースモニターさん！削除を邪魔している仲間（プロセス）を教えて頂けないでしょうか？

<font color="Blue">**● 削除できない対象を検索欄に入力して、使用しているプロセスを検索します。**</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/0e4617e4-98a1-7b87-8fe5-3dd190941af9.png)
調べたんやけど、どうやら犯人はこいつらやで。（リソースモニターさん）
犯人は、お前らかあああ！！！ まずお前らの人生を終わりにしてやるわああ！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/224eb867-b539-2a85-b9ee-be43e8a14561.png)
<font color="Red">**※ 停止する前に、本当に停止してもよいプロセスなのか確認することをお勧めします。
　 停止すべきでないプロセスを停止してしまうと、プロセスの処理が中途半端に終了します。**</font>

<font color="Blue">**● 対象を選択して、右クリックで「プロセスを終了」させることができます。**</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/de781608-f123-2dec-bf38-c7326fc11b3a.png)
<font color="Blue">**● 終了できない場合は、コマンドプロントから強制終了させましょう。
　 青枠に囲まれている「PID」を指定して終了させます。**</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/fc385044-088f-b263-908f-58404b8786fa.png)
どやあああああああああ！！！（仲間の人生終了・・・。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/25c1e3c4-dad4-82bb-3f18-33aae6ded00f.png)
次はお前らの番やあああああ！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/6e262fb6-0cd9-e0ba-30e0-7338d4f39d99.png)
ざまーみろおおお！！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727351/615506f4-4b3c-c94d-0988-269bc3bbd1bb.png)
# とな感じで・・・。
削除したいファイルやフォルダが削除できなかった場合は、この方法を試すのもありです。
お付き合い、ありがとうございました。
XcodeのリリースビルドでError (Xcode): "Runner" requires a provisioning profile. 

XcodeのSigning & Capabilitiesにてただしく、
Apple DistributionのProvisioning Profileを設定しているのに、見つからないとのエラーがリリースビルドのたびに発生しました。

# 結論
「Build & Setting」
に行き、
・「Code Signing Identity」の「Release」が「iOS Distribution」になっているかどうか

・「Provisioning Profile」の「Release」に、manual設定で作成したprovisioning Profileが設定されているかどうか

この二点を確認し、改善したらうまくいきました。
エンジニア5年目ですが技術ブログはじめます

## ご挨拶

はじめまして、Rinaと申します。
これから記事をがんばって、がんばって、更新しようと思っています。
今年の目標の1つです。

記事を書く前に自己紹介をしようと思い立って書いています。
興味ない方が1億パーだと思いますが、
僕らの名前だけでも覚えて帰ってください〜🎙

# キャリア履歴

### 1社目(2015年〜2017年くらい)
儲かるならなんでもする事業内容ブラックベンチャー
事務員という名の雑用係ポジションでした。
事務以外もやっていましたがここには書けないのでもし会えたら聞いて下さい。


### 2社目(2018年くらい〜現在)
一応コンサルティング会社だと思います。多分。知らんけど。
DODAで転職しました。
希望は専門職とだけエージェントのお姉さんに伝えていました。
手に職ってやつです。
前の会社の失敗もあってキャリアを積まなきゃと考えていました。

ただ具体的な職種の希望もなかったので、何も勉強もしておらず・・・
当時２５歳だったので本当に若さとやる気だけで採用してもらいました。
HTMLナニソレ？のレベルでしたもん。
こんな感じでプログラマーにぬるっと転職しました。

未経験からプログラマー転職した記事とか書ければよかったんですけど
今と状況がかなり違うもので・・・
入ってからどうだったかとかはまた別の記事で書ければと思います。


## 今、技術ブログをはじめる理由

端的に言うと上司に言われたからです。
今「言われたことしかできない受け身サラリーマン」と
1ミリでも思った人は左の頬を出しなさい。

話を戻すと、
* 人事評価でちょびっとだけ評価上がる。かも。
* 自分の成長とかキャリアのためにもなるし。
* あとエンジニア仲間ほしい。

てな感じです。（ザコモチベ）
行動するのが大事ってどこかの啓発本にもあるから大丈夫、なはず！

## 投稿する予定の記事

予定は未定。
ネタ帳みたいなもんだと思って下さい。

#### 資格試験
* 基本情報技術者試験に落ちてみた
* 基本情報技術者試験の勉強方法（貧乏社員編）


#### ポエム系
* 普通の事務員からプログラマーに転職してわかったこと
* コミュニケーション能力ってなに？


#### 技術系
* ノンデザイナーが独学でデザインを学ぶ
* Windowsアプリ開発のあれこれ（VB.NET,C#）
* クラシックASPでのWeb開発のあれこれ
* JavaScript, Vue.jsでのWeb開発のあれこれ
* 製造業におけるDB設計のあれこれ


## 最後に

投稿主はミーハーなオタクです。
最近はスラムダンクの映画を見て感動し完全版全巻がほしくてたまりません。
井上先生の映画製作秘話が載っている本を読んで感動しました。
同人誌欲しい。ていうか描きたい。

あとぼっちざろっくを観てドラムを始めようと考えています。
まだスティックさえ握ったことはないのですが・・・
バンドやろうぜ！

あとこれ大事です。猫飼いです。
猫のために働いています。
保護猫ボランティアもやっています。

猫のために投稿がんばりますので、どうか今後も
なにとぞ、なにとぞよろしくお願い致します。
Preattentive Attributesの外観を知る

ビジュアルを使用した分析を行うに際して，　Preattentive Attributesは大切な概念の一つです．
ビジュアルでの分析はデータを探索し理解するための手段であり、分析のプロセスそのものを支援し加速すると，TableauのHPでも述べています(後述のHelpページ)．

まず， Preattentive Attributesとはなにかについて理解しましょう.
Preattentive Attributesと海外サイトも含めて検索すると，トップページには以下のサイトと説明が表示されます．

>What are Pre-attentive Attributes?
Pre-attentive attributes are attributes that our brain, or more exactly our Spatial Memory, subconsciously processes when looking at a visual. It is the very first thing that you pay attention to. The process is done in milliseconds, before you are even aware of it.
>訳：前注意の属性とは？
前注意の属性とは、私たちの脳、より正確には空間記憶が、ビジュアルを見るときに無意識に処理する属性のことです。これは、あなたが最初に注目することです。この処理は、あなたが意識する前に、数ミリ秒のうちに行われます。
>https://elias-nordlinder.medium.com/designing-with-your-brain-in-mind-using-pre-attentive-attributes-977a7af54b58#:~:text=What%20are%20Pre%2Dattentive%20Attributes,are%20even%20aware%20of%20it.

Preattentive Attributesとは私たちの脳、より正確には空間記憶が、ビジュアルを見るときに無意識に処理する属性のことです．

過去にあったTableauのユーザー会「【DXを目指す企業様限定】第3回Salesユーザー会～営業部門のためのデータリテラシー講座～」では，Preattentive Attributesの外観について以下のように説明しています．

>■人間の知覚と認識
>
>・Preattentive Attributes
>Form：向き・幅・長さ・囲い・サイズ・形状
>Color：色（色相）・色（彩度）
>Position：空間グループ・位置
>
>・棒グラフではなく、長さと位置
>・線グラフではなく、位置、向き、長さ
>
>と認識する
>https://community.tableau.com/s/feed/0D54T00000C5LRMSA3?_ga=2.98029340.2086060384.1674295741-740354915.1668271568&_gac=1.124811768.1674295743.Cj0KCQiAt66eBhCnARIsAKf3ZNEM8b9h8W6oBfrUCJeJalJ2T5TWQmh2IXp8_cozGV9hKKqDDvQL6NIaAvNuEALw_wcB

また，Tableau Helpで検索をかけると以下の記事がヒットしました．

>もともと認識しやすい属性
>
>ビジュアル分析はもともと認識しやすい属性を活用して、人を最も効果的な方向へと導きます。もともと認識しやすい属性とは、注意処理を行う脳の器官に情報が送られる前に、ほぼ即座に視覚的に処理できる情報です。以下のものがもともと認識しやすい属性です。
>![bp_why_visual_analytics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394349/24742d33-3aef-7c49-a8fc-a373eea0df03.png)
>https://help.tableau.com/current/blueprint/ja-jp/bp_why_visual_analytics.htm

Preattentive Attributesには種類があり，データ視覚化を考える時に必ず抑えておきたいPreattentive attributeは以下４つの要素だといわれています。

・位置(Position)
・色(Color Hue)
・サイズ(Size)
・形状(Shape)

これまでが，Preattentive Attributesの外観です．
次回の記事にてこれらの要素を実際に使用した例を用いて，効果をご説明します．
【Smarty】JavaScritpを別ファイルに書くときの読み込みパス

# Smarty使用時にJavaScritpを別ファイルに書くときの読み込みパス

## 発端
* javascriptをjs専用のフィアルに書いてそれをSmartyで読み込みたかったがうまく読み込めずハマったので備忘録。

## 原因
* Smartyからのパスを書いていた。

## 解決方法
* そのテンプレートファイルを呼び出しているPHPからのパスを書く。

## 詳細
* ディレクトリ構造
```
test--
    |-layout
    |   |_resource
    |   |    |_javascript.js
    |   |_layout.tpl
    |
    |-module
    |   |_module.php
    |
    |-template_c
```
* module.phpでlayout.tplを読んで画面に表示させているとき、layoutに記述したinputタグの内容についてjavascriptで処理をしたいとする。

```html:layout.tpl
<body>
    <input id="input" type="text">
    <p id ="text">HELLO WORLD</p>

<!--ここにファイルパスを書いて読み込み-->
<script src="../layout/resource/javascript.js"></script>

</body>
</html>
```
:::note info
* module.phpから見ると一階層上のlayoutの中のresourceの中のjavascript.jsとなる。
:::

* jQueryを使用する場合はheadタグ内にCDNを記載しておけば同じ処理で使用可能
Android 非公開APIの見分け方

# 非公開APIとは
AndroidにはAPIの種類があります。
殆どの方が使用するのは、publicAPI(AndroidStudioで開発する際誰もが使用できるAPI)だと思います。
[Android Code Serarch UserHandle#myUserId()](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/UserHandle.java;l=551?q=UserHandle.java)を見てみるとMethodの上に@SystemApiや@hideやらついています。

これらのAPIは普段3rdParty(GooglePlayからインストールするようなApp)では使用できないAPIになります。
じゃなぜこれの説明をするのって？？
日々の業務の中でPre-inAppを作成しており、そのAppを配信化する事になりました。

しかし！！先ほど説明した非公開API(@SysteApiや@hideがついているMethod)は使用しない方針で進める事になりました。
現状各Pre-inAppには大量の使っており、置き換えもしくは設計の見直しが必要になりました。

ということでまず非公開APIにも見分け方があるという事で今回はそちらを記載します。

# なぜ見分け方を知る必要があるか？？
Googleは非公開APIを見分けるToolを用意してくれています。[veridex](https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces?hl=ja#veridex-windows)
しかし、なぜか出力されないAPIもあるという事に気が付き、自身でも見分け方を知っておく必要がありました。



## 見分け方1-APIのみに@SystemApi or @hideが付与
例：[Android Code Serarch UserHandle#myUserId()](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/UserHandle.java;l=551?q=UserHandle.java)

こちらは簡単です。APIの直下に付与されている場合、そのアノテーションが有効化されます。
SystemApiの場合は、@hideと@SystemApiの2つが付与されSystemApiに識別されます。

hideApiは@hideのみが付与されhideApiに識別されます。

## 見分け方2-Classに@SystemApi or @hideが付与
例：[VolumeInfo.java](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/media/java/android/media/VolumeInfo.java;l=45?q=VolumeInfo&sq=)
Class自体にアノテーションが付与されている場合はClass全体が非公開APIと識別されます。
こちらは普段使用する方は殆どいないと思います。
もちろんAndroidStudio等で入力しても自動変換されず、buildすらできない状態になります。

## 見分け方3-Classに@SystemApi、APIに@hideが付与
Class全体はSystemApiですが、APIの上に@hideが付与されている場合はそちらが優先されます。

### 補足
他にも種類はありますが、殆どの非公開APIはこれでも網羅できます。
またSystemApiとhideの違いについてはAppをインストールする場所によって、利用可能か変わってきます。
Appをインストールするパーテーションという仕切りによって権限が変わり
system配下の場合hideApi, SystemApiも利用可能。product配下の場合SystemApiが利用可能になります。


# 最後に
もしこれからAppを作られる方は特別な理由がない限りはApp層のAppには非公開APIを使用しない事をお勧めします。
基本的にGoogle自体もhideApi, SystemApiの利用はお勧めしてません。
git pushで"non-fast-forward" エラー

git pushするときによく"non-fast-forward" エラーが出ます。
これはリモートリポジトリに既に新しいコミットがプッシュされている場合に発生します。
それに対して、ローカルのリポジトリには古いコミットが残っているため、
Git はそれらをマージすることができないためにプッシュを拒否します。
これは、他の人が同じブランチにすでに変更を加えている場合に発生します。

この問題を解決するためには、リモートリポジトリから最新の変更を取得し、それらとローカルの変更をマージする必要があります。
そのためには、以下のコマンドを使用することができます:

- git fetch origin # リモートリポジトリから更新を取得します
- git merge origin YOUR_BRANCH_NAME # リモートリポジトリの更新をローカルの変更とマージします

また、上記の 2 つのコマンドを 1 つにまとめることもできます:

- git pull origin YOUR_BRANCH_NAME # リモートリポジトリから更新を取得し、それらをローカルの変更とマージします


おそらく最初はこのエラー出くわすこと多いと思います。
WORDで差込印刷を相対パスのファイルに対して行う

# はじめに
ＷＯＲＤの差込印刷機能では、どうも外部のデータファイルは絶対パスでしか指定出来ないようなので、ファイルをOnedriveなどで他人と共有したらリンク切れが起きてしまいます。
どうしても相対パスでは指定できないようです。
それで、データファイルのフォルダ名が変わっても問題なく差込印刷が可能な方法を考えました。


# 差込印刷のデータファイルをテキストで作成
##### 差込みファイル
```:差込ファイル.txt
番号	氏名
1	鈴木一郎
2	田中花子
3	山田太郎
```
・フィールド区切りはtab(カンマでも可)
・１行目はタイトルとする


##### WORDファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/2944a1b0-5dfe-d12e-090a-51656c58d6e1.png)

##### 結果のプレビュー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/075a9aad-6174-e198-e1c5-c083a5edaed7.png)


##### 対応マクロ
ThisDocumentのOpenイベントに下記のコードを記載する
ファイルの拡張子をdocmで保存（docxではマクロを保存できないため）
```VB
Private Sub Document_Open()
    Dim strPath As String
    strPath = ThisDocument.Path & "\差込ファイル.txt" '相対パスのファイル名を指定する
    Call ActiveDocument.MailMerge.OpenDataSource(strPath)
    ThisDocument.Saved = True '未編集の時に「保存しますか」の確認を表示させない
End Sub

'以下のマクロを記述するとオープン時にSQLコマンドの確認メッセージが表示されない
Private Sub Document_Close()
    Dim Saved As Boolean
    Saved = ThisDocument.Saved
    Call ActiveDocument.MailMerge.DataSource.Close
    ThisDocument.Saved = Saved
End Sub
```

2023/1/25 追記
差込ファイル.txt をEXCELファイルに変えるとEXCELファイルで差込データを作成することも可能
その場合はOPEN時にシート名を選択する画面が表示されますが適切なシートを選んでOKを押下すればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/0c2ed0b0-512b-ed0a-15f6-629eeb94df88.png)


# やったこと
マクロの記録機能で、差込印刷の「既存のリストを使用」コマンドを実行して記録させて、生成されたコードから関係のなさそうな引数を削除し、外部ファイルのパス部分をThisDocumentのパスになるように変更
NextJSで作成したページを静的ページとしてApache経由で公開する

# 目的
当初目的: ローカルサーバ上でNextJSのHTTP/2カスタムサーバを動作検証予定であった。
以下のサンプルのインストールを行ったがレンダリング時にエラーが発生したため、暫定的にApache経由で公開するテストを行ったので、備忘録とする。
https://github.com/vercel/next.js/tree/canary/examples/with-http2

NodeJSでのHTTP/2カスタムサーバは動作確認はできている。

# 環境
RedHat Enterprise Edition 8.7
Node v19.4.0

# 作業概要
:::note info
ApacheのSSL, HTTP/2, 証明書等の設定は実施済のものとする。
DocumentRootは/www/html/とする。
:::
1\. packege.jsonを修正
```diff_json
- "build": "next build",
+ "build": "next build && next export",
```

2\.  next.config.jsにimagesを追加
```diff_json
const nextConfig = {
  reactStrictMode: true,
+  images: {
+    unoptimized: true
+  }
}
```
:::note info
上記設定で生成されるファイルは、ApacheのDocumentRootに関連するファイルが配置される前提となる。
プロジェクト毎のサブディレクトリにまとめる場合は、next.config.jsに設定を追記する。
```diff_json
const prefixPath = '/sub_dir'
const nextConfig = {
+  assetPrefix: prefixPath,
+  basePath:    prefixPath,
  reactStrictMode: true,
  images: {
    unoptimized: true
  },
}
```
:::

3\. ビルドおよび結果のコピー
```
$ npm run build
$ cp -pr out/* /www/html/
  サブディレクトリを指定する場合
$ cp -pr out /www/html/sub_dir
```

これでApache経由でHTTP/2で参照できる。

# ToDo
動的ページのApache経由での公開方法
NextJSでHTTP/2カスタムサーバの構築
Vercelにdeployしてwith-http2カスタムサーバが動作するか確認する。動作するなら環境の違いの切り分け。

# 参考にしたサイト
https://qiita.com/masakinihirota/items/99054b9f9cf428881617
https://github.com/vercel/next.js/tree/canary/examples/with-http2
https://zenn.dev/chot/articles/99ae6acca1429b
他にもNextJSでHTTP/2カスタムサーバの設定中に参照したサイトはありますが、URLを失念しました。
Tableauのクエリパイプライン

Tableauが実行するさまざまなアクション（操作）の実行順序のことをクエリパイプラインと言います。

ユーザーが考えているフィルターの実行順序と、捜査の順序との間にズレがある場合、予期しない結果が出力されることがあります。

Tableauの操作順序の図は以下です。

ディメンションフィルターをコンテキストフィルターに変換する、表計算をFIXED詳細レベルの式に変換するといった各種変換は可能です。

リンク先にて事例が紹介されています。
![スクリーンショット 2023-01-21 19.00.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394349/bc31e2da-e75c-14a0-d348-c4df0be7cbbd.png)
https://help.tableau.com/current/pro/desktop/ja-jp/order_of_operations.htm
EKS PodがOOMKilledでクラッシュする

# はじめに
AWS EKSでk8sの勉強用でクラスタを立て、マイクロサービスアプリをデプロイした時に遭遇したエラー。

### 忙しい人用
ソース：[ノードよりも大きいメモリー要求を指定する](https://kubernetes.io/ja/docs/tasks/configure-pod-container/assign-memory-resource/)
要約してもそのままな気がするが、OOM(Out Of Memory)によってPodが不健全な状態のため強制終了と再起動が繰り返される。
そのためPodのリソースリクエスト量を増やす必要があるが、**ノードのキャパシティを超えるようなリクエストをしてしまうとPodがスケジュールされない**ので要注意!

# このエラーの見つけ方
・`kubectl describe pod xxxxxx`を実行したときに`Reason:`に表示される。
・`kubectl get pod`実行時の`STATUS`列を見る。
この辺りで十分かなと思います。

# スペック
EKSをEC2でホストし、podのマニフェストは以下のようになっています。
このくらいでいいかー。とてきとうにリソースリクエストを書いたのが悪かったです。
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
  labels:
    app: react
spec:
  replicas: 1
  selector:
    matchLabels:
      app:react
    spec:
      container:
      - name: react
        image: xxxxxxxxx:tag
        ports:
        - containerPort: 8000
        resources:
          requests:
            memory: 256Mi
            cpu: 250m
          limits:
            memory: 512Mi
            cpu: 500m
```

# 対策
- Podのスペックをあげる(足りなければノードに追加のリソースを与える or ノードの追加)
- 今回EKSをEC2でホストしているが、Fargateに変える。(limitを設けるなどすればコストの急増を抑制できる気が。)
予測可能なキャパシティであれば、[ResourceQuotas](https://kubernetes.io/ja/docs/concepts/policy/resource-quotas/)を使うと管理面で便利かも。

今回は練習のためリクエスト量を直に増やす。
ノードのスペックとサービスに必要なスペックを考慮する。(過剰なリクエストは控える。)
```yaml
~~~~~~~~~~~~~~
~~~~~~~~~~~~~~
    spec:
      container:
      - name: react
        image: xxxxxxxxx:tag
        ports:
        - containerPort: 8000
        resources:
          requests:
            memory: 1024Mi   # 256Mi -> 1024Mi
            cpu: 500m        # 250m  -> 500m
          limits:
            memory: 2048Mi   # 512Mi -> 2048
            cpu: 1000m       # 500m  -> 1000m
```
「npx create-react-app」でエラー

環境： Mac,zsh

>Error: EPERM: operation not permitted, uv_cwd

このエラーが出てアプリ作成できない。

### 試した方法（１）
ターミナルから「ファイルとフォルダへのアクセス許可」の権限があるか確認。
<img width="500" alt="スクリーンショット 2023-01-21 18.42.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117645/9e66b5f9-8bc7-a820-8de6-e52b78b550a0.png">
→既に付与済みだった。

### 試した方法（２）
ターミナルもしくはPC本体の再起動。
[yarnのissues](https://github.com/yarnpkg/yarn/issues/8787)で同じような質問を見つけたので試した。
→成功。
OpenStreetMapのタイル画像を事前生成する

自前のWebサイトに地図を使いたいけど、GoogleMapsを避けたいときなどは、OpenStreetMapを使うことが多いと思います。
その時に必要となるタイル画像を事前生成する手順のメモです。

## 地図用のデータを取得する

OpenSteetMapの地図データであるPBFファイルをどこかから取得する。
- https://extract.bbbike.org/

を使うと、必要なエリアの地図データのみ取得できる。

## OpenSteetMapのサーバーを立てる

神`Dockerfile`が公開されているので、簡単に構築できる。

```
$ docker volume create osm-data # データ領域を作る

$ docker run -v [取得したPBFファイルのフルパス]:/data/region.osm.pbf -v osm-data:/data/database overv/openstreetmap-tile-server import # データインポート

$ docker run -p 8080:80 -v osm-data:/data/database -d overv/openstreetmap-tile-server run # サーバー起動
```

`http://localhost:8080`にアクセスして、地図の動作確認ができる。

# タイル画像を生成する

[downloadosmtiles](https://metacpan.org/dist/Geo-OSM-Tiles/view/downloadosmtiles.pl)を利用する。

実行したディレクトリの直下にタイル画像が生成されるので、適当なディレクトリを作成して、その中から実行する。

モジュール`Geo/OSM/Tiles.pm`が必要なので、事前に入れておく。

``` bash
$ mkdir map_images
$ cd map_images
$ wget https://fastapi.metacpan.org/source/ROTKRAUT/Geo-OSM-Tiles-0.04/downloadosmtiles.pl
$ cpan install Geo/OSM/Tiles.pm
$ perl downloadosmtiles.pl --lat=[開始緯度]:[終了緯度] --lon=[開始経度]:[終了経度] --zoom=[開始ズームレベル]:[終了ズームレベル] --baseurl=http://localhost:8080/tile
```

以上。
[Python]Classモジュールの中でimport_moduleを利用して処理タイプ毎に動的にモジュールを読み込み実行する

# やりたいこと

Classモジュールの中に処理タイプ毎のモジュールを用意しておき動的に読み込み実行する


## Code

動作確認環境: Python 3.7.10

```
test.py
test_class/
　　├ __init__.py
　　└ func/
　　　　├ hoge.py
　　　　└ fuga.py
```

```python:test_class/__init__.py
from importlib import import_module

class test_class():
  def __init__(self, func_type):
    self.func = import_module(f".func.{func_type}", "test_class")

  def exec(self):
    self.func.main('test message'h)
```
Classの中ではimport_moduleを利用して動的にモジュールを読み込む
この時import_moduleはtest_classモジュールからの相対PATHで記載する


```python:test_class/func/hoge.py
def main(message):
  print(f"hoge {message}")
```

```python:test_class/func/fuga.py
def main(message):
  print(f"fuga {message}")
```
それぞれの処理であるhoge.pyとfuga.pyでは、同じ関数を用意しておくこと


```python:test.py
from test_class import test_class

hoge = test_class('hoge')
hoge.exec()

fuga = test_class('fuga')
fuga.exec()
```
→これのアウトプットは 
```
hoge test message
fuga test message
```

実際に利用する際は外部からの入力で読み込むモジュールを変更する


## 背景

EventBridgeからINVOKEされるLambdaで、渡されるeventタイプ毎に処理を定義したかった。
eventタイプは将来的に増える可能性があったため、eventタイプを追加する際に以下のポイントを見たす構成として本構成を採用した。

- 既存のコードを極力編集せずに処理を追加可能
- 万が一追加されたeventタイプのコードがエラーであったとしても、既存のeventタイプに対する処理に影響が出ない

eventタイプごとに、Lambdaを用意するという方法も検討したが、eventタイプが増えるに従いlambda関数が増殖するのを避けたかった。
Bundle.moduleを自前で取得する方法 (SwiftPM)

## はじめに
SwiftPM (Swift Package Manager)を使ったライブラリを開発するとき、
```Bundle.module```、使いたくないですよね？
```Bash
swift package init --type library
```
↑を実行してパッケージ基盤の生成直後に```Bundle.module```を使おうとすると、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95033/b2d6177a-f392-0a92-b16c-1efc262a3f12.png" width=300>
「```Bundle.module```とか知らねぇよ」と怒られてしまいます。
黙って```nil```を返してくれればいいのに、プロパティの存在が無くなってビルドエラーになるのは使いにくいと思います。


## 代替方法２選
### 1. allBundles
```Swift
static var alt1Bundle: Bundle? {
    for bundle in Bundle.allBundles {
        if let subBundleURL = bundle.url(forResource: "", withExtension: "bundle"),
           let subBundle    = Bundle(url: subBundleURL) {
            return subBundle
        }
    }
    return nil
}
```
```Bundle.allBundles```の中から探す方法です。
ループを回すのでちょっと非効率かもしれませんが、広い範囲を調べるので```Bundle.module```相当が見つかる可能性は高そうです。


### 2. BundleFinder
```Swift
static var alt2Bundle: Bundle? {
    class BundleFinder {}
    let bundle = Bundle(for: BundleFinder.self)
    if let subBundleURL = bundle.url(forResource: "", withExtension: "bundle") {
       return Bundle(url: subBundleURL)
    }
    return nil
}
```
```Bundle(for:)```の引数にはクラスしか渡せないので、```BundleFinder```と呼ばれる[^1]テクニックを使います。これによって```struct```や```enum```でも使えます。
知らない人が見ると「このクラスは何？」となる可能性は考えられます。

## 解説
処理の流れは以下の通り。
1. UnitTestがあるBundle「(ライブラリ名)Tests.xctest」を取得する。
1. その下にある「(ライブラリ名)_(ライブラリ名)Tests.bundle」を探す。
1. そのBundleが```Bundle.module```相当です。(独自研究)
```
.
├── xxxxxxxTests.xctest
│   ├── xxxxxxxTests
│   ├── xxxxxxx_xxxxxxxTests.bundle  ← Bundle.module
│   │   ├── Test.txt
```


## Bundle.module生成方法
```Bundle.module```を使う方法も書いておきます。

１. ```Package.swift```内の```testTarget```に```resources```の記述を追加する。(```target```でも可)
```Swift
.testTarget(
    name: "xxxxxxxTests",
    dependencies: ["xxxxxxx"],
    resources: [
        .process("./Test.txt")
    ]
),
```
２. Sources配下にファイル(本例ではTest.txt)を追加する。
```
├── Package.swift
├── Sources
│   └── xxxxxxx
│       ├── ・・・
└── Tests
    └── xxxxxxxTests
        ├── Test.txt
```
３. ビルドする。
４. ```Bundle.module```が使えるようになる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95033/e7e1852e-de83-98b6-8f00-99793dbef585.png" width=300>



## おわりに

ライブラリの開発中は問題がなかったけど、ライブラリをアプリに組み込んだ状態でビルドでしたら「**Type 'Bundle' has no member 'module'**」が出た！という問題を筆者は経験したことがあります。
ライブラリのテスト時には使うけど、ライブラリの配布時にはパッケージに含めないファイルがあると発生しがちだ思われます。
テスト時は本物のファイルで、配布時は空ファイルにすればいいのか？などと思案していますが、簡単で効果的な方法に辿り着いていません。
良い方法があったら教えてください。

[^1]:呼ばれてないかもしれない:stuck_out_tongue:
[Linux]TimeZoneの変更方法について

■環境
サーバ：EC2インスタンス
OS：AmazonLinux2
---------------------------------------
dateコマンドで日時がUTC表記になっているケースに遭遇したことはありませんか。
UTCのままでも特に不都合は生じないですが、日本時間に計算するのが煩わしい。
以下の方法で、簡単にTimezoneの変更ができます。

■手順
※日本時刻に変更するパターン

### ①"/etc/localtime"ファイルを置き換える
※シンボリック元のファイルは、自分がTimezoneに指定したい地域のファイルを指定する。

```
#ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
#ll /etc/localtime
lrwxrwxrwx 1 root root 30 Jan 21 17:45 /etc/localtime -> /usr/share/zoneinfo/Asia/Tokyo
```

### ②dateコマンドを打って、JSTに変更されたことを確認する
```
#date
Sat Jan 21 18:08:58 JST 2023
```

### ③再起動しても、Timezone設定が元に戻らないように、"/etc/sysconfig/clock"ファイルを修正する
※UTCの設定値を変更した場合、何か良くないらしいのでそのままで。

```
#cat /etc/sysconfig/clock 
ZONE="UTC"
UTC=true

#vi /etc/sysconfig/clock 
ZONE="Asia/Tokyo"
UTC=true
```

以上

■所感
過去にUTCのままで気にせずcron設定していたら、
+8H計算されて想定通りの時間に実行されなかったケースがあったので意外に注意が必要。
Orthographicカメラのグローバル座標幅を取得する拡張メソッド

・前提
カメラをOrthographic設定にしておくこと。

・コード

	public static class CameraExtension
	{
		/// <summary>
		/// Orthographicにおける、WorldPositionの撮影幅を取得
		/// </summary>
		public static float OrthographicWorldWidth(this Camera camera)
		{
			return camera.orthographicSize * camera.aspect * 2.0f;
		}

		/// <summary>
		/// Orthographicにおける、WorldPositionの撮影高さを取得
		/// </summary>
		public static float OrthographicWorldHeight(this Camera camera)
		{
			return camera.orthographicSize * 2.0f;
		}
	}
RHEL9をインストールしようとしたら妙なはまり方して時間を浪費した件

# クソ仕様な回線でインストールする場合のワークアラウンド
どうにもならない回線でRHEL9のインストールする場合のワークアラウンドというか対応フローを
備忘録的に書く

#　頼むからまともな認証方式にしておくれ・・・

1. インストール画面にてtabキーで以下のオプションを書く
　　inst.vnc
2. VNCの接続用のIPが出てきたら接続して接続後は次の手順を実施するまで触らない
3. Anaconda側（サーバ側）でalt + tabで切り替えてbashに入る
4. 次のコマンドで認証実行
wget --http-user=admin --http-passwd=di34Ld85 http://10.23.62.1/login.cgi
5.　RHELの登録を実施してインストールソースをRedhat CDNにする
6.　あとはふつーにやる

# 参考サイト
https://ex1.m-yabe.com/archives/2822

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html-single/performing_a_standard_rhel_9_installation/index#performing-a-rhel-install-in-vnc-direct-mode_performing-a-remote-installation-using-vnc

https://isleofhoso.com/rhel-rhn-subscription-add/#toc9
python(boto3)でS3上のファイルをコピーし、コピー元のフォルダごと削除

# やりたいこと
S3上の対象のファイルを別の場所にコピーして、そのファイルが格納されていたフォルダごと削除したいことがありました。
具体的には、AWS Glueでファイルを新規フォルダに出力した後、そのファイルをリネームして別のフォルダに移動させたかったのです。
S3を扱うboto3のコードは色々と検索でヒットしましたが、ドンピシャのものがなかったので記事にしてみます。

# 前提
以下がコピー元、先のURIと想定します。
少しわかりにくいですが、sampleフォルダの中にあるtest.txtを1階層上に「new_file.txt」という名前にリネームして移動します。その後、sampleフォルダは削除します。

・コピー元のファイル
`s3://sample-bucket/20230121_copy_glue/sample/test.txt`

・コピー先のファイル
`s3://sample-bucket/20230121_copy_glue/new_file.txt`

# 実装
これで動きました。
`sample`フォルダにはファイルが1つしか入っていない前提なので、1つのファイルをコピーしたらフォルダごと削除しています。
```python
import boto3

bucket_name = "sample-bucket"

# コピー
s3 = boto3.resource('s3')
s3.Object(bucket_name,"20230121_copy_glue/new_file.txt").copy_from(CopySource=bucket_name + "/20230121_copy_glue/sample/test.txt")

# コピー元ファイル（フォルダごと）削除
bucket = s3.Bucket(bucket_name)
bucket.objects.filter(Prefix="20230121_copy_glue/sample/").delete()
```

# おわりに
バケット名だけだったり、プレフィックスだけだったり、両方結合したり、スラッシュが入ったり入らなかったり、S3のパス指定は面倒ですね。
今回は1ファイルだけでしたが、s3の指定フォルダの中身の一覧を取得してコピーをfor文で実行、そして最後にフォルダごと削除すれば複数ファイルでもできると思います。
GitHubとGitについて


# はじめ
本記事について、GitHubとgitの内容と違いを記載しています。
記事を書こうと考えたきっかけとして、知人との学習を目的として利用したことがきっかけでした。
これは自分自身の勉強用として投稿しているので、間違って認識していることもあるかもしれない<br>ですが、ぜひ他の人の参考になればと思います。


## :point_up_tone3:Gitとは

***ソースコード***の***バージョン等***の管理を行う***管理システムツール***のこと（<font color="#cf0025;">分散型バージョン管理</font>）
目的として、開発をしやすくしたり、PJを管理しやすくすることが主な目的となる。

:thumbsup_tone3:利点と欠点:thumbsdown_tone3:
- 作成や編集したコンテンツを共有できる　利点
- GUI操作で操作も難しくない　利点
- コマンドを覚える必要がある　欠点
- 業界や会社によっては全く使用しない　欠点

## :point_up_tone3:GitHubとは

***Git***を利用して様々な***コンテンツ***を共有・公開・保存ができる***共有サービス***のこと。
「***Git***」の「***ハブ：拠点・中心・集まり***」という意味をもつ。

:thumbsup_tone3:利点と欠点:thumbsdown_tone3:
- 作成や編集したコンテンツを共有できる　利点
- GUI操作で操作も難しくない　利点
- アカウントを作成するのが面倒　欠点
- サービスのGUIが英語ベースであり、用語などが理解が出来ていない場合は操作が難しい　欠点

## :bulb:用語:bulb:
- ***Push***
このPushを実行すると、リモートリポジトリに自分の変更履歴がアップロードされて、リモートリポジトリ内の履歴変更がローカルリポジトリに変更履歴と同じ状態になる。
上記の内容を踏まえると、変更履歴がローカルとリモートで同じ状態になることを指す。<br>

- ***Pull***
このPullを実行すると、リモート→ローカルを更新する際に行う操作。
リモートから最新の変更履歴をダウンロードしてきて、自分のローカルにその内容を取り込むことができる。<br>

- ***Pull Request(プルリク)***
GitHubの操作機能の一つ。変更点を通知したり、分かりやすく表示したり、コードに関する内容が記載できる。


- ***Clone***
cloneはリモートリポジトリをローカルリポジトリへ複製することを指す。
cloneを実行すると、リモートリポジトリの内容を丸々ダウンロードでき、別のマシンにローカルリポジトリとして作成できる。<br>

- ***コミット***
ファイルやディレクトリの追加や変更を行う際、リポジトリに記憶する時に「コミット」を行う。
コミットを実行するとリポジトリ内で、前回コミットして時の状態から現在までの差分を
記録したコミットを作成される。<br>

- ***ブランチ***
履歴の流れ分岐して記録していくもの、分岐したブランチは最終的に合体する。
他のブランチの影響を受けないため、同じリポジトリ中で複数の変更を同時に進めてることができる。<br>

- ***リポジトリ***
サーバのようなもので、ファイルやディレクトリなどを保存や共有する場所のことを指す。


- ***ローカルリポジトリ***
ユーザ一人ひとりが利用するための、自分の手元のマシン上に配置するリポジトリ。
***※***<font color="#cf0025;">***ローカルPC（自身）の環境***</font>

- ***リモートリポジトリ***
専用のサーバに配置して複数人で共有するためのリポジトリ。いわばNW上のサーバのようなもの。
***※***<font color="#cf0025;">***インターネット側の仮想環境***</font>

  etc.....（ほかにも用語があるが、ここでの紹介はこれまで）

:point_up_tone3:GitとGitHubのなにが違うの？
---
上記でも
GitとGitHubの違いは、Gitはツールのことを指しており、GitHubサービスを指す。
Gitを使用したサービスがGitHubであることから、`＝`ではないということだ。

基本的にGitを使用しないとGitHubは使用できません。
逆にGitHubを使用せず、Gitは使用できます。
※Googleで調べると色々と出てくると思うので是非調べてく見てください。





# まとめ
:::note
- ***Git***と***GitHub***は`＝`ではなく、Gitを使用したサービスがGitHubにあたる
- 使用当初はとても混乱する
- コマンドとツールを覚えるのが面倒だが、慣れればとても便利なツール及びサービスである
:::

自分自身もIT業界のインフラ界隈の監視部分で仕事をしているため、Git及びGitHubを使用することはまずありません。存在は認知しているが、使用方法はもとより用途すら理解していないまま利用することになり、勉強するにつれ便利なツールだと実感させられました。インフラ界隈においては今後も利用することはほぼ無いですが、web業界のエンジニアの方はこれがデフォルトだと思おうと羨ましいと感じました。

実際に使用してみて、コマンド入れるのが慣れていないと抵抗感があるかもしれないと感じました。また実際に使用する際、全体のフローが理解できていないと使用時のどのようにすればよいかわからなくなると思います。


以上を踏まえ、まだ触ったことがない人は是非勉強してみてはいかがでしょうか。
今後の転職などを考えると勉強しておいても損はないと思います。本投稿を見ている方は、今後使用する機会があればぜひ色々と触ってみてほしいです。


# 参考サイト

- https://github.com/
  - GitHubの公式サイト　※アカウント登録が必要
- https://git-scm.com/
  - Gitの公式サイト　※Giインストールと設定が必要
マリアDBでテーブル作成時のエラー「there can be only one auto column and it must be defined as a key mariadb」

# マリアDBでテーブル作成時のエラー

下記のエラーが出て単純なSQLでテーブルが作成できませんでした。

```
there can be only one auto column and it must be defined as a key mariadb
```

どうやらオートインクリメント属性には、「primary key」を追加しないといけないらしい。

```
CREATE TABLE `trading_environment` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
```

「unique key」でもいいらしい。
下記のように単純にすればいいみたいです。


```
CREATE TABLE `trading_environment` (
  `id` int(11) unsigned AUTO_INCREMENT primary key NOT NULL,
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
```
Vue3 <script setup> 構文で孫、子、親のバケツリレーを書いてみた。

現在、Nuxt3, Vue3, TypeScriptsで開発をしております。

タイトル通り、孫、子、親のバケツリレーを書くことがありましたので、書き方をアップしていきます。
関係する部分のみ記載するため、ご注意ください⚠️

## 確認と前提
- propsの値は、子コンポーネントでは変更することを推奨されていない。
（挙動としてはできるが、vueの更新などで、できなくなってしまったら、システムとして成り立たなくなることもあるので、プロジェクトではやらない。）
- storeを使ったデータの受け渡しもあるが、データの動きがわかりづらくなり、コードが読みづらくなるため、うちのプロジェクトでは推奨されなかった。



## 孫コンポーネント
inputの枠やその周辺のコンポーネント
<FormInput>

```vuejs
<script setup langt="ts">
const props = withDefaults(defineProps<{
  val: string,
}>(), {
});
interface Emits {
	(e:'commentUpdate', comment: string): void;
}
const emits = defineEmit<Emits>();

</script>
<template>
　
  <textarea
    :autocomplete="props.autocomplete" // この値propsで送られてくる。（どんな値が期待されるかを示唆するもの。）
    :value="props.val" // 表示は親でする。 上記もだが、propsなくても良い。
    @input="emits('commentUpdate', ($event.target as HTMLInputElement).value);”
  ></textarea>

</template>
```

## 子コンポーネント
　input枠やその周辺のコンポーネントを含む、その他部分を足したコンポーネント。
<Result>
```vuejs
<script setup langt="ts">
const props = withDefaults(defineProps<{
  comment: string,
}>(), {
});

interface Emits {
  (e:'commentUpdate', comment: string): void;
}
const emits = defineEmit<Emits>();

</script>
<template>

  <FormInput
    :val="props.comment" // 親の値をそのまま孫へ
    :width="'100%'"
    @commentUpdate="emits('commentUpdate', $event)"　 // 親へそのまま値を持っていくだけのメソッド。
  />
</template>
　　ここの＄eventは孫の($event.target as HTMLInputElement).value)　入力されたもの。
```

## 親コンポーネント
```vuejs
<template>

<Result
  :comment='state.comment'
  @commentUpdate="state.comment = $event"
>

</template>
// 孫から子供を通ってきた値そのまま、stateに反映。
```

## 結論
孫から親へは、emitで値を送る。
親から孫へは、propsで値を送る。

参考
https://zenn.dev/k_kudo/articles/5e60caba140ad7
https://cloudsmith.co.jp/blog/frontend/2020/12/1656030.html
実機＆Androidエミュレータ上のサーバへの接続確認

PCのローカルで立てているサーバに対して接続確認したい場合の Local IPアドレスの指定について
ちょっと苦しんだので調査した結果をメモしておく。
以下、xxxx = port番号 を示す。

- PC の Web上(Chrome, Edgeなど) => PCのローカルサーバ　のケース
  - "http://localhost:xxxx" でOK
- Androidエミュレータ => PCのローカルサーバ　のケース
  - "http://10.0.2.2:xxxx"　
  - https://developer.android.com/studio/run/emulator-networking.html
  に記載がある
- Android実機 => PCのローカルサーバ　のケース
  - Windows のコマンドプロンプトで ipconfig コマンドを打って出てきたIPv4アドレス(ex. http://192.168.0.1:xxxx)
AndroidアプリでOpenCVを利用しようとした際のGradle Syncエラー対策

# はじめに
Android Application(Java)上でOpenCVを取り込んで動かそうとした際に引っかかったこととその対処のメモです。
ほとんど自分用に備忘録になります。
OpenCV SDKのバージョン:4.7.0

# OpenCVの取り込み
Android StudioへのOpenCVの取り込みはすでに分かりやすくい記載されている方がいるので以下を参照

https://qiita.com/tifa2chan/items/a2ec4f5d90eeb9cf1802

# GradleのSync error
参考ページのOpenCVの取り込みを実施し、openCVでモジュール名を設定しFinishしたところGradleのsyncで以下のエラーが発生
```
Plugin with id 'kotlin-android' not found
```

# 対応策
対処方法について調べていたところ以下に対策の記載があった

https://coskxlabsite.stars.ne.jp/html/android/OpenCVpreview/OpenCVpreview_A.html

どうやらOpenCVのAndroid SDKに含まれているGradleのスクリプトではデフォルトでKotlinを使用するようになっている模様。
今回はkotlinを使う必要がなかったため以下の部分をコメントアウト
```
//apply plugin: 'kotlin-android'
```

コメントアウトした結果Syncに成功してサンプルプログラムの動作に成功

# おわりに
Android ApPlicationで勉強がてら何かしらできないものかと考えていた際に、学生の頃にOpenCVをVisual C++上で動かしていたことを思い出し、Android上で画像処理を久しぶりにやってみようと思いたったはいいものの、Android Application環境のGradle周りについて知識が浅いので引っかかった
Gradleのスクリプトについては勉強が必要なことを学ばせてもらった
Docker alpineベースの環境でnode-gypのエラーが出た

# はじめに

Dockerでnodejsの環境をalpineベースで作成し、
 `supabase-js`をインストールしようとしたところ以下エラーが発生したのを修正した時のメモ。

# エラー時の状況・原因・解消方法

## 発現時の状況

```dockerfile:Dockerfile
FROM node:18.13-alpine3.16

RUN apk update

WORKDIR /var/www/app

USER node

CMD ["yarn", "dev"]
```

```yaml:docker-compose.yml
version: '3'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - "./front:/var/www/app"
    tty: true
```

```zsh
$ docker-compose exec app sh
/var/www/app $ yarn add @supabase/supabase-js

・
・
・
gyp ERR! find Python 
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON
gyp ERR! find Python checking if "python3" can be used
gyp ERR! find Python - "python3" is not in PATH or produced an error
gyp ERR! find Python checking if "python" can be used
gyp ERR! find Python - "python" is not in PATH or produced an error
gyp ERR! find Python 
gyp ERR! find Python **********************************************************
gyp ERR! find Python You need to install the latest version of Python.
gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
gyp ERR! find Python you can try one of the following options:
gyp ERR! find Python - Use the switch --python="/path/to/pythonexecutable"
gyp ERR! find Python   (accepted by both node-gyp and npm)
gyp ERR! find Python - Set the environment variable PYTHON
gyp ERR! find Python - Set the npm configuration variable python:
gyp ERR! find Python   npm config set python "/path/to/pythonexecutable"
gyp ERR! find Python For more information consult the documentation at:
gyp ERR! find Python https://github.com/nodejs/node-gyp#installation
gyp ERR! find Python **********************************************************
```

## エラーの原因・解消方法

* `node-gyp`の依存関係で起こったエラー。
* `node-gyp`とは、Node.jsのモジュールをコンパイルするコマンドラインツール。

公式の[Github](https://github.com/nodejs/node-gyp)を確認したところ、依存関係にはmakeやpythonが必要なようでした。

![スクリーンショット 2023-01-21 17.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/2d204961-e370-7b90-c327-81a7cbf1d9ce.png)

`make` `gcc` `g++` `python`の4つの依存関係をインストールすることで依存関係のエラーは解消できそうです。

## Dockerfileの変更

```Dockerfile
FROM node:18.13-alpine3.16

# 変更
RUN apk update && \
    apk upgrade && \
    apk add --no-cache make gcc g++ python3

WORKDIR /var/www/app

USER node

CMD ["yarn", "dev"]
```

変更後無事インストールできました！

```zsh
/var/www/app $ yarn add @supabase/supabase-js
yarn add v1.22.19

・
・
・

├─ whatwg-url@5.0.0
└─ yaeti@0.0.6
Done in 12.07s.
/var/www/app $ 
```
Expo - React NativeでFirestoreを使うとき、複数のファイルに分割する方法


<h1>状況</h1>
Firestoreのライブラリを作っていくとき、 [Firestoreの公式](https://firebase.google.com/docs/web/setup)には、このように1つのファイルに書いていく方法しか、記載がありません。

```typescript
import { initializeApp } from 'firebase/app';
import { getFirestore, collection, getDocs } from 'firebase/firestore/lite';
// Follow this pattern to import other Firebase services
// import { } from 'firebase/<service>';

// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
  //...
};

const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

// Get a list of cities from your database
async function getCities(db) {
  const citiesCol = collection(db, 'cities');
  const citySnapshot = await getDocs(citiesCol);
  const cityList = citySnapshot.docs.map(doc => doc.data());
  return cityList;
}
```

これらのFirebaesへのメソッドを、複数ファイルにしていくとき、
initializeAppを複数回呼び出すと以下のエラーが発生します。
（initializeAppを呼び出せるのは1回）

```
The default Firebase app already exists. This means you called initializeApp() more than once without providing an app name as the second argument. In most 
cases you only need to call initializeApp() once. But if you do want to initialize multiple apps, pass a second argument to initializeApp() to give each app a unique name.
```

<h1>解決方法</h1>

firebaes.firestore()をexportして、他のファイルから参照できるようにします。

```typescript:index.ts
export const fireStore = firebase.firestore();
```

そして、他のファイルから参照して使用。

```typescript:function.ts
import { fireStore } from "./firebase";

await fireStore.collection....
```

<h1>参考</h1>
https://nipo-plus-doc.sndbox.jp/tech/separate-files/index.html
https://yasutomo.hatenablog.com/entry/2021/01/13/215631
ラズパイzeroでのPythonの自動起動（systemdを使用）

　Raspberry Pi zeroにおいて，Pythonプログラムの自動起動で悩んだのでやり方を記録する．
## serviceファイルの作成
　/etc/systemd/system/内でserviceファイルを作成する．

```CMD:serviceファイルの作成
$ cd /etc/systemd/system/
$ sudo vim test.service
```

## serviceファイルの内容
　下記のように記載した．`User=Username` `Group=Username`にはOSのユーザ名を記載した．`After=network.target`にすることで，ラズパイがインターネットに接続された後に実行される．`ExecStart`は絶対パスで書くことに注意する．ただし`WorkingDirectory`にディレクトリを指定することで，実行ファイル名は相対パスでも動作する．


```CMD:serviceファイルの内容
[Unit]
Description=Test
After=network.target

[Service]
User=Username
Group=Username
Type=simple
WorkingDirectory=/home/pi
ExecStart=/usr/bin/python3 main.py

[Install]
WantedBy=multi-user.target
```

## serviceファイルの動作確認
　以下のように実行することでserviceファイルが動作するかを検証できる．
```CMD:serviceファイルの動作確認
$ sudo systemctl daemon-reload
$ sudo systemctl start test.service
$ sudo systemctl status test.service
```

## serviceファイルの登録
　上の結果がエラーなく`running`になっていれば問題ない．以下のようにすることで起動時に自動的に実行されるようになる．
```CMD:serviceファイルの登録
$ sudo systemctl enable test.service
解除は，enable -> disable
```

　上のように作業することでPythonプログラムを自動的に実行できるようになった．
【Python】前処理で区切り文字ごと抽出する方法

# この記事でわかること

以下の文章を

```
すごい！さすがですね。他には何か特技はありますか？
```

以下のように末尾の句読点`。`やはてなマーク`？`を残したまま分割したいときの解決法を紹介します．

```
[
"すごい！",
"さすがですね。",
"他には何か特技はありますか？"
]
```

splitメソッドだと以下のようになってしまいます．
```.py
sentence = "すごい！さすがですね。他には何か特技はありますか？"
print(sentence.split('。？！')

# 出力
>> [
"すごい",
"さすがですね",
"他には何か特技はありますか"
]
```

# 方法
末尾の句読点やはてなマークごと抽出したい場合はsplitではなく標準ライブラリ`re`にある`findall`メソッドを使いましょう．
以下のように末尾の句読点やはてなマークごと抽出することが出来ます．
```.py
sentence = "すごい！さすがですね。他には何か特技はありますか？"
print(re.findall("[^。！？!?、]+[。！？!?、]?", sentence))
# 出力
>> [
"すごい！",
"さすがですね。",
"他には何か特技はありますか？"
]
```
ArduinoIDEでCAN通信するときの準備

Auduinoでcan通信するときに必要なライブラリ**mcp_can.h**をインストールします。

## (1)下記サイトにアクセスしzipをダウンロード
https://github.com/coryjfowler/MCP_CAN_lib

## (2)zipファイルからライブラリインストール
ArduinoIDEを開き**スケッチ→ライブラリをインクルード→.zip形式のライブラリをインストール**から先ほどのzipファイルを選択します。
mocopiのトラッキングデータをUnityで利用する

ゲームで使うモデルのモーション作成めんどくさいなーと思っていたら
mocopiが発表されたので速攻で予約しました

初のモーションキャプチャーでしたが非常に使いやすいので記事にします

メモ書きの立ち位置なので参考にはあまりならないと思います

https://www.sony.jp/mocopi/

# mocopiとは
手足腰頭の6点にデバイスを装着してスマホと連携するだけでモーションキャプチャーができるデバイスです

加速度センサー＋角速度センサーをBluetooth通信でスマホに送信し、AIで各部位の位置を推測しています
https://www.sony.net/Products/mocopi-dev/jp/documents/Home/Aboutmocopi.html

VIVEトラッカーなどと比べると精度は低いのですが
・非常に軽量（8g×6）
・手足腰頭の6点なので着脱が簡単
・PCがない環境でもスマホで撮影可能
・5万円と非常に安価
などのメリットがあります

### デメリット
・やはり精度は高くない。イメージ伝達用のモックに使うのはあり
　・手を上げたとき、両手でなにかを持った時は大体ズレてる
　・割とすぐズレていく。10分くらいしたらリキャブレーションが必要
　・ちゃんとしたデータを作ろうとすると手直しが多すぎて厳しそう
・腰に付けるので座ると邪魔
・装着感がないからといってトイレに座るとホールインする危険があるので注意

# トラッキングデータをリアルタイムでPCのUnityで利用する
mocopiが <b>mocopi Receiver Plugin</b> を提供しています
https://www.sony.net/Products/mocopi-dev/jp/documents/ReceiverPlugin/Overview.html

- DLしてプロジェクトを開いてサンプルシーンを読み込みPlay
- mocopi側でPC接続設定をしてモーション送信を送る
  - IPアドレスの欄に送信先のPCのIPアドレスを入れてください
  - localhostにしか対応していません

<table>
  <tr>
    <th>Name</th>
    <th>ID</th>
  </tr>
  <tr>
    <td><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/07bd1972-05e5-df52-8de1-2adfa5686226.png" width="250"></td>
    <td><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/94cf2f44-38d1-e8bf-0a76-6d30de5c98cc.png" width="250">/td>
  </tr>
</table>

- するとUnity側でトラッキングデータを受け取ってモーション再生してくれます
  - うまくいかないときはスマホが家のLANに入っているか、mocopiでモーションの送信になってるか確認してください

![tracking_test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/8d09041c-9608-2b2c-38b8-ec126edd4c60.gif)


port指定ができるのでmocopiごとにportを指定することで
複数人のトラッキングにも対応していると思われます


# BVHをDLしてモーションデータとして利用する
- mocopiのモーションモードで撮影保存
- BVHファイルがmocopiフォルダに出力されるのでPCに転送
  - 私(iPhoneSE2)はGoogleDriveに挙げてからPCでDLしてます
    - アップロード > 参照 > ブラウズ > このiPhone内 > mocopi
- BlenderでBVHをインポート
  - 適当な人型モデルを用意してFile - Import - MotionCapture(.bvh)
- モーションデータを人体モデルに適用
- FBXとして出力
- Unityで取り込み

![sitting_gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/0aeba8be-d2d4-9c33-f29b-0cac60b504ff.gif)

# あとがき
blenderでモーションを打ち込んでいくのに比べれば
かなり簡単にモーション作成できるようになりました

なにか作らないと...
NextjsをFargateで起動するまで

## 前置き
- 一回やっただけだと頭からすぐ抜けていきそうなので、作業ログっぽい形で残す
- どうせGUIは変更が入るのでコマンドとテキストメインで

## Nextjsの準備
割愛。

## イメージの作成とローカルで確認
こっからちゃんと書く。
Dockerfileの準備。
```:Dockerfile
FROM node:14-alpine

WORKDIR /usr/src/app

ENV LANG C.UTF-8
ENV TZ Asia/Tokyo

COPY ./app/ ./

RUN yarn install && \
    yarn build
EXPOSE 3000

CMD ["yarn", "start"]
```

実際には管理しやすいようにイメージ名をECRのリポジトリ名にした。

```bash
// イメージの作成
$ docker build -t hoge .

// imageの確認
$ docker images

// 確認のためイメージの起動
$ docker run --rm -p 3000:3000 hoge
```

http://localhost:3000 で確認できる。

【追記】buildの際にplatformの設定をしないとfargateのタスクの起動・再起動が繰り返していた。以下で対応した。
```
$ docker build --platform linux/amd64 -t hoge .
```

## ECRにpush

- Amazon Elastic Container Registryにアクセス
- リポジトリの作成(リポジトリ名が必須だった)
- 「プッシュコマンドの表示」で表示されるコマンド通り進めばpushできる

一応書いとく。

```
// 認証を行う
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com

// イメージにタグつけ
$ docker tag hoge:latest xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge:latest

// リポジトリにイメージをpush
$ docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge:latest
```




## Fargateクラスターの作成・タスク定義
- その前にVPCの作成(割愛)
- 作業に入る前に言葉の意味の確認

#### タスク定義
- タスク定義とは、タスクを構成するコンテナ群の定義
- タスクとは、タスク定義に基づき実際に稼働するコンテナ群のこと


#### クラスター
- クラスターとは、コンテナを動かすための論理的なグループ

#### サービス
- サービスとは、コンテナを管理するための概念
- タスク実行数の定義
- ELBの設定、起動タイプの設定など

### タスク定義
- Amazon Elastic Container Service にアクセス
- サイドバーからタスク定義に移動
- 新しいタスク定義の作成をクリック

- タスク定義ファミリー名
    - 管理しやすいように「xxxxx-task-difinition」とした
- コンテナの設定
    - イメージURIはECRにpushしたイメージのURI
    - xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge:latest
    - ↑はECRのページからコピーできる
    - コンテナポートには3000番を追加しておく(nextjsを3000番指定したので)

### クラスター
- 「クラスターの作成」から作成
- ネットワーキング
    - VPCは、事前に作成したVPCを使用
    - もちろんサブネットも指定


## サービスとタスク作成
### サービス
- クラスターの詳細からサービスの作成
- デプロイ設定
    - ファミリーを指定する箇所で、前項で設定したタスク定義を指定する
    - タスク定義を更新していくとリビションが増えていくので最新でデプロイ設定しておく
    - サービス名: 必須
    - 必要なタスク
        - 起動するタスク数の指定。
        - 本来ならロードバランサー設定するので2を指定したいところだが今回は簡略化のために1を指定
- ネットワーキング
    - VPCはクラスター作成の時に指定しているので変更を加えない
    - セキュリティグループ
        - 3000番を開けておく

- 最後に作成
    - デプロイに数分かかる
    - http://[public ip]:3000

## デプロイに失敗したら
- タスクからログが観れるのでそこから修正すると早い
    - Next.jsが起動の確認
    - 起動できているのに繋がらない→ネットワーク、セキュリティグループ周りの設定見直し。

## 感想
- 事前にAWS公式のハンズオンやっていたのでスムーズだった
- コンテナさえ準備すればアプリケーションの開発に集中できるのすごい
- コード化したい
WindowsでMatlabからpythonを呼び出すためのインストール方法まとめ

# はじめに
Matlabからpythonを動かせるよう設定・テストしたので、忘備録を記す。

# 動作環境
Windows 10 
Matlab R2022b

# インストール前に
普通に使おうとすると下記エラーメッセージが出て使えなかった。そこでエラーメッセージに従ってpythonからインストールします。

>> py.myfunc
Python コマンドには、サポートされているバージョンの CPython が必要です。

Cpythonってなに？って調べると、C言語で書かれたpythonの一種だそうで、最も一般的なpythonだそうです。


# インストール方法
下記サイトにて、Matlab versionに対応するPythonを調べます。

https://jp.mathworks.com/support/requirements/python-compatibility.html

ダウンロードサイトはこちら（ここで、Looking for a specific release? を探して入れる）

https://www.python.org/downloads/


その際のハマりポイントが１点ありました。下記手順が必要です。
- 一回インストール後、アプリのインストーラーをoffにしてアンインストールする。
- その後再度同じpythonを入れる。その際にAdd python.exe to PATHにチェック入れる(下図)

![python_install2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915299/c014c9a9-0911-98fc-7491-a767b3a849ad.jpeg)

詳細はこのサイトに記載されています。
https://zenn.dev/ef/articles/fede252753800b12f42b

# 実行結果
Matlab上でpyenvを実行します。ただしくExecutableなどのpathが設定されていればMatlab上でpythonソフトを呼び出すことができます。

![matlab動作結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915299/485f849b-44e0-4490-314b-6d7999a16a02.png)

# おわりに
マニアックな情報ですが、誰かの役に立つことを願って。
Macで公開鍵と秘密鍵を生成する


# 環境情報
||バージョン|
|---|---|
|OS|macOS12.1|

# コマンド
## .sshディレクトリを作成し、移動する
```
$ cd ~/
$ mkdir .ssh
$ cd .ssh
```

## 鍵を生成する
```
$ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/{ユーザ名}/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): {任意のパスワード}
Enter same passphrase again: {任意のパスワード}
Your identification has been saved in /Users/{ユーザ名}/.ssh/id_rsa
Your public key has been saved in /Users/{ユーザ名}/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:v4UT6QGnjdhJ/TCDeKYxaojhv/0oNTU0yq+CLzePZb0 {ローカル環境のPC名}
The key's randomart image is:
+---[RSA 3072]----+
|                 |
|       + o       |
|.   . * B *      |
|.o . + % B *     |
|... o = S = .    |
|  .. o.. o +     |
|  ...oo.  = .    |
| o =*.. .  +     |
|  ++=+.E  .      |
+----[SHA256]-----+
```

## 鍵を確認する
```
$ ls -al
-rw-------   1 {ユーザ名} {グループ名}  2675  1 21 16:06 id_rsa
-rw-r--r--   1 {ユーザ名} {グループ名}   592  1 21 16:06 id_rsa.pub
```
ChatGPTに幸せについて聞いてみた

![スクリーンショット 2023-01-21 16.24.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978980/b9522715-d935-af21-6dea-ac986da5e7f1.png)
![スクリーンショット 2023-01-21 16.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978980/854966a4-0cb3-495b-a89c-2aa76939d0a5.png)
![スクリーンショット 2023-01-21 16.24.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978980/f86830b2-2e82-ee5f-baab-e6cfafd8e3f0.png)
![スクリーンショット 2023-01-21 16.24.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978980/7b9dbc37-f6d5-03b0-32a4-7a122fc7c5f7.png)

最後、どういたしましてだけじゃなくて、一言添えるのが、人間味あってすごい、、
M5Stackで始めるモノ作り・設計編

# あらすじ

M5Stackを使用して室内の観葉植物の土壌水分モニターデバイスを開発した話をそのまま時系列でいくつかに分割してご紹介したいと思います。最終ゴールはAlexaに連携させ、Alexaに尋ねると土壌水分状態を教えてくれるところを目指したいと思います。途中で設計変更など紆余曲折ありますが、果たしてゴールに辿り着けるのか。。。

先に結論を言うと、やり方が分かれば十行足らずのコードとクリックだけでAlexa連携デバイスを実現することも可能であることがわかりました。ただしAlexa連携に関してはついてはいくつか考慮すべき制約があるため、設計段階でそれらを踏まえておくことをオススメします。Alexa連携に関する情報はおいおい纏めて紹介できればと思います。

# プロダクトプランニング

最近、何鉢か観葉植物を買ったのですが、水のやり方についてお店の方に尋ねると色々と覚えることが多く、感覚を覚えて習慣化するまでは苦労しそうな感じです。観葉植物は種類によって比較的乾燥を好むものや、逆に沢山の水を好むものなど様々です。いずれの種類においても水を与え過ぎても、与えなさ過ぎても植物にとっては元気を無くしたり枯れさせてしまう原因となり、水をやる量やタイミングが大切です。水をやり過ぎると根腐れという症状で枯れてしまったり、とても暑くなる時間帯に水を与えると土壌の水が煮えて根にダメージを与えたり、逆に凍るほど寒い時期は水分が凍ってやはり根にダメージを与えたりするようです。

今回は室内に置くためタイミングについては枯らしてしまう程の懸念はなさそうなため、土壌の水分量を数値化し水を与える時期と量を知る手がかりとなる様にしたいと思います。ただし、数値化だけだと数値の意味がどの程度の乾燥状態を表しているのかイメージできないので、乾燥状態を把握できるものであって欲しいです。
その他にやりたいこととしては、既に何鉢かあり、後数鉢程増やそうと考えているため、各鉢の水分量を一元管理できるようダッシュボードで確認できるようにしたいです。
また、水を与える時期と量の感覚を覚えるための手がかりとして、水分量の履歴も必要です。履歴を見て植物の種類毎にどれくらいまで乾燥したら水を与えるべきか、感覚が掴めるようにしたいです。
最後にAlexaと連携し、Alexaに尋ねると現在の水分量を教えてもらえるようにする必要があります。ものぐさな私にとってこれは必須事項です。

## プロダクトデザイン

ということで、以下のような観葉植物の土壌水分量モニターシステムを作っていこうと思います。

### システム要求
* 土壌の乾燥状態が把握できること
* 水分量の履歴が確認できること
* 各鉢の水分量の一元管理できること
* Alexaと連携できること
* モニターデバイスはバッテリー駆動とし、単体で水分量が確認できること

以下は開発対象外とします。

* 各観葉植物の水分量と種類毎の適切な水やり時期と量についての学習は人間が行うことにします。 つまり私の脳みその仕事です。とは言え将来的には最低限閾値による通知を行えるようにしたい。。。
* 水やりも人間が行うことにします。 屋外なら灌漑設備を作るのも面白そうですが、室内のためポンプとかあると見栄えが悪くなります。


### システム構成
システム構成はざっくりと次のようにしたいと思います。
![システム構成.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481340/ac51ddb4-eca3-b40a-31dd-7fb056cc0d11.jpeg)

全てローカル環境で済ませようと思いましたが、Dockerコンテナが使えるNASが壊れているため、Dashboardについては適当なクラウドサービスを使用予定とします。Alexaはホームネットワーク上でローカル接続での連携とします（この部分は後日設計変更を迫られます）。

### 土壌水分モニターデバイス
土壌水分量の計測値は現在の乾燥状態がイメージできるよう１０段階のレベルで出力することにします。また土壌水分量の計測はバッテリー消費を抑制するため一定時間間隔での間欠動作にします。３〜６時間の間隔で測定するくらいで十分そうに思います。この辺りはやってみてから調整することにします。

センサーは個体差があることが予想されるため、値のバラつきを抑えるためキャリブレーション機能を搭載することにします。

土壌水分モニターの制御部分のハードウェアには、バッテリー駆動可能であるのとLCDを備えていることから単体でも利用可能なM5StickC plusを使用することにします。

土壌水分を計測するセンサーには、入手性が良く安価なものとしては抵抗方式と静電容量方式の２つがありますが、抵抗方式はセンサー部分の腐食が問題になるのと精度を考慮し、静電容量方式のものを採用します。

Pythonがマイコンでも使えることを知り使ってみたかったので、開発環境にはmicropythonを使用したいと思います。

ということで要件を整理すると次のような感じです。

##### 要件

* 土壌水分量を測定し、表示する
１０段階で数値化します。バッテリー駆動であることを考慮し、間欠動作にします。間隔は調整可能とします。
* センサーをキャリブレーションする 
センサーの個体差を吸収し、測定値が同じ基準になるようにします
* Alexaと連携する（後に変更を迫られます）

##### ハードウェア構成


* M5StickC plus
 バッテリー及びLCD搭載しており、単体だけで水分量の確認が可能
* 静電容量方式の土壌水分センサー
 腐食耐性と精度を考慮

##### 開発環境

* micropython 使ってみたかった（後に環境変更を迫られます）

### ダッシュボード要件
Dashboard as a serviceの選定要件としては以下の２つがあれば十分です。

* 現在のデータが確認できること
* 履歴データが確認できること
ひと月程度は欲しいところですが、贅沢は言わないことにします。

### Alexa
自宅にあるAmazon Echoを使用します。

# 次回
大体こんな感じで作って行きたいと思います。今回はここまでにして、[次回](https://qiita.com/Reiji-Nishiyama/items/c4b991c7a26405dde0fa)は土壌水分モニターデバイスを開発するために必要な環境をインストールして行きたいと思います。