OmniAICreator/Qiita-1.07M huggingface dataset:
ボタンをタップしても画面遷移できず、前の画面に戻れない

## はじめに
私は最近プログラミングスクールにて学習をスタートした初学者で、学習していく中で疑問に思ったことや苦労したことなどについて記事を書いております。


知識が浅はかですので、間違っている部分があるかもしれません。
あらかじめご了承ください。

## ボタンタップ時にエラー表示が出て画面遷移できない。

現在、簡易的なTwitterサンプルアプリを作成しているのですが、ツイート編集画面にて、ユーザー名とツイート本文を打ち込んでいるにもかかわらず、「ポストする」ボタンをタップしても元の画面に戻れずエラー表示が出てしまう。

![Screenshot 2024-04-26 at 23.34.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715605/2b0cc4a4-ec74-c121-f6e9-48e8c03470ad.png)


コードは以下の通りです。

```swift:ツイート編集画面

/// データを保存
    func saveData() {
        guard let userName = userNameTextField.text,
              let tweetText = tweetTextView.text else { return }
        do {
            let realm = try Realm()
            try realm.write {
                dataModel.userName = userName
                dataModel.tweetText = tweetText
                realm.add(dataModel)
            }
            // 前の画面に戻る
            dismiss(animated: true, completion: nil)
        } catch {
            print("データの追加エラー: \(error)")
            showAlert()
        }
    }
    
    /// アラートを表示
    func showAlert() {
        let alert = UIAlertController(title: "エラーが発生しました",
                                      message: "",
                                      preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        self.present(alert, animated: true, completion: nil)
    }
```

```swift:データモデル

import RealmSwift

class TweetDataModel: Object {
    @Persisted var id: String = UUID().uuidString //データを一意に識別するための識別子
    @Persisted var userName: String = ""
    @Persisted var tweetText: String = ""
}
```

## 原因

Realmのマイグレーションエラーでした。

最初は違うモデルで保存していたのに、
モデルの定義がuserName、tweetTextに書き変わってしまったので、
どっちを信じればいいのだろうか？

とRealmはなったわけです。

```swift:データモデル
    @Persisted var 最初違う名前でした: String = ""
    @Persisted var 最初違う名前でした: String = ""
```

## 解決策

一度デバイスから、アプリを削除する。

RealmやUserDefaultsなどの端末に保存する系はアプリ内に保存しているので、削除すれば消去できます。

例えばLINEを削除するとトーク履歴が消え去ってしまうのはそのためです。

## おわりに

Realmをインストールし、使うことで難易度が上がったような気がします。

これからもコツコツ学習していこうと思います。
[Unity]球面座標を用いた法線の圧縮

## はじめに
以前作ったVAT生成の仕組みでpotision texture の alpha に圧縮した法線を格納することでメモリ消費を削減したかったので球面座標を用いた法線圧縮について調べてみました

本記事は以下のWebページのコード(MIT License)を参考に作成されています

https://www.shadertoy.com/view/llfcRl

## 実装

検証用のshaderです
```hlsl
half spherical_16(float3 nor)
{
    float2 v = float2(0.5 + 0.5 * atan2(nor.z, nor.x) / 3.141593, acos(nor.y) / 3.141593);
    uint2 d = uint2(round(v * 255.0));
    return d.x | (d.y << 8u);
}

float3 i_spherical_16(half data)
{
    uint d = data;
    float2 v = float2(d & 255u, d >> 8) / 255.0;
    v.x = 2.0 * v.x - 1.0;
    v *= 3.141593;
    return normalize(float3(sin(v.y) * cos(v.x), cos(v.y), sin(v.y) * sin(v.x)));
}

v2f vert(appdata v)
{
    v2f o;
    float3 nrm = v.normal;
    half enc = spherical_16(nrm);
    o.normal = i_spherical_16(enc);
    return o;
}

fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = fixed4(i.normal, 1.0);
    return col;
}
```

左はModelのNormalをそのままfragment shaderで出力したもの
右はModelのNormalを圧縮して解凍したものをfragment shaderで出力したもの(前述の検証用shader)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440297/1921126f-bf9d-5da8-6808-07ff15111a7a.png)

## 解説

### 圧縮

ざっくり説明すると、直交座標系の法線を球面座標に変換して角度を2つ(phi, theta)を各8bitでhalf(16bit)に格納しています

```hlsl
half spherical_16(float3 nor)
{
    float2 v = float2(0.5 + 0.5 * atan2(nor.z, nor.x) / 3.141593, acos(nor.y) / 3.141593);
    uint2 d = uint2(round(v * 255.0));
    return d.x | (d.y << 8u);
}
```

球面座標は(r, theta, phi)で表される極座標系ですが、法線は単位ベクトルなので r(ベクトルの長さ)を記録する必要がありません

今回はxz平面のx軸から法線までの角度をphi、 y軸と法線間の角度をthetaとします
phi `−π < φ ≤ π` theta `0 ≤ θ ≤ π` です

`atan2(nor.z, nor.x)` と `acos(nor.y)` で各角度を求めることができます

```hlsl
float2 v = float2(0.5 + 0.5 * atan2(nor.z, nor.x) / 3.141593, acos(nor.y) / 3.141593);
uint2 d = uint2(round(v * 255.0));
```

上記の処理で `0 ≤ x ≤ 255`の範囲にします

```hlsl
return d.x | (d.y << 8u);
```
phiと8bit左シフトしたthetaの論理和を取ってhalfに格納します

### 解凍

```hlsl
float3 i_spherical_16(half data)
{
    uint d = data;
    float2 v = float2(d & 255u, d >> 8) / 255.0;
    v.x = 2.0 * v.x - 1.0;
    v *= 3.141593;
    return normalize(float3(sin(v.y) * cos(v.x), cos(v.y), sin(v.y) * sin(v.x)));
}
```
圧縮部分の処理が理解出来ていれば難しくはありません
phiとthetaを取り出して元の値に戻した後、球面座標から直交座標に変換しています

## 参考

https://www.shadertoy.com/view/llfcRl
DeepLのAPI呼んでみた

## はじめに
弊社運用中のアプリにてDeepLを用いた翻訳機能が必要になったため、その実装方法を備忘録として残しておこうと思います。

公式ドキュメントは以下になります。

https://developers.deepl.com/docs/getting-started/your-first-api-request

## 実装していく
まずbuild.gradleにライブラリをインストールします。
```kotlin
implementation("com.deepl.api:deepl-java:1.5.0")
```

次に公式ドキュメントにあるプログラムをそのままコピペします。
```kotlin
import com.deepl.api.Translator

class Example {
    private val translator: Translator

    init {
        val authKey = "f63c02c5-f056-..." // あなたのキーに置き換えてください
        translator = Translator(authKey)
        val result = translator.translateText("Hello, world!", null, "fr")
        println(result.text) // "Bonjour, le monde !"
    }
}
```

このままでも動きますが、アプリの仕様上今回はシングルトンである必要があるため、修正を加えます。

```kotlin
/**
 * DeepLへのリクエストを処理する
 */
object DeepLServer {
    private lateinit var translator: Translator

    fun init(authKey: String) {
        translator = Translator(authKey)
    }

    @JvmStatic
    fun translate(text: String, sourceLang: String, targetLang: String): String? {
        try {
            // 翻訳した結果を返す
            val result = translator.translateText(text, sourceLang, targetLang)
            return result.text
        } catch (e: Exception) {
            ErrorLoggerUtil.error("DeepLServer : translate : e = $e")
            return null
        }
    }

}
```

initでインスタンスを作成して、実際に翻訳します
```kotlin
// DEEPL_API_KEYは認証キー
DeepLServer.init(DEEPL_API_KEY)
val TranslatedValue = DeepLServer.translate("こんにちは", "ja", "en-US") ?: throw NullPointerException("null")
println("翻訳後のメッセージ: $translatedValue")
```

実行するとこんな感じ
```
翻訳後のメッセージ: Hello
```
以上で実装完了になります。

翻訳可能な言語については以下ドキュメントを確認してみてください。

https://developers.deepl.com/docs/resources/supported-languages#target-languages

## 最後に
公式ドキュメントの参考プログラムをちょっと変更しただけなので簡単に実装できました笑
気になっている方はぜひ導入してみてください！
ただ、翻訳の数が多いと料金も高くなりますので、気を付けましょう！
classってそんな使い方ができるの！？

#### はじめに

今回は、この1か月間HTMLとCSSを学ぶ中で、私自身が躓いた**class**をまとめようと思います。もしかすると、「こんな簡単なこと」と思われてしまうかもしれませんが、私と同じく、右も左もわからないような、これからプログラミングを学ぶという人など、少しでも参考になれば嬉しいです。

#### 【div class】

"div class"はHTMLに記述したコードを分類するときによく使われます。

```ruby:例

<div class="box"></div>

```

このdiv classは複数のコードに処理をする場合に使われますが、下記の例のように、ひとつだけ違う指定をすることも出来てしまいます。

```ruby:例

<div class="content-block">
    <p>box1</p>
</div>
~~~~~
<div class="content-block box-yellow">
    <p>box7</p>
</div>
~~~~~
<div class="content-block">
    <p>box18</p>
</div>

```

うん、とても便利ですね。


#### 【p class】

先ほどは"div"というブロック要素を使用しましたが、実は"p"タグにもclassをつけることが出来ます。例えば下記の例のように、同じ言葉でもひとつだけ位置や状態を変えたい場合はこの方法によって簡単に指定することが出来ます。（私はpタグにclassをつけることが出来ると知らずに、しばらく悩んでいました。。。）

```ruby:例

<p>仮テキスト</p>
<p class=text-left>仮テキスト</p>
<p>仮テキスト</p>

```

こちらも便利ですね。

#### おわりに

今回は、簡単に2種類まとめてみましたが、プログラミングを学ぶ中で気づいたことがあります。

それは。。。。。

**固定観念に縛られず、思いついたら試せ！！！**

拙い記事ですが、ここまで読んでいただきありがとうございました。
自然言語処理のお勉強1

# はじめに
自然言語処理の基礎的な知識を勉強したのでまとめます。
# 自然言語処理とは
自然言語処理(NLP: natural language processing)とは、自然言語（人間が日常的に使う言語）をコンピュータで扱う技術のことです。プログラミング言語とは違い、厳密な決まりがない自然言語をコンピュータで扱うところに難しさがあります。
# 基礎的な技術
自然言語処理における基礎的な技術について簡単にまとめます。
## 形態素解析
文章を形態素と呼ばれる単位に分割し、形態素の品詞や辞書の見出し語を判別する技術です。よく似た言葉にトークンと呼ばれるものがありますが、ほぼ同じと考えても良さそうです。
## 係り受け解析
文章を文節または単語で分割し、修飾、被修飾の関係を明らかにする技術です。構文解析と呼ばれることもあるようです。
## 固有値表現
文章から実体(entity)を取り出す技術です。実体とは実世界に存在し、識別可能な物体や事象です。
# 参考にした文献
1. BERT/GPT-3/DALL-E 自然言語処理・画像処理・音声処理 人工知能プログラミング実践入門
2. [自然言語処理への第一歩](https://zenn.dev/akimen/articles/650ef89878915e)
3. [わわわIT用語辞書](https://wa3.i-3-i.info/word11594.html)
【Next.js】最適化された画像のキャッシュ期間を変更する方法

`next.config.js`に以下のように記述すると最適化された画像のキャッシュ期間を変更できます。
デフォルトでは60秒になっています。

```js
module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

```

個別で変更する場合には `headers`　を使用して `Cache-Control`ヘッダーを設定します。

https://nextjs.org/docs/app/api-reference/components/image#minimumcachettl

https://nextjs.org/docs/app/api-reference/next-config-js/headers
タイムラインでのふりかえりを試してみたい

[Qiita×Findy記事投稿キャンペーン 「今の開発組織でトライしたこと・トライしていること・トライしようとしていること」 - Qiita](https://qiita.com/official-events/06e1e6af790c81a75b7f) に向けて書いた記事で、このうちトライしようとしていることについて書いてみたいと思います。

なお、今の「システム開発組織で」とありますが、この記事はあくまで私の個人的な感想・視点に基づいた個人的な意見であり、組織や所属するチームを代表するものではございません。
また、過去の複数の開発組織やプロジェクトを思い返しながら書いているため、必ずしも「今の」開発組織の話にフォーカスした話ではありません。
予めご了承ください。

また [Zenn](https://zenn.dev/yumechi/articles/b13ba28b01d589), [Qiita](https://qiita.com/yumechi/items/396ca4f724f39bfd2ce7) に同じ内容を投稿しています。

## これまでの開発をふりかえってみて思っているふりかえりの難しさ

背景として私は現職で4社目になり、いくつものプロジェクトに参加してきました。
参加したプロジェクトについては途中で抜けてしまったものの（現場都合や、組織上の再配置など原因は多岐にわたります）、最後まで参加できているものについては比較的うまく終わることが多いように思っています。
一方で、プロジェクトとして納期やコストを守りつつ機能やビジネスニーズを満たすような成果は出せているものの、いろいろな課題が見つかることは多いです。
例えば、コミュニケーションですとかスケジュールを守るために労働時間でカバーするなどがあり、プロジェクトを完了することはできていても、その過程での課題を解決できなかったことも多いです。

そのためふりかえりを行うことは非常に重要だと考えています。
ふりかえりはプロジェクトの成果を振り返るだけでなく、その過程での課題や問題点を見つけるための手法としてもとても有効であると感じています。


## 手法に対する課題

一方、ふりかえりの実施はメンバーとしての参加、ファシリテーターとしての参加の両方で場数を踏んできましたが、その中でいくつかの課題を感じていました。
特に期間が長かったもののふりかえりが難しい、と考えています。ファシリテーターとして参加する立場になってからも、期間が長いふりかえりは回数が少なく、またその度に難しいなと感じています。

ふりかえり期間が長いと、その間に起きたことを思い出すのが難しくなります（期間が長い、は1～3か月以上のイメージです）。
その時は確かに問題であったものも、プロジェクト中で解決されたことで忘れてしまい、埋もれてしまうことも多いです。

また、ふりかえりの手法についても課題を感じています。
KPT フレームワークを採用してのふりかえりは多いですが、KPT フレームワークでのふりかえりは個人的に長期間のふりかえりに向いていないと感じています。
理由としては下記です。

- 期間が長すぎてその間に起きたことを思い出すのが難しい
- 期間が長いと付箋がふえて、KPTの性質上Tに対して紐づくK, Pが多く関係性が複雑になってしまう
- 悪い印象のあった思い出が想起されやすく（？）、P ばかりが出てしまうケースが何となく多いように感じる
- 感情や価値観を含んだ意見が出しずらく、ぼやけやすい

なお、KPT フレームワークはスクラムのスプリントなどで、短く見て傾向と対策を考えていきやすいと考えています。
知っている方も多いので学習コストも低いという点から実施しやすい優秀なフレームワークであると思います（後で触れますがふりかえり手法は適材適所であり、ふりかえりの目的に合わせて選択することが重要だと考えています）。

## タイムラインによるふりかえりを試したい

タイムラインはふりかえりの一つです。下記の記事がわかりやすいと思います。

[ふりかえりのアクティビティ紹介：Timeline #ふりかえり - Qiita](https://qiita.com/viva_tweet_x/items/2127531c37c170f39409)

タイムラインは、プロジェクトの進行を時系列で振り返る手法です。
タイムラインでのふりかえりは性質上、どのタイミングで何が起こったか・何を行ったが明確になるため時間軸をもとにふりかえることに向いています。
なので、長期間であっても相対的に物事を並べていくことで、比較的その間に起きたことを思い出しやすくなると考えています。

またタイムラインでのふりかえりは、感情面も含めてこのときに思っていたことを共有することができます。
心境の変化というものは長期視点だと大事だと私は考えています。つらい時期はどうしても物事の進捗などが悪くなりがちです。
そういったものも含めて、要因を考えつつ最終的にうまくいく方向に向かって心境が改善していくというのも大事だと考えています。

一方で私はまだタイムラインでのふりかえりを実施したことがないため、実際にどのような効果があるのかはわかりません。
そのため今の開発組織でトライしたいこととして、タイムラインでのふりかえりを試してみたい、試すぞ！と思っています。

## ふりかえりは複数の方法を試していい

ふりかえりというと、私の経験上はどうしても慣れた手法が選択される傾向にあるように思います。
一方で、ふりかえりは目的やターゲティングによって手法を変えることが重要だと考えています。

例えば、スプリントごとの課題を発見していきたいというメンバーが多い場合では YWT ではなく KPT が適しているかもしれません。
それは Problem を確実に発見して改善することでプロジェクトの障壁を取り除きたい、という目的があるからです。

逆にふりかえりで後ろ向きになってしまう場合などもあるかもしれません。
そういったときは一度、自分たちができていることに目を向けもっと伸ばしていきたいことを見つけるために YWT などを試してみて自分たちを見直してみるのもいいかもしれません。

そういったようにふりかえりは向き不向きがあり、これだけでよい！というのはないと考えています。
下記の記事でいろいろなふりかえり手法が紹介されているので、ふりかえりを試してみたいと思った方は参考にしてみてください。

[ふりかえりを拡張する「ふりかえりカタログ」 #ふりかえり - Qiita](https://qiita.com/viva_tweet_x/items/cc3bad3bd298406b6cc7)

## ふりかえりから向き直りたい

また、ふりかえっただけでなく、今後に生かしていくむきなおりも大事です。
むきなおって現状の先にあるものをさらに良いものに変えていくための分析材料として、ふりかえりが活用できると考えています。

これからも試行錯誤しながら開発組織をリードし、よりよいプロダクト作りやプロジェクトの成功に貢献できるよう、ふりかえりという題材を通じて自分自身・チーム全体の改善につなげていきたいです。
カスタムリソースを使用してS3内オブジェクトを削除

下記の記事でCloudFormationのスタックを削除しても、S3にオブジェクトが存在すると削除できなかった。
カスタムリソースでLambdaを使用してオブジェクトを削除するようにする。

https://qiita.com/kutinasi_hobby/items/496fe8ed149d72673b10


今回作成するLambdaはほかのCloudFormationでも使用することがあると思うので、別のyamlファイルとして作成する。
注意：上記記事で作成したyamlファイルでスタックを作成する前に下記ファイルでLambda(カスタムリソース)を作成しておく必要がある。

### Lambda用yaml作成
こちらの記事を参考に作成

https://qiita.com/hiyanger/items/5b00cb5ebc7128b178c0

※LambdaFunction の Runtime: python3.7 が現在 python3.12になっているので変更

```yaml
  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: s3delete
      Role: !GetAtt s3deletelambda.Arn
      Runtime: python3.12 # ←ここ
```

Lambdaのコードはこちらの記事を参考

https://dev.classmethod.jp/articles/custom-resource-empty-s3-objects/

※まだLambdaに設定が必要なので、Lambdaのスタックのみ作成してください。

これでLambdaを使用してCloudFormationスタックを削除するタイミングでS3オブジェクトを削除するようになりました。
しかし、Lambdaの部分で下記エラーが発生してしまいます。
```
[ERROR] Runtime.ImportModuleError: Unable to import module 'index': No module named 'requests' Traceback (most recent call last):
```
どうやらrequestsのバージョンがpython3.12に対応していないようです。

### エラー対応
作成したLambdaにレイヤーを追加します。
・Labdaの右下にあるレイヤーの追加を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/8bc9a1d7-b5f0-58e0-79ec-904e4514f5f7.png)

・ARNを指定を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/6eadf844-09a6-f1d4-3248-b435e5e99d71.png)

・下記サイトからから対象ライブラリのARNを取得します。
https://github.com/keithrozario/Klayers/tree/master/deployments

・東京リージョンで作成しているので Asi Pacific(Tokyo)のhtmlを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/add85833-ddd1-2568-d0ad-7c9995e4390d.png)

・requestsのARNが欲しいので Package: requests のarnをコピー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/e29bb774-0225-693f-f02b-26c26587412b.png)

・LambdaのレイヤーのARNを指定に張り付けて追加すればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/37f0dd57-7c20-b374-cdb5-7eed9f32456c.png)

これでS3やCodePipelineのCloudFormationスタックを実行してもエラーにならないはずです。
エラーになる場合は同じ手順でライブラリーを追加してみてください。
※ライブラリ追加せずに実行すると1時間ほど本当に処理が固まるので注意してください。

以上
Djangoの環境構築始めました。

# Djangoの環境構築！
## よし、Djangoを入れよう！ってなる前に。。
　はじめはDjangoをサイトからダウンロードしてってやろうとしましたが、どうやら参考書を見てみるとそれは大変らしい。。
なぜなら、Webサイトを作るフレームワークなため、Webサーバを借りて、アップロードして、変更してとそんなの初心者ができるわけない。そのため、全部セットアップしてある環境を使いたい。
## それがAnaconda
　Anacondaってでっかい蛇？映画のやつ？って思った私。これは、Python のディストリビュート（様々なプログラムをパッケージ化し、ひとまとめにして配布しているもの）の一つ。これを使うと便利らしい。
## 入れ方は公式ドキュメント見てくだちぃ。。
ごめんなさい。ほんとはしっかり説明したいけど、たぶん他の人のやつ見た方がわかりやすいかも！
## 余談: 本ではSpyderと呼ばれる、テキストエディタを使ってるけど。。
 私はVScodeしか使ったことが無いのが原因だと思うけど、Spyderちょっと使いにくかった笑(まだ魅力が伝わるまで使ってないってのもあるかも)
なので私は普通にVScodeで書いていきます！
2024/04/13～2024/04/19に公開されたCVEの件数と個人的に気になったもの

# はじめに
脆弱性がたまに話題になりますが、一週間の間にいくつの脆弱性が公開されているか知っていますか？

本記事では、2024/04/13～2024/04/19の一週間の間に公開されたCVEの件数とその中で個人的に気になったものについてまとめてみました。

# 2024/04/13～2024/04/19に公開された脆弱性

| 概要 | 件数 |
| --- | --- |
| 公開されたCVEの件数 | 1038件 |
| CVSS Base Scoreが7.0以上であるCVEの件数 | 265件 |

今回初めて一週間の間に公開された脆弱性の数を調べてみましたが、想像以上に多いですね。一日に140件程度公開されています。

今回調べた期間中ではありませんが、Palo Alto Networks社PAN-OSの脆弱性（CVE-2024-3400）も4月12日に公開され、話題になっていました。

# 気になったもの

期間の中で気になった脆弱性について調べました。

## CVE-2024-28185

### 概要

> https://nvd.nist.gov/vuln/detail/CVE-2024-28185
> 

CVSS Base Score：10.0

judge0（Githubのスター数は2000）というオンラインでコードを実行できるOSSでの脆弱性。シンボリックリンク経由でサンドボックスをエスケープできます。

このアプリケーションでは、サンドボックスディレクトリ内に配置されたシンボリックリンクを考慮していなかったため、攻撃者がこれを利用して任意のファイルに書き込み、サンドボックスの外でコードを実行できる可能性がある脆弱性についてです。

### 詳細

下記はユーザが送信した実行コードを実行するときのコードの一部。

```ruby
run_script = boxdir + "/" + "run"
unless submission.is_project
	# gsub is mandatory!
	command_line_arguments = submission.command_line_arguments.to_s.strip.encode("UTF-8", invalid: :replace).gsub(/[$&;<>|`]/, "")
	File.open(run_script, "w") { |f| f.write("#{submission.language.run_cmd} #{command_line_arguments}")}
end
```

judge0では、実行するためのコマンドをrun_scriptに書き込みを行います。攻撃者はrun_scriptにシンボリックリンクを作成でき、`f.write`がシステム上の任意のファイルに書き込む可能性があります。

```yaml
services:
    server:
      image: judge0/judge0:latest
      volumes:
        - ./judge0.conf:/judge0.conf:ro
      ports:
        - "2358:2358"
      privileged: true # ← 特権モードのフラグがtrue
      <<: *default-logging
      restart: always
```

さらには、`docker-compose.yml`では特権フラグを使用してDockerコンテナが実行されているため、攻撃者はLinuxホストファイルシステムをマウントできるようになり、悪意のあるcronジョブなどを書き込んでシステムにアクセスできてしまいます。

### 対策

脆弱性を修正したversionは公開されています。脆弱性のあるversionは、v1.13.0以下。

対策としては、最新のversionである1.13.1以上にアップデートすることです。

# おわりに

コンテナのセキュリティとして特権モードのフラグを立ててはいけないと言われますが、CVE-2024-28185の事例を見て、改めて特権モードでの実行の怖さを実感しました。

何かおかしな点がありましたらご指摘ください！

# 参考文献

- https://nvd.nist.gov/vuln/detail/CVE-2024-28185
- https://github.com/judge0/judge0
- https://github.com/judge0/judge0/security/advisories/GHSA-h9g2-45c8-89cf
- [CVEdetails.com（今回調べた1038件の脆弱性の一覧）](https://www.cvedetails.com/vulnerability-search.php?f=1&vendor=&product=&cweid=&cvssscoremin=&cvssscoremax=&publishdatestart=2024-04-13&publishdateend=2024-04-19&updatedatestart=&updatedateend=&cisaaddstart=&cisaaddend=&cisaduestart=&cisadueend=&page=52)
gem install 時の permissions エラーの対応

いまさらながらGithub　Pagesでプロフィールでも整備するかと思い立ち、おもむろにgem install したらpermissions error に遭遇しました。

```
% gem install bundler jekyll
Fetching bundler-2.5.9.gem
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.
```

下の記事によるとどうやらシステムのrubyを利用していると、権限不足でgemのインストールができないというエラーのようです。

https://qiita.com/nishina555/items/63ebd4a508a09c481150

gem install bundler jekyll ができるところまで手順を残しておきます。

- 環境
macOS Ventura

# 現状確認

```
% which gem
/usr/bin/gem
% which ruby
/usr/bin/ruby
```

# rbenvでrubyを管理する

rbenvをインストールします。
```
# brew update
% brew update

# rbenvのインストール
% brew install rbenv ruby-build

# 現在利用しているバージョンの確認
% rbenv versions
system
```
現在はシステムにインストールされている環境を使用しているようです。
rbenvの管理下に安定版のrubyをインストールします。
```
% rbenv install -l
3.0.7
3.1.5
3.2.4
3.3.1
jruby-9.4.6.0
mruby-3.3.0
picoruby-3.0.0
truffleruby-24.0.1
truffleruby+graalvm-24.0.1
```
現在(2024/4/26)はバージョン3.3.1が安定版として提供されているようです。
3.3.1をインストールします。
```
#ruby 3.3.1のインストール
% rbenv install 3.3.1

# バージョンの確認
% rbenv versions     
* system
  3.3.1
```
3.3.1をglobalでするように変更します。
```
# バージョンの切り替え
% rbenv global 3.3.1

# 確認
% rbenv versions    
  system
* 3.3.1 (set by /Users/unsername/.rbenv/version)
```
rbenvにパスを通すため、シェルの設定ファイル(.bashrcや.zshrc)に以下を追加します。
```
vim ~/.zshrc
```
追加内容
```
[[ -d ~/.rbenv  ]] && \
  export PATH=${HOME}/.rbenv/bin:${PATH} && \
  eval "$(rbenv init -)"
```
vimの操作については下記を参考にします。
https://qiita.com/hide/items/5bfe5b322872c61a6896

# 確認
シェルを再起動して、rubyとgemのパスを確認してみます。
```
% which ruby 
/Users/username/.rbenv/shims/ruby
% which gem 
/Users/username/.rbenv/shims/gem
```
先ほどインストールしたruby3.3.1のパスになっています。
# gem install

gem installに再チャレンジ
```
$ gem install bundler jekyll

 ...gems installed
```
gem installができるようになりました！
ほとんど参考にさせていただいた記事を同じ内容になりました。現在もこの対応で良さそうです。

プロフィール作る作業に戻ります。
コスパ最強の自作NASへの道 その2

# JONSBOの新しいNAS用ケース、N4を購入してみました

https://www.jonsbo.com/en/products/N4Black.html

しかしこのN4は日本ではほとんど販売されていません。もし販売されていても、値段は高価です。そこで私はAliExpressから購入してみました。価格は1万5000円で送料無料でした。注文してから2週間で届きました。段ボール箱にはサランラップで包装されており、少しへこみがありましたが中身は無事でした。

# 良いところ
+ 3.5インチハードディスクが6台収納可能
+ 比較的小さいサイズ

# 悪いところ

+ ハードディスクが6台搭載できるものの、そのうち2台はホットスワップができず、4台のみ可能です。
+ ケースが弱々しい
+ ハードディスクのネジ部分にゴムを付けて押し込む構造になっているため、取り外しを繰り返すとゴムが摩耗し、破れる可能性があります。

少し高くてもSILVERSTONEのケース(SST-DS380B)の方が良かったかもしれません。

![DSC_4731.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/9d293212-7f22-31d3-b64a-6808bff10ed1.jpeg)
![DSC_4733.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/6675fcab-490a-19c0-329d-691ac8e1bd0a.jpeg)
![DSC_4734.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/f2ac073f-79d3-c46d-3b08-75a49bfac29d.jpeg)
![DSC_4737.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/02948b5d-6fc3-c29c-a2a6-0cdfe82f6be5.jpeg)
![DSC_4747.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/5ea42d3b-f805-3894-0f5b-f5e8bf5928b5.jpeg)
![DSC_4751.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/0b576d32-020a-b1d8-594e-8d6fa623eb1b.jpeg)
![DSC_4753.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/87080341-47fc-702d-6940-7c63f4447184.jpeg)
![DSC_4755.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/6f5e69b0-70a5-9b09-0a62-94a95c3603c5.jpeg)
![DSC_4756.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/26281601-d17f-896e-b064-1db19531083a.jpeg)
![DSC_4757.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/378e3566-bbab-502a-993a-a86693a6de3d.jpeg)

まあ安いから仕方がない。
ハードディスクは6台搭載予定で残り3台はセールの時に買おうと思います。

# 金額は
48TBのNASを作るのにかかった金額です

| 項目                           | 価格       |
|-------------------------------|------------|
| ケース JONSBO N4                      | 15,000円   |
| マザー BKHD-1264-NAS                  | 20,500円   |
| 電源 SilverStone SST-ST30SF-V2   | 8,000円    |
| メモリ DDR5 32GB CMSX32GX5M1A4800C40  | 12,500円   |
| HDD WD80EAAZ (8TB x 6台)                | 104,000円  |
| S-ATAケーブル Cable Matters SATAケーブル(6本) | 1,100円   |
| M.2 SSD 128GB(余りパーツ) | 0円   |
| **合計**                       | **161,100円** |

下記の製品だと箱代だけで11万なので、HDDを追加すると22万は必要です。

https://kakaku.com/item/K0001445184/
【合格体験記】AWS Certified Data Engineer - Associate (AWS DEA)

# はじめに
2024年2月に All Certificationを達成したので、
その勢いのまま正式リリースされたDEAも取ってしまおうと思ったのですが、
結果は思ったよりギリギリの合格。。
今後学習する方々のために体験記を残します。

■バックグラウンド：AWS実務経験アリ(2年ほど)
　ただ試験範囲に関わるような業務はほぼ無し


# 結果
クエリ系の問題をノーマークでほぼ外した自覚があるので、
第3分野の得点が低くなっちゃった気がする。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778694/99f0064f-f371-2c97-a9fb-46b94d46cb47.png)

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778694/352d2240-d361-7b50-d1cf-f004c0ba9dca.png)

# 対策期間・学習方法
#### 対策期間
計3週間（勉強時間：20-30時間）
#### 学習方法
■ Udemy AWS認定Data Engineer Associate（DEA-C01）試験 対策トレーニング
&emsp;URL : https://www.udemy.com/course/aws-data-engineer-associate-dea/
 
 →基本的なサービス、設定、オプションは一通り学習することができます。
　ただし内容がAWS Certified Data Analytics - Specialtyを基準に
　構成されているため、おさえておきたい範囲の過不足はありました。
　最後の演習問題はDASの試験基準なので受けなくていいです。

■ AWS公式の模擬試験
URL :  https://awscertificationpractice.benchprep.com/app/official-practice-question-set-data-engineer-associate-dea-c01#exams

 →1,2問はほぼ同じ問題が出ます。
　全体的な学習範囲の確認と、上のUdemyでおさえられなかった
 　サービスを確認して試験範囲の潰し込み。

# 所感
・Associate試験同士で難易度を比較すると、
　**SAA=DEA>DVA>SOA** こんな感じだと思います。
　新しい試験ということもあり、少し難易度は高めかと思います。
・Glueが特に頻出でした。S3やRedShiftとの連携、
　連携のためになにを使うのか
　(S3イベント通知なのかStep FunctionsなのかGlueワークフローなのか)
　このあたりは時間をかけて勉強することをオススメします。
・RedShift、S3、Glueは細かい機能に関する問題や、
　どのクエリが正しいでしょうor高速でしょうなどの問題が出ます。
　机上だとなかなか勉強しにくい範囲ですが、
　AWSの公式ページを参考にしておさえておきたいところです。

# Data Analytics - Specialty保有者に向けて
DASを取得されていた方は、DASの内容の復習から始めると思います。
その際に気を付けたほうがいいことを下記に記します。
　・Apacheのコンポーネントに関する詳しい理解は必要なかったです。
 　　(HadoopとかHBaseとか)
   　　↑Airflowだけは理解しておいたほうが良さそう。
　　　ワークフロー関連の問題でStep Fuctionsと対比で出ます。
　・DataStreamsとDataFirehoseの出題頻度がDASより低いです。
　・DASにあった、どのグラフが最適ですか系の問題は無かったので、
 　　復習不要です。
　・移行系の問題でDBSの知識も少しだけ問われます。
シングル構成だけどPgpool-Ⅱを構築する

# はじめに
仕事の関係で検証環境にpgpool-Ⅱを構築する必要ができた。
普通、冗長構成を持たないWeb-DBサーバであればpgpool-Ⅱ構成は不要だけど
pgpool-Ⅱの検証のためにあえて作るってことであんまし実用性はないんだけど、思い出としてメモっとく。

# 参考
このとおりにやったらすぐできた！感謝

https://qiita.com/d-ebi/items/89a683f55185c3ae5457

全体像を理解する際にこちらも参考にしました

https://qiita.com/sankaku9/items/0e293de1e51acbcb772a

# コマンドまとめ
先によく使うコマンドまとめとく

```:PGPOOL側
# ノードの確認
pcp_node_info -v -h localhost -U pgpool -w
# ノードの接続
pcp_attach_node -h localhost -U pgpool -n 0 -w
# ノードの切り離し
pcp_detach_node -h localhost -U pgpool -n 0 -w
# DBサーバへの直接接続
psql -h nbfr151v -U postgres
# pgpool経由でのDB接続
psql -p 9999 -U postgres
# pgpoolの起動
sytemctl start pgpool
# pgpoolの停止
sytemctl stop pgpool
```

```:DB側
# PostgreSQL起動
pg_ctl -D ${PGDATA} start
# PostgreSQL停止
pg_ctl -D ${PGDATA} start
```

# 主要な設定ファイルまとめ


```:PGPOOL側
# サービス定義ファイル
/usr/lib/systemd/system/pgpool.service
# サービス定義ファイルのオプションまとめ
/etc/sysconfig/pgpool
# メインとなるPGPOOLの設定ファイル
/usr/local/pgpool-II/etc/pgpool.conf
# pcpプロトコル通信するときに使用するパスワード設定
/usr/local/pgpool-II/etc/pcp.conf

## ほかにもたくさんあるけどそこんところは参考資料を見ることにする
```

```:DB側
# メインとなるPostgreSQLの設定ファイル
/home/postgres/data/postgresql.conf
```

# 構成
※nbfr151v→nbdb151vは鍵認証でのssh通信が可能な状態になっていること
| HOST名 | IPアドレス | 備考 |
|:-----------|------------:|:------------|
| nbfr151v   | 10.1.0.5 | Web(Tomcat+PGPOOL)|
| nbdb151v   | 10.1.0.7 | DB(PostgreSQL) |

***Pgpool-Ⅱ構成に必要なポート***
* 22(SSH)
* 5432(PostgreSQL)
* 9898(PCP)※pgpoolが使う独自の通信
* 9999(PGPOOL)※ユーザーがPGPOOL経由でDBにアクセスするとき使うポート
※ほかにもあるけどよく見かけるのはこれらになる

# 設定ファイル
PGPOOLの設定ファイルを載せておく。ほかの設定は参考資料のほうが参考になる。

nbfr151vにて設定。
内容精査はできてないのであくまで「この設定で動いた」っていう実績の意味で残してます。

```:/usr/local/pgpool-II/etc/pgpool.conf
[root@pgpool .ssh]# cat /usr/local/pgpool-II/etc/pgpool.conf | grep -v ^# | grep -v ^$
backend_clustering_mode = 'streaming_replication'
listen_addresses = '*'
port = 9999
pcp_listen_addresses = 'localhost'
pcp_port = 9898
pcp_socket_dir = '/tmp'

backend_hostname0 = '10.1.0.5'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/home/postgres/data'
backend_flag0 = 'ALWAYS_PRIMARY'
backend_application_name0 = '10.1.0.5'

log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/pgpool'
log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log'
log_file_mode = 0600
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 10MB

sr_check_period = 10
sr_check_user = 'pgpool'
sr_check_database = 'postgres'

delay_threshold = 0
delay_threshold_by_time = 5
prefer_lower_delay_standby = on
follow_primary_command = '/usr/local/pgpool-II/etc/follow_primary.sh %d %h %p %D %m %H %M %P %r %R'

health_check_period = 10
health_check_timeout = 20
health_check_user = 'pgpool'
health_check_database = 'postgres'
health_check_max_retries = 0
health_check_retry_delay = 1

connect_timeout = 10000
failover_command = '/usr/local/pgpool-II/etc/failover.sh %d %h %p %D %m %H %M %P %r %R %N %S'
failover_on_backend_error = on
failover_on_backend_shutdown = on

detach_false_primary = on
search_primary_node_timeout = 5min
recovery_user = 'pgpool'
recovery_1st_stage_command = 'recovery_1st_stage'
recovery_timeout = 90
client_idle_limit_in_recovery = 10
auto_failback = on
auto_failback_interval = 1min
hostname0 = ''

```
EC2にVOICEVOXをインストールしてpythonから音声ファイルを作る

## はじめに
Amazon Linux 2023にVOICEVOXをインストールしたときのメモ


## VOICEVOXのダウンロード
公式サイトからLinux版、対応モードCPU、Zip版を選択してダウンロード
落としたときのファイル名称は voicevox-linux-cpu-0.18.1.tar.gz
ファイル名称は18世代って意味だっけ

## 解凍
どこでもいいと思うけど /root直下に格納してtarで解凍する
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625818/55e3e909-cfde-77b2-9490-ff370bbe259b.png">

## 実行
Windows版もrun.exeだったし、これでしょと思って実行してみる。
<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625818/3e67fb70-948e-2b69-7c2a-ac69b9a890cf.png">

普通に動いた。最高かよ


## サービスに登録する
毎回手動実行するわけにもいかないので、サービスに登録しておく。
rootで以下コマンド実行
```
vi /etc/systemd/system/voicevox.service
```


中身は以下
```
[Unit]
Description=Voicevox Service
After=network.target

[Service]
User=root
Group=root
WorkingDirectory=/root/VOICEVOX/vv-engine
ExecStart=/root/VOICEVOX/vv-engine/run
Restart=always

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

vi 閉じたらサービス登録と起動
```
sudo systemctl enable voicevox.service
sudo systemctl start voicevox.service
```

## Pythonからwaveファイルを作る
いきなりコード
```python:voicevox.py
import requests
import json

# 指定文字を音声ファイルに保存する
# ・デフォルトはなみだめずんだもん(76)
def put_wave(text, file_path, speaker_id=76, speaking_rate=1.0):
    # 音声設定
    response = requests.post(
        'http://127.0.0.1:50021/audio_query',
        params = { 'text' : text, 'speaker' : speaker_id },
        timeout = (3, 10))   # 接続タイムアウト、全体タイムアウト？
    if response.status_code != 200 :
        return False

    # 速度変更
    speed = response.json()
    speed["speedScale"] = speaking_rate
    query = json.dumps(speed)

    # 音声データ要求
    response = requests.post(
        'http://127.0.0.1:50021/synthesis',
        params = { 'speaker' : speaker_id },
        data = query,
        timeout = (3, 10))
    if response.status_code != 200 :
        return False

    # 音声データ保存
    with open(file_path, 'wb') as fp :
        fp.write(response.content)
    return True

if __name__ == "__main__":
    put_wave("こんにちは！ずんだもんです！", 'output.wav', 1, 1.0 )
```

話す速度は変更できるようにした。タイムアウトはよく分かってない。

## 話し手IDのありか
以下jsonファイルに登録されているので、知りたいときは参照する。

VOICEVOX/vv-engine/model/metas.json
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625818/ebd3f8c2-8e6c-89c9-86b1-9782c57b993b.png)

## おわりに
1年間無料の t2.micro だからなのかけっこう動作不安定になるなぁ
スペック足りなめなのかな。
なみだめずんだもん最高におもろい！
CinemachineとInputSystemを連携する

備忘録として残しておく。

CinemachineVirtualCameraがアタッチされているゲームオブジェクトに「Cinemachine Input Provider」というコンポーネントを追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779290/57991036-4edd-b1d7-da9f-0f19942b311a.png)

[XY Axis]、[Z Axis]にInputSysytemで作成したActionを割り当てる。

以上。
DjangoでGAFAの一角担いたい

## 初心者プログラマーがDjangoはじめました。
ただの初心者プログラマーがDjangoで学んだことを適当に書いていきます！

なので、わけわからないことや間違った解釈を載せる可能性大！その時には、ぜひ正しい知識を私にご教授お願いします。怒りに満ち溢れた文章でもかまいません！

ちなみに、一緒に学んでいく本はこれです↓↓↓
著者:掌田津耶乃　タイトル:Python Django　超入門
(Amazonのリンク張っときます！)

https://www.amazon.co.jp/Python-Django-4-%E8%B6%85%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83-ebook/dp/B0CGQZCGM9?ref_=ast_author_dp&dib=eyJ2IjoiMSJ9.drNqUEmGgwg5dnidrXGZ9Nviam2byql6ap3BeZk8uGIPvm4rEfRJkfOpFMViLZHjoWf4eNYzSCDNSQbc0w7aVnUuFWSDSV3TIVGytR2IILErrVVGsf_ijf1mAk2y1F2yYbsZ3iMAeHXoT7kpRP0mR57RjYe1wfIvVi_2OoQpk2VUgj4gJ7ADTgasexg9-jWKogVD5VLrFQvEhkAM3BC9an9eF1TQtdXO-ohuzM-9o4Y.sH--c1ODjC1_XXgW4k9D5hAURmH7c7VaSfv_9XV5XYo&dib_tag=AUTHOR

(ちなみに私のもっている本は、図書館にあった初版を借りているため、結構古い情報ばっかかも...)

## Djangoってなに？
　Djangoとは、Pythonで動かすWebアプリケーションフレームワーク。フレームワークとは、アプリケーションを開発する際によく使われる機能がまとまったソフトウェアのこと。読み方は、「ジャンゴ」。私はずっと"ディ"ジャンゴって呼んでしまう。。
 
### なぜ数あるフレームワークでこれを選んだのかって？
  ーなんかPythonで動くってかっこいいからー
  たったこれだけの理由。

## Djangoのもっと詳しい説明
### Djangoの「考え方」
Djangoは。MVCアーキテクチャっていう考えに基づいてる。MVCモデルとは、プログラムを役割ごとにModel（モデル）・View（ビュー）・Controller（コントローラー）の3つに分けて管理するソフトウェア設計モデルのこと。
- Model・・・データベース(データの組織的な集合)とやり取りする部分を担当
- View・・・画面を表示する部分を担当
- Controller・・・全体の制御を担当

みたいな感じ！

## Djangoについて少しだけ知れた。
これからは、Django の環境構築や作り方を本を参考にして勉強して記事に乗せていきます！
StampS3の内蔵シリアル(USB)で遊ぶ。


参考

↓クリック↓

https://qiita.com/Ninagawa123/items/5fae80c3050a20dcf03a



x 注意事項があります。

目的
なぜか、いろいろ上手く行かないのでまとめた。

StampS3の設定は、全てデフォルト

![o_coq068.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/11cbabfa-9ba3-3eec-dcce-9fe7711b08be.jpeg)

```c++


//USBSerial_test1_M5S3

void setup() {
  USBSerial.begin(115200);
  USBSerial.setDebugOutput(true);  
}

void loop() {
  USBSerial.println("Start as I2C 0x");
  delay(1000);
}


```


いつたん、USBを抜いて、また、USBを挿す。

結果は、


![o_coq067.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a3756b4c-a48a-ffed-e465-72189bcd9297.jpeg)


注意、注意、注意、注意、注意、注意、注意、注意、注意、注意、

なぜか? 「書き込めなくなる」

そんな時は、「BTN0」を押しながら接続する。
本当にあった検索アンチパターン

検索機能を実装する際に出会ったアンチパターンをご紹介します。

## 1. 検索フォームが POST メソッド

```html
<form method="POST" action="https://example.com/search">
    <!-- ... -->
    <button type="submit">検索</button>
</form>
```

通常、検索機能は「読み取り」操作であり、GETメソッドの使用が推奨されます。
GET メソッドを使うと以下の利点があります。

- ブックマーク可能: `GET` リクエストはURLにクエリパラメータを含められるので、ブックマークやリンクの共有が容易になる
- キャッシュ可能: ブラウザやサーバーが `GET` リクエストの結果をキャッシュでき、パフォーマンス向上が期待できる

## 2. 検索条件をセッションに入れて、リダイレクトして検索結果画面を表示

```php
    public function search(Request $request): RedirectResponse
    {
        $request->session()->put('search.query', $request->all());

        return redirect()->route('result');
    }

    public function result(Request $request): View
    {
        $query = $request->session()->get('search.query');
        $result = xxx; // 検索処理

        return view('result', $result);
    }
```

1で `POST` しているからか検索結果画面をリダイレクトして表示していました。
検索条件をセッションに入れて、検索結果画面を表示する際にセッションから検索条件を取り出し、実際にデータベースへアクセスしていました。

- 別タブで検索すると検索条件が上書きされる
- セッションからの値の出し入れがめんどくさい

## 3. 一意にならないソートキーが指定されている

ORDER BY句に `投稿日` カラムがキーに指定されていました。
ただ、検証環境に同じ日時の `投稿日` データが大量に入っていました。

ページャー機能により2ページ目、3ページ目を表示するも1ページ目で表示したアイテムが再度表示されてしまう

## まとめ

検索機能を実装するときは `GET` メソッドを使おう

今日はこちらのイベントに参加しました。

https://phper-tea-night.connpass.com/event/314048/

この時の自己紹介で「今まで作った検索機能の思い出」を語ることになり、思い出を思い出したついでに記事として供養したいと思います。
CorneCherryのキーマップを表示させるアプリ作ったヨ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71846/94732a1a-6d94-3cc7-c681-aaab931caf84.png)
初めましての方は初めまして、そうでない方も始めまして。
この記事は自作分割キーボード[Corne Cherry](https://shop.yushakobo.jp/products/corne-cherry-v3)を使用している方、
もしくは購入を考えている方に向けに書いています。
このアプリがレイヤーを覚えるまでの助けになってくれるはず(´・ω・｀)

## アプリを作った理由
[Corne Cherry](https://shop.yushakobo.jp/products/corne-cherry-v3)は通常のキーボードの**40%程度**のキーのみで構成されています。
なので**QWERTYUIOP**から上の数字キーやファンクションキーなどが物理的に存在しません。
![CorneCherryV3](https://shop.yushakobo.jp/cdn/shop/products/cornecherryv3_1_700x.jpg)

その点を**レイヤーキー**を用いて、一つのキーに複数の役割を持たせることで数字キーやファンクションキーなどをタイプすることが可能となっています。
利点はホームポジションから全く手を動かさずにすべてのキーにアクセス出来る点や、分割キーボードなので腕を開いてリラックスした状態でタイピングが出来る所ですが、如何せん**レイヤーを覚えるのが難しそう**と思ったのがこのアプリを作る切っ掛けでした。

## 何ができるの?
すでに起動しているアプリの上に任意のキーマップを表示させることができます。
画面の透過度やキーマップ、画面のサイズ、表示するフォントなどが変更できます。
👇はVSCodeにかぶせた例です。
![スクリーンショット 2024-04-26 214404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71846/610db77e-9cd7-9e73-25f8-9191af8c4b6d.png)

## 導入

https://github.com/Lacty/CorneOverlay

👆画面右の[Release](https://github.com/Lacty/CorneOverlay/releases)から``CorneOverlayApp.zip``をダウンロードしてください。
解凍した中の``CorneOverlay``が本体です。
``config.json``にて画面サイズやキーマップ、フォントの指定などを書き込んでください
```yml
{
    "window" : {              # 画面
        "width" : 400,        # 画面サイズ横
        "height" : 100,       # 画面サイズ縦
        "alpha" : 0.7,        # 画面透過度
        "allwaysTop" : true   # 常に表示 falseを指定すれば他のアプリ同様下に潜ります
    },
    "keymap" : {              # キーマップ
        "top" : [ "Tab"  , "!", "@", "#", "$", "%", "^", "&", "*", "(",  ")", "BS" ],
        "mid" : [ "Ctrl" ,  "",  "",  "",  "",  "", "-", "=", "[", "]", "\\", "`" ],
        "bot" : [ "Shift",  "",  "",  "",  "",  "", "_", "+", "{", "}",  "|", "~" ]
    },
    "font" : {                # フォント
        "name" : "Segoe UI",  # フォント名
        "weight" : "normal",  # フォントの太さ "Bold"など
        "size" : 10           # フォントサイズ
    }
}
```

## さいごに(´・ω:;.:...
需要が分からなかったので完璧じゃない状態でのリリースとなります。
（自分が使えれば良いやの精神
本当はレイヤーキーを押したときだけ表示させたかったけど、HIDとしてデバイス接続はできても、キー入力の受け取り方が分からなくて断念。
タイトルバーが邪魔だけど消しちゃうと移動処理も書かないといけないので面倒で未実装。
その他見た目が質素...etc
**Githubの🌟押してくれると頑張れるかもしれません(｀・ω・´)**

ここまで読んでくれて有難うございます。
一緒に自作キーボードライフ楽しみましょう！
grpc-go resolverのメモ

grpc-go(https://github.com/grpc/grpc-go) resolverのメモ

確認したバージョン
  - go 1.22
  - google.golang.org/grpc v1.63.2

### resolverとは
- gRPCのresolverはクライアントがサーバー発見するために使用されるコンポーネント
  サービス名を実際のネットワークアドレス（IP アドレスとポート）に解決する役割を担っている

### ライブラリから提供されるresolver
- ライブラリ(grpc-go)から[dns](https://github.com/grpc/grpc-go/blob/v1.63.2/internal/resolver/dns/dns_resolver.go), [passthrough](https://github.com/grpc/grpc-go/blob/v1.63.2/internal/resolver/passthrough/passthrough.go), [unix, unix-abstract](https://github.com/grpc/grpc-go/blob/v1.63.2/internal/resolver/unix/unix.go)の4種類のresolverが提供されている
- どのresolverを使うかはgrpc.ClientConnを生成する[grpc.NewClient](https://pkg.go.dev/google.golang.org/grpc#NewClient)と[grpc.DialContext](https://pkg.go.dev/google.golang.org/grpc#DialContext)のtarget引数に渡すURL schemaで判定される
DNS resolverを使用したい場合は`dns://server.grpc.demo`
- schemaを指定しない場合...
    - grpc.ClientConnをgrpc.NewClientで生成すると、デフォルトでschema "dns"として扱われる
    - grpc.ClientConnをgrpc.DialContextで生成すると、デフォルトschema "passthrough"として扱われる
- デフォルトのschemaを変更したい際はgrpc.ClientConn生成前に↓のように設定しておく必要がある
    ```go:Go
    resolver.SetDefaultScheme("passthrough")
    ```

#### DNS resolver
- DNS resolverでもgrpc.DialOptionで↓のようにload balancingを設定することで、DNSから返ってきた複数IPアドレスをload balancingすることができる
    ```go:Go
    grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`)
    ```

### custom resolver    
- 自前のresolverを登録できる
- 例えばAWS Cloud Mapを使用したい場合は[aws-cloudmap-grpc-name-resolver](https://github.com/aws-samples/aws-cloudmap-grpc-name-resolver/blob/main/client/resolver.go)のようなコードが参考になる
  - この場合はDNS名前解決ではなく、Cloud Mapの機能でサーバー発見する
  - つまりCloud Mapのインスタンスの検出設定に"DNSクエリ"は不要で、"API呼び出し"のみがあれば良い

### resolverの挙動
- [resolver.ResolverのResolveNowメソッド](https://github.com/grpc/grpc-go/blob/1e8b9b7fc655b756544cf10fded8f0d2fa3226e8/resolver/resolver.go#L319)はgRPCコネクションが切れたタイミングなどで呼ばれる
- サーバーのインスタンスやpodが増えた際はResolveNowは呼ばれない
つまりスケールアウトしたインスタンスにはリクエストされず、適切にload balancingされない
- 対応方法の1つとしてサーバー側で↓のように[keepalive.ServerParameters.MaxConnectionAge](https://pkg.go.dev/google.golang.org/grpc/keepalive#ServerParameters)を設定する
    ```go:Go
    s := grpc.NewServer(grpc.KeepaliveParams(keepalive.ServerParameters{
    	MaxConnectionAge:      10 * time.Minute,
    	MaxConnectionAgeGrace: 30 * time.Second,
    }))
    ```
    [関連issue](https://github.com/grpc/grpc/issues/12295)を見てもこの方法が推奨されてる模様
manコマンドにfishシェルで色をつける

`man`コマンドが白黒で醜いことが多々あると思います。
下記のコマンドを`~/.config/fish/config.fish`に追加するとmanで色のついたマニュアルを表示できます。
ぜひお試しください。
```bash
set -x LESS_TERMCAP_mb (printf "\033[01;31m")  
set -x LESS_TERMCAP_md (printf "\033[01;31m")  
set -x LESS_TERMCAP_me (printf "\033[0m")  
set -x LESS_TERMCAP_se (printf "\033[0m")  
set -x LESS_TERMCAP_so (printf "\033[01;44;33m")  
set -x LESS_TERMCAP_ue (printf "\033[0m")  
set -x LESS_TERMCAP_us (printf "\033[01;32m")
```
クラウドリソースをTerraform管理から外したり戻したりする手順

最近、ECS on FargateとELB(ALB)を新しく構築しました。基本的にリソースはTerraformでコード管理しているのですが、ECSのタスク定義とサービスについてはデプロイごとに更新が必要(ライフサイクルが短い)なので、[ecspresso](https://github.com/kayac/ecspresso)というOSSで管理しています。

ELBについては一度構築すれば滅多に更新されることはないと思っていたのですが、今回Blue/Greenデプロイを導入したら、リスナールールのターゲットグループがデプロイごとに変わることがわかりました。これだとTerraformの構成ファイルと実際のリソースで差分が出てしまい、他のリソースを作成・更新する際にその差分が乗っかってきてしまいます。

この問題を解決するために、まずは「ターゲットグループを動的に読み込む」といった方法が思い浮かんだのですが、Terraformの構成が複雑になりそうな気がしたので、更新頻度が高いリソースに対しては、「リスナールールをTerraformの管理から一時的に外し、必要に応じて管理下に戻す」という方法を選びました。

# Terraform管理からリソースを外す手順
`modules/elb/main.tf`で以下のリスナールールを管理しているとします。

```tf
resource "aws_lb_listener_rule" "blue" {
  listener_arn = aws_lb_listener.https_443.arn
  priority     = 100

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target_blue.arn
  }

  condition {
    host_header {
      values = ["dev.example.jp"]
    }
  }
}
```
`terraform apply`を行っているディレクトリで以下のコマンドを実行すると、Terraformのステートファイルからこのリスナールールが削除されます。

```
$ terraform state rm module.elb.aws_lb_listener_rule.blue
```

最後にリスナールールをコメントアウトするか削除することで、次回の`terraform apply`にリスナールールの変更が影響されなくなります。

# Terraform管理下にリソースを戻す方法
リスナーのARNをコンソールから確認して、AWS CLIでリスナールールのARNを特定します。

```bash
$ aws elbv2 describe-rules --listener-arn [リスナーのARN]
```
以下のように出力されるので、　`RuleArn`をコピーします。

```
{
    "Rules": [
        {
            "RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:********:listener-rule/app/example-alb/********/********/********",
            "Priority": "100",
            "Conditions": [
                {
                    "Field": "host-header",
                    "Values": [
                        "dev.example.jp"
                    ],
                    "HostHeaderConfig": {
                        "Values": [
                            "dev.example.jp"
                        ]
                    }
                }
            ],
```
以下のコマンドでリソースをTerraformの管理下に戻すことができます。

```bash
$ terraform import module.elb.aws_lb_listener_rule.blue　[リスナールールのARN]
```

# おわりに
今回みたいな頻繁に更新されるリソースの管理をみなさんがどうされているのかしりたい..
Windows11にて拡張子とアイコンとプログラムを関連付ける

プログラムを作成し、複数の独自の拡張子を使えるようにしました。ところがそれぞれの拡張子とアイコンの連携がうまくいかず試行錯誤しましたが、最終的にうまくいきましたので備忘録として残しておきます。

拡張子 .aaa と .bbb 
プログラムのパスはC:\Program Files\XXX\YYY.exe 
拡張子 .aaa用のアイコンはC:\Program Files\XXX\aaa.ico、インデックスは0
同じく.bbb用のアイコンはC:\Program Files\XXX\bbb.ico、インデックスは0
プログラムの名称は、MyAppとします。

最終的に動いたレジストリは次のとおりです。すべて文字列なのでTypeは省略します

HKEY_CLASS_ROOT
　├ .aaa　　　(Default)　MyApp.AssocFile.AAA
　├ .bbb　　　(Default)　MyApp.AssocFile.BBB
　├ MyApp.AssocFile.AAA
　│　├ DefaultIcon　(Default)　C:\Program Files\XXX\aaa.ico,0
　│　└ shell
　│　　　└ open
　│　　　　└ command　(Default)　C:\Program Files\XXX\YYY.exe "%1"
　├ MyApp.AssocFile.BBB
　│　├ DefaultIcon　(Default)　C:\Program Files\XXX\bbb.ico,0
　│　└ shell
　│　　　└ open
　│　　　　└ command　(Default)　C:\Program Files\XXX\YYY.exe "%1"

 ※ ”AsscocFile”という記載はMediaPlayerのレジストリ記載を真似ただけでこうでなくてはいけないということではないようです。拡張子の(Default)の値に登録した名称と同じになれば良いと思われます
※ 登録後、Explorerを再起動したら反映されました
[1.20.1]黄昏の森で日本語化が正常に行えない不具合の修正

## 日本語にならない！


公式で日本語に対応しているはずが、
最新のmodファイル(`ver4.3.2145`)ではうまく日本語化できていない

検索しても情報が全く出てこないので、
気合で原因と解決方法を見つけた


## 原因
modファイル内に日本語化データは存在するが、
記述ミスにより読み込まれていない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/9e180c63-2655-99bb-1e2a-5ec3beb6f910.png)

`ja_jp.json`の1007行目、カンマがないです。
ここを修正するだけで正常に読み込まれます。

## 解決方法

#### 7zipなどの解凍ソフトで黄昏の森.jarを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/8e4962c0-17e0-86e1-1278-92f73c1bab1e.png)

#### `assets\twilightforest\lang`に移動する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/45da7695-b453-dd44-3f04-f5812cdf3def.png)

#### `ja_jp.lang`を開く

windowsに標準で搭載されているメモ帳やワードパッドでも大丈夫だと思いますが、
私はVScodeで開いています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/f719d375-3b1c-5673-5df3-7df66be1e6c3.png)

#### 1007行目の最後にカンマを追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/378e0962-4a76-a5a8-02cf-83046ac64d50.png)

#### ctrl+sで保存して完了

編集したjarファイルをmodsフォルダに移動してminecraftを再起動すれば日本語になっているはずです。


## おわり

![runtim Screenshot 2024.04.26 - 20.41.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/0848bf38-86f4-828f-55b9-3805e26f8adc.png)

そういえばこれ書きながら公式フォーラムのissue読んでなかったなと思いました。

おしまい
YOLOで追跡してみる

ようやく花粉症のピークも過ぎたでしょうか。連休明けまで気が抜けない方もいらっしゃるかと思います。最近は黄砂も影響するでしょうか。花粉や黄砂の密度の薄いところで暮したいものです。という訳でもないのですが、今回は物体の追跡です。

# 物体の追跡とは
ある画像の中で注目したい物体の位置を特定するのは、物体検知など定番の技術です。
次に動画を考えたときに、次のフレームでも同じことをして、さらに前のフレームと検知したものが同一か判断することが求められます。

# 使うだけならそれほど困らない
追跡機能を持つYOLOを試してみることにしました。ずいぶん昔に試したころは物体検出までしかできない時代だったのですが、しばらく見ていない間にずいぶん進化しています。同時に使い勝手も良くなったようです。

https://docs.ultralytics.com/ja/modes/track/

ソースは[こちら](https://github.com/ishikawakouji/yolov8track/tree/main)
この中の `track_video_write.py`が目的のものになります。あとは、書きちらかしたものなので、気にしないでください。

# 今回のポイント
動画は自前で用意してもいいのですが、準備するのも大変ですよね。ということで、YouTubeを利用したいと考えました。探してみると同じことを考えている人は多く参考にさせてもらいました。

https://qiita.com/suo-takefumi/items/4c63399e39edecdcf323

動画のソースはこのあたりで使い分けます。とりあえずは、自前の動画ファイルを利用するようにしていますが、YouTubeを利用したい場合は適宜コメントアウトの位置を変更してください。
```python
# Open youtube
#video_url = "https://youtu.be/xxxx"
#video = pafy.new(video_url)
#best = video.getbest(preftype="mp4")

# Open Video
video_path = "video1.mov"

#open
#cap = cv2.VideoCapture(best.url) # or video_path
cap = cv2.VideoCapture(video_path) # or video_path
```

こんな感じで動きます、とサンプルとか載せたいところですが、著作権とかあるし、自前のはいろいろ恥しいので、ぜひお手元の動画で試してみてください。

# おわりに
YOLOを見るまではちょっと大変かもなと思っていたんですが、ほぼサンプル通りで労せずできることがわかりましたので、忘れないように自分のメモです。
ssh鍵を使ってsshログインできるようにする

# はじめに
長らくハマってたssh鍵作成～sshログインまでの流れがようやく理解＆成功したので
メモっとく。

# 参考
元々は↓↓の記事作ってた。でもこのやり方は、接続先サーバのauthorized_keysに公開鍵をコピペで張り付けるっていう力技。
よそのサイトで紹介してるssh-copy-idを使ってのスマートなやり方がわからなかったための苦肉の策でした。

https://qiita.com/watyanabe164/items/c206a118a6aff91d0c21

# 先に結論
クライアント側からssh-copy-idを使ってサーバ側へ公開鍵を渡すためには、前提として ***「そのユーザーはそもそもクライアント～サーバ間でパスワード認証でssh接続できること」*** が必須。

今までずっと「鍵を渡すためにはssh通信できないといけないのにどうやってほかの人はssh鍵を渡しているんだ…」とおもってたけど、
わかってしまえば何のことはない話だった。。。

あと、ssh接続時に使うユーザー名はクライアント側とサーバ側でそろえておいたらいいです。
そろってなくてもできる気もするけど検証する気が起きないのでそこは割愛。

↓↓のサイトのおかげでようやく結論にたどり着けた。。。感謝

https://maku.blog/p/2mzbmw8/

# 改めて手順の説明
### 構成

| HOST名 | IPアドレス | 使用するユーザー名 | 備考 |
|:-----------|------------:|:------------|:------------|
| nbfr151v   | 10.1.0.5 | nabehiro | クライアント|
| nbfr152v   | 10.1.0.6 | nabehiro | サーバ |

## 1. パスワード認証設定にする（サーバ / root）

/etc/ssh/sshd_configを確認して、以下のようにパスワード認証を有効にする

```:/etc/ssh/sshd_config
#PasswordAuthentication yes
PasswordAuthentication no
```

sshdを再起動。これやってもssh接続が切れることは無いので安心してください。

```
systemctl restart sshd
```

https://qiita.com/jinnai73/items/f41fa6df6998d47d1f33


## 2. ssh鍵を作成する（両方 / nabehiro）
新規でユーザーをつくったケースを想定しているので.sshは新規で作る
受け入れ側も.sshないと公開鍵を受け取る場所がないのでサーバ側にも作った

```
$ mkdir ~/.ssh && chmod 700 ~/.ssh
$ cd ~/.ssh
$ ssh-keygen -t rsa -b 4096
```

実行後の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/b87213ca-10c0-dbbf-fc4d-6a1c0fa33e13.png)

実行後の.ssh/
秘密鍵（id_rsa）と公開鍵（id_rsa.pub）が作られる。
名前指定してないとid_rsaって名前になる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/bef420e6-27da-d5dc-2616-d20556f28aa7.png)


## 3. パスワード認証で接続（クライアント / nabehiro）
ここが前半のクライマックス。
パスワード認証できれば次の認証鍵でのパスワード不要な認証へチャレンジできる。
秘密鍵がデフォルトの場所ならサーバとログインアカウントの指定だけでOK。

```
ssh nabehiro@10.1.0.6
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/73b57fd0-4ace-2fa0-b2e2-39d7b8722543.png)

## 4. 公開鍵の転送（クライアント / nabehiro）
ssh-copy-idを使って転送する

```
## dry-runで確認
ssh-copy-id -n nabehiro@10.1.0.6

## -nを外して実行
ssh-copy-id nabehiro@10.1.0.6

```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/2dfcf4ae-f294-3549-5d2b-b089940e0f56.png)


なお、ssh-copy-idに成功すると↓↓のようにauthorized_keysが作成され、そこに公開鍵がコピーされる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/b3e451c4-cac9-b1c4-a130-dcca86ac9455.png)

## 5.鍵認証を使ってログイン（クライアント / nabehiro）
ログインコマンドはこちら。-iは鍵ファイル名を指定する

```
ssh -i id_rsa nabehiro@10.1.0.6
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/c2f0e340-9f5f-578a-1e87-d156c0a35fb2.png)

ちなみに、試しでid_rsaを複製して.ssh/id_rsa2を使ってログインしようとしたら-i ~/.ssh/id_rsaと指定しないとダメだった。
id_rsaだけが特別なんだなと思いました。


# オマケ：サンプルユーザーの作り方
また同じ要領でハマったときにつるっと検証できるようにユーザー追加コマンドを置いておく
検証用の使い捨てユーザーなのでBAD PASSWORDと叱られても気にしないのがコツ。

```
useradd -m -d /home/nabehiro nabehiro
passwd nabehiro
nabehiro
nabehiro

# 削除したいときはuserdel。-r使ってホームディレクトリごと消す
userdel -r nabehiro
```

作成時の結果はこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/b9b7254d-a080-f1fe-bb99-dec6b2f69e35.png)
時計で遊ぶ。(シリアル出力)(StampS3)


注意あり　参考

↓クリック↓


https://qiita.com/caa45040/items/b118ba99efc2765d8b1d


目的
DS1307のテスト


注意、注意、注意、

書き込んだ後に、USBを抜いて、USBを挿す。
再書き込み時には、「BTN0」ボタンを押してUSBに挿す。


結果

![o_coq069.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3c2922fd-1663-508d-2c88-84b178d2413b.jpeg)



プログラム


```c++


//I2C_DS1307_M5S3_1


//インクルド
#include <Arduino.h>
#include <Wire.h>   //I2C


//定義
// デバイスアドレス(スレーブ)
#define ADDR    0x68    // 2進数 1101000


//初期化
void setup()
{

  //シリアルの初期化処理
  USBSerial.begin(115200);
  USBSerial.setDebugOutput(true);
    
  //i2cの初期化処理
  Wire.begin(); // 13 15 M5S3

} //setup


//メインループ
void loop()
{

  // レジスタのアドレスを先頭にする
  Wire.beginTransmission(ADDR);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(1);

  // I2Cスレーブに8byteのレジスタデータを要求する
  Wire.requestFrom(ADDR, 8);

  // 8byteのデータを取得する
  char data_read[16] = {0x88, 0x88, 0x88}; //データバッファー
  int ii = 0;
  while (Wire.available())  {   // 要求より短いデータが来る可能性あり
    data_read[ii++] = Wire.read();       // 1バイトを受信
  }//while
  delay(1);

  //表示変換する パック二進化十進を文字列にする
  char cn1[16];  //桁
  cn1[0] = '0' + (data_read[2] >> 4);  //0 時 上位
  cn1[1] = '0' + (data_read[2] & 0xf); //1 時 下位
  cn1[2] = ':';
  cn1[3] = '0' + (data_read[1] >> 4);  //2 分 上位
  cn1[4] = '0' + (data_read[1] & 0xf); //3 分 下位
  cn1[5] = ':';
  cn1[6] = '0' + (data_read[0] >> 4);  //4 秒 上位
  cn1[7] = '0' + (data_read[0] & 0xf); //5 秒 下位
  cn1[8] = 0;

  USBSerial.println(cn1); //時刻を表示する

  delay(1000); //1秒待つ

} //loop



```
【備忘録】IP5306 i2c回路図とレジスタ

# IP5306 i2c回路図

[IP5306 automatic standby - M5Stack Community (https://community.m5stack.com/topic/62/ip5306-automatic-standby3)](https://community.m5stack.com/topic/62/ip5306-automatic-standby)

↑こちらにあった[回路図](https://community.m5stack.com/assets/uploads/files/1515402963959-97994060-2969-49dc-ad9c-7b3887d95a17-image.png)を参考にした。


5V駆動のため、ESP32などの3.3V MCUに接続する場は、i2c信号のレベル変換が必要。

![ip5306_circuit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/f0560107-0ba0-cb86-0e98-c3d36a96980d.png)


# IP5306レジスタ

[M5Stackの充電制御IC IP5306のネット上に分散していたレジスタ情報をまとめる(https://zenn.dev/tomorrow56/articles/43f64daa279510)](https://zenn.dev/tomorrow56/articles/43f64daa279510)

↑上記サイトの情報をリンク

# SYS_CTL0 (0x00)

![](https://storage.googleapis.com/zenn-user-upload/4f654759c6e55fba0e9352e1.png)

# SYS_CTL1 (0x01)

![](https://storage.googleapis.com/zenn-user-upload/c94948c889aa2be4d38bd0c6.png)

# SYS_CTL2 (0x02)

![](https://storage.googleapis.com/zenn-user-upload/5f5592f50929a22aa8190b9c.png)

# Charge_CTL0 (0x20)

![](https://storage.googleapis.com/zenn-user-upload/8e25c4fd3336da571c31acdd.png)

# Charge_CTL1 (0x21)

![](https://storage.googleapis.com/zenn-user-upload/452406f7b4b8173375691e5e.png)

# Charge_CTL2 (0x22)

![](https://storage.googleapis.com/zenn-user-upload/cc9cd82f908486e5a993a362.png)

# Charge_CTL3 (0x23)

![](https://storage.googleapis.com/zenn-user-upload/e6476599fa2cd136cfbf2cea.png)

# CHG_DIG_CTL0 (0x24)

![](https://storage.googleapis.com/zenn-user-upload/0211428c20be247f268a1c3e.png)

# REG_READ0 (0x70)

![](https://storage.googleapis.com/zenn-user-upload/78e8896a0a4c89e1cc9a292d.png)

# REG_READ1 (0x71)

![](https://storage.googleapis.com/zenn-user-upload/2f710516bfd3e4942d98e897.png)

# REG_READ2 (0x72)

![](https://storage.googleapis.com/zenn-user-upload/0f8844fe81a6e2b7ac7fb62f.png)

# REG_READ3 (0x77)

![](https://storage.googleapis.com/zenn-user-upload/45587ff3696496ec68e76e08.png)


# REG_READ4 (0x78)

![](https://storage.googleapis.com/zenn-user-upload/e19b37a61547ca7ec1ec52de.png)

# サンプルプログラム

出来次第アップします。

**以上**