OmniAICreator/Qiita-1.07M huggingface dataset:
Arduino IDE + ESP-01 単体 Wi-Fi Clock

## 概要
* ESP-01 単体で Wi-Fi Clock を作成
* USBケーブルを刺したままプログラムが書き込める USB-ESP8266 アダプタモジュールを使用

![IMG_20250221_185604406.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670759/4827e172-234b-46c1-ab48-48805affaa2a.jpeg)

![ESP8266 USB アダプタ モジュール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670759/a856a43e-72de-4818-af55-03a7a87b6c43.jpeg)

## ソフトウエア資材
* Arduino IDE ESP8266 on Windows 11
## ハードウエア資材
* ESP-01S
* SSD1306(OLED)
* USB-ESP8266アダプタモジュール
## プログラム
```C:ESP-01Clock.ino
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <time.h>

#define WIFI_SSID   "Your SSID"
#define WIFI_PASSWORD "Your Password"

#define TIMEZONE_JPN  (3600 * 9)  // JST is UTC+9hours
#define DAYLIGHTOFFSET_JPN  (0)   // No summer time
#define NTP_SERVER1   "ntp.nict.jp"  // NTP

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void displayDateTime() {
  char bufTime[32], bufDate[32];
  time_t Now = time(NULL);
  struct tm* tm = localtime(&Now);
  strftime(bufTime, sizeof(bufTime), "%T", tm);  
  strftime(bufDate, sizeof(bufDate), "%a %b %d %Y", tm);  
  Serial.printf("%s %s\n", bufTime, bufDate); // Debug
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 0);
  display.println(bufTime);
  display.setTextSize(1);
  display.setCursor(0, 20);
  display.println(bufDate);
  display.display();
}

void setup() {
  Serial.begin(9600); // Serial for debug
  delay(5000);

  Wire.begin(0, 2);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) delay(500);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.println("Initializing");
  display.display();

  configTime(TIMEZONE_JPN, DAYLIGHTOFFSET_JPN, NTP_SERVER1);
}

void loop() {
  displayDateTime();
  delay(1000);
}
```
## まとめ
最も小さなシングルボードコンピュータで WiFi 時計が作れました。
ESP-01 は、なかなか良いですね。
GitHubで初めてのブランチ作成とプルリク！初心者が学んだこと

# GitHubで初めてのブランチ作成とプルリク！初心者が学んだこと

## **はじめに**

GitHubを使ってチーム開発をする際、ブランチを作成し、プルリクエスト（PR）を送ることは必須の流れ。しかし、初心者にとってはこのプロセスが難しく感じることも。

この記事では、**「ブランチとは？」「PRとは？」という基礎知識** から、 **「実際の操作方法」** まで詳しく解説する。Gitを学び始めたばかりの人でも安心して使えるようになるはず！

---

## **そもそもGitとは？GitHubとは？**

### **Gitとは？**
Gitは「バージョン管理システム」の一つで、**ソースコードの変更履歴を記録するためのツール** です。

例えば、ドキュメントの編集履歴を保存する「Googleドキュメントの変更履歴機能」に近いイメージ。ただし、Gitは **複数人での開発** に適した仕組みになっていて、**「誰が」「いつ」「どこを」修正したか** を簡単に管理できます。

### **GitHubとは？**
GitHubは、**Gitをオンラインで使えるようにしたサービス** です。

- Gitを使ってコードを管理できる
- チームで共同開発しやすい
- 変更の履歴を記録・管理できる

GitHubを使うことで、複数人での開発やコードレビューがスムーズになります。

---

## **ブランチとは？**

ブランチとは、**メインのコードを維持したまま、新しい変更を加えられる作業領域** のこと。

例えば、
- `main` ブランチ（本番環境にあるメインのコード）
- `feature/button-fix`（ボタンの修正作業用のブランチ）

のように分けることで、**メインのコードに影響を与えずに修正ができる**。

✅ **なぜブランチを使うのか？**
- メインのコードを壊さずに新しい機能を開発できる。
- 修正内容を後からまとめて確認できる。
- PRを使って、他の人と共有・レビューしやすくなる。

---

## **ブランチを作成する方法**

ブランチを作成し、そこに変更を加えていきます。

### **ブランチの作成手順**
```bash
git checkout -b feature/button-width-fix
```

**`feature/button-width-fix` という新しいブランチを作成し、そこに移動する** コマンドです。

---

## **変更をコミットする**

ブランチを作ったら、次に変更を加え、保存（コミット）します。

```bash
git add .
git commit -m "ボタン幅を修正"
```

✅ **ポイント:**
- `git add .` は「変更を記録する準備（ステージング）」をする。
- `git commit -m "コメント"` で変更を確定させる。
- コミットメッセージは、**どんな変更を加えたのか分かりやすく書く**。

---

## **リモートリポジトリにプッシュする**

作業が完了したら、変更をGitHubにアップロードします。

```bash
git push origin feature/button-width-fix
```

もし、エラー `fatal: The current branch has no upstream branch.` が出た場合は、以下のコマンドを使います。

```bash
git push --set-upstream origin feature/button-width-fix
```

---

## **プルリクエスト（PR）とは？**

PR（プルリクエスト）とは、**「この修正をメインのコードに取り込んでください！」と依頼するための仕組み** です。

GitHubでは、PRを作成することで **「この修正で問題ないかチェックしてもらう」** ことができます。

✅ **PRを使うメリット**
- 変更内容を他の人にレビューしてもらえる。
- コードに問題がないかチェックできる。
- メインのコードを安全に保てる。

---

## **プルリクエスト（PR）を作成する方法**

GitHubのリポジトリにアクセスし、「Pull Requests」タブから「New Pull Request」を選択。

### **PR作成時のポイント**
- **何を修正したのか明記する**
- **なぜこの修正が必要なのか説明する**
- **スクリーンショットやコードの変更点を載せると親切**

---

## **まとめ**

GitHubでのブランチ運用とPRの流れを学ぶことで、チーム開発にスムーズに参加できるようになります。

✅ **ブランチを作成して、変更を安全に管理する**
✅ **PRを通じてレビューを受けることで、より良いコードを書く**
✅ **エラーが出ても慌てずに調べながら対応する**

初心者でも、これらの流れを押さえれば自信を持って開発に取り組める！
ロゴ

![DALL·E 2025-02-25 00.06.27 - A professional and modern logo for a system named 'CHOICE' that manages ID applications and contract signing. The logo should prominently feature the .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/b530a64e-1668-46b7-8366-7d3a1283db17.png)
![DALL·E 2025-02-25 00.06.30 - A monochrome professional and modern logo for a system named 'CHOICE' that manages ID applications and contract signing. The logo should prominently f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/a0aa4f30-6565-411c-ad03-8fa9ff8b8af4.png)
![案1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/76c3d949-812c-43e7-adf2-dd6138916281.png)
![案２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522228/d5f73b72-0126-4123-aabf-bc61866af411.png)
Filemaker ExecuteSQL用のSQL文作成を補助するカスタム関数

FilemakerのSQL文はフィールドをダブルクォーテーションで囲んだり面倒な上に､テーブル名やフィールド名を変更しても連動しないために忘れずに変更しないといけない｡

ということで､そこを少しだけ補助するカスタム関数｡

## テーブル名､フィールド名をクォーティション付きに変換する

### カスタム関数: SQL用テーブル名
```
Let (
	fn = GetFieldName ( field );
	"\"" & GetValue ( Substitute ( fn; "::"; "¶" ); 1 ) & "\""
)
```
### カスタム関数: SQLフィールド名
```
Let (
	fn = GetFieldName ( field );
	"\"" & Substitute ( fn; "::"; "\".\"" ) & "\""
)
```

## 使用方法
カスタム関数を使用しない通常の書き方の例
```
Let ( [
	%sql = "
		select
			\"field1\",
			\"field2\"
		from
			\"tableA\"
		where
			\"key\" = ?
		";
	%rows = ExecuteSQL ( %sql; ""; ""; "keyword" );
%=0];
	%rows
)
```
カスタム関数を使用した場合
```
Let ( [
	%sql = "
		select
			" & SQL用フィールド名 ( tableA::field1 ) & ",
			" & SQL用フィールド名 ( tableA::field2 ) & "
		from
			" & SQL用テーブル名 ( table::PK ) & "
		where
			" & SQL用フィールド名 ( table::key ) & " = ?
		";
	%rows = ExecuteSQL ( %sql; ""; ""; "key1" );
%=0];
	%rows
)
```
カスタム関数内で`GetFieldName`によりテーブル名やフィールド名の置き換えが行なわれるので､テーブル定義で名称を変更しても連動して動く｡
また､計算式を作成する際にFilemakerのコード支援が効くので､SQL文を作るのが少し楽です｡
統計検定1級　2024　統計応用(理工学)　問1　解説

［4］は一部ギブアップです。
![img20250218_11493678.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/c20a6e2a-49c3-4a43-b802-4e59a0fa7d2b.jpeg)
![img20250221_13465763.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/d2d82ece-b493-4bd3-8b1a-aa6ad0e51689.jpeg)
NFC 名刺に書き込みをする  NT3H2111版



「STEP to STEP テキスト： JLCPCB で NFC 名刺を PCBA」
https://qiita.com/nanbuwks/items/83ca803efb51f5b11f91

で作った名刺に、自分の情報を書き込んでスマホをかざすと名刺情報を出せるようにします。


# 作った名刺

![IMG_20250217_113011.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/434a9519-b850-404f-b13b-859df1dc7620.jpeg)



![IMG_20250217_113039.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/11aea550-b4dd-468a-8bb0-567b4320ab0f.jpeg)


# Android スマホで書き込み

NXPのアプリを使います。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e88a0ca9-628f-45ee-b7bf-c95ad9ea17d3.png)


https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter&hl=en&gl=US

起動したところです。

![Screenshot_2025-02-17-11-48-46-423_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1e7aa9f0-26d4-45e6-acb5-0c5035f87dce.jpeg)


# NFC TagWriter by NXP の使い方

メニューから、「Erace tags」を選びます。
![Screenshot_2025-02-17-11-44-31-436_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ce7d5d10-183b-4bc9-a560-128a00b4d253.jpeg)

「Erace tags」↑「Erase & format as NDEF」
![Screenshot_2025-02-17-11-44-47-543_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/54bc33e3-510d-411e-8bc0-f931ff43c2e1.jpeg)

ここは、492 と入力が必要だそうです。(?)
![Screenshot_2025-02-17-11-45-26-926_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e76a4d3d-928b-4dab-adcb-7361df95cc30.jpeg)


「TAP TO CONFIRM FORMAT」ボタンを押して進みます。
![Screenshot_2025-02-17-11-49-01-951_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1a5583b6-8349-41cb-ade9-21d9f54a2a20.jpeg)

うまくいったようです。
![Screenshot_2025-02-17-11-49-12-086_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5b0dcee0-c7cd-4f6d-b7aa-81cea79e9080.jpeg)


「Write tags」
![Screenshot_2025-02-17-11-49-24-264_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c61251a1-a479-42f0-8527-c598bf109a14.jpeg)


「New dataset」

![Screenshot_2025-02-17-11-49-36-317_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/89d11e91-0f5c-4e10-ade0-03f3c161728b.jpeg)

dataset は色んな情報を格納することができます。
![Screenshot_2025-02-17-11-49-48-777_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d23b1f70-632a-4150-8849-c123e73daf3c.jpeg)


今回は、Link を設定しました。

URLを設定します。
![Screenshot_2025-02-17-11-51-35-943_com.nxp.nfc.tagwriter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/512913d6-84d6-4db3-b2e8-b47849395ea5.jpeg)
円周率近似。 多角形の数を追記増やしていく方式

まず、結論。
<h3>Googleスプレットシートの方が有効桁数が多かった</h3>

だけど、まずはCプログラム↓

```pai13.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


void now(void)
{
	time_t t = time(NULL);
	struct tm *local = localtime(&t);
/*
	printf("%04d/", local->tm_year + 1900);
	printf("%02d/", local->tm_mon + 1);
	printf("%02d", local->tm_mday);

	printf(" ");
*/
	printf("%02d:", local->tm_hour);
	printf("%02d:", local->tm_min);
	printf("%02d\n", local->tm_sec);
	fflush(stdout);
}

int main(int argc,char *argv[])
{
	unsigned long long	nnn = time(NULL),o=0;
	unsigned long long	n=1000;
	if(argc > 1 )
	{
		n=atol( argv[1] ) ;
	}
	printf("---START---     ");	now();//時刻表示
	//--- --- --- ---
	int m=10 ; // 計算する数

	double ox,oy  ,x,y ,hiriz ,a ,kos;
	ox = 1.0d /sqrtf(2.0d);
	oy = ox ;
	kos = 8.0d ;

	while(m)
	{
		x=1.0d-(1.0d-ox) / 2.0d;
		y=oy / 2.0d;

		hiriz = 1/sqrtf(x*x +y*y);
		x *= hiriz ;
		y *= hiriz ;
		a=sqrt((1-x)*(1-x) + y*y);

		ox = x ;
		oy = y ;

		nnn = time(NULL);
//		if ( nnn >= o)
		{
			printf("%1.24f ,%d角形\n",a * kos,(long long)kos ) ;
//			now();
			o = nnn + 1 *1  ;
			m--;
		}

		kos *= 2.0d;
//m=1;	
	}//...while
	printf("\n正解π↓\n%1.24f \n",M_PI ) ;
	 
	 
	return 0;
}
```

```結果.txt
---START---     18:23:18
3.121445215682374652033104 ,8角形
3.136548472039406565414765 ,16角形
3.140331117647078507104652 ,32角形
3.141277270129558374378576 ,64角形
3.141513802258355525509614 ,128角形
3.141572989680802230338941 ,256角形
3.141587814405001566342435 ,512角形
3.141591629083641201702903 ,1024角形
3.141592637263832532568131 ,2048角形
3.141593029342560683403462 ,4096角形

正解π↓
3.141592653589793115997963 
```
↑
3.1415926
まで正解


---
Googleスプレットシートは
```..
3.141592653589790000000000
```
↑
3.14159265358979
まで正解。

Googleすげぇや
(あんたが15年前のPC使ってるからだよ)
Arduino IDE が閉じれない

Arduino IDE を起動した状態でPCを離れ、しばらくしてから戻って作業を再開しようとすると主要な操作ができなくなっています。ネットを検索したら１つ投稿が見つかりました。

https://forum.arduino.cc/t/ide-2-3-0-wont-close/1222082

スリープ時間が長いときに発生するようです。解決策は不明です。タスクマネージャで終了させるしか方法がありません。

発生環境は Windows 11 24H2 です。
Apple Silicon の Macで発生する ImportError: The 'enchant' C library was not found and maybe needs to be installed. の対処方法

### 軽い前置き
# 何について書いているのか
- Apple SiliconのMacを使っていて、英語のスペルチェッカーであるenchantを使いたいが、rosetta を使えという対処法しか見つからず、処理速度が遅くて唸っている人向けの enchant の入れ方です
- 結論から言うと、rosetta使わなくても入れることが出来ます

# 主要なコマンド

```
brew install enchant
poetry add pyenchant
export PYENCHANT_LIBRARY_PATH=/opt/homebrew/Cellar/enchant/2.8.2/lib/libenchant-2.2.dylib
```
です。
以下のソースコードで動作確認してオッケーなら、ちゃんと入っています

```python
import enchant
d = enchant.Dict("en_US")
d.check("Hello") # True
d.check("Helo") # False
```

# 何をやっているのか
## 1行目
```
brew install enchant
```
- [enchant](https://github.com/rrthomas/enchant)（英語のスペルチェッカー）を入れています。
- [ここ](https://formulae.brew.sh/formula/enchant)にある通り、最新版がHomebrewで配信されており、macOSでも動くようになっています
- [PyEnchant](https://pyenchant.github.io/pyenchant/)の[Enchantのリンク](https://abiword.github.io/enchant/)が切れており、たどり着けない方がいるようです

## 2行目
```
poetry add pyenchant
```
- [poetry](https://python-poetry.org/)使っている前提になっていますがpipでも一緒です、たぶん。

## 3行目
```
export PYENCHANT_LIBRARY_PATH=/opt/homebrew/Cellar/enchant/2.8.2/lib/libenchant-2.2.dylib
```
- [PyEnchant](https://pyenchant.github.io/pyenchant/)が読みに行くパスを設定してあげることで、読めるようになります

# 背景
## 意地でもrosetta使いたくないマン
- 私は意地でもrosetta使いたくないマンです
- だって遅いんだもん
- 他にもEC2でもArmを選択したいとか、raspiで動かしたいとか、いろいろ邪念が多いようです

## [rosettaを使えというissue](https://github.com/pyenchant/pyenchant/issues/265)
- Apple Silicon 出始めに作られたこちらのissueを見に行ってしまうケースが多いようです
- 出てからもう何年も経ってるからさすがに対応されてるだろJK、ってことでここでも意地を張ります

## [pypiにAppleSiliconバイナリが上がっていない](https://pypi.org/project/pyenchant/#files)
- バイナリ付きのwhlはWindows向けしか上がっていないんですよね
- 逆に言うとMac向けのは無さそうに見えちゃいます
- また、最終更新も2021年と古く、「最近更新されてないのかなぁ」という思い込みを生じやすいです

# 自力でビルドしてインストールする場合
- [ここ](https://github.com/rrthomas/enchant/releases)にソースが上がっているのでbuildしてもセットアップできます

### groffを入れる
- groffを入れていない場合は ```brew install groff``` を実行しましょう

### INSTALLに記載のあるコマンド

```
 test -f configure || ./bootstrap
 ./configure
 make
 make install
 ```
上記を実行すると以下ができるので、
```
/usr/local/lib/libenchant-2.2.dylib
/usr/local/lib/libenchant-2.dylib
```
PYENCHANT_LIBRARY_PATHを設定してdynamicに読む設定をしてあげると、動きます
 

# 最後に
- 上記の通り、わりと罠が多めなので、注意しましょう
ChatGPTの新機能「プロジェクト」でライフハックしてISTQB Test Analystをやっつけ合格した話（コピペで使えるプロンプト付き）

### 受験に至る経緯

今期受験しようとチケットを購入し、仮日程を登録しておいた「ISTQB Test Analyst」試験。準備が整ったら受験するつもりだったが、リスケしようとしたら無料リスケ期限（72時間）が過ぎており、**翌日試験を受けるしかなくなった**。

普段はISTQBの試験を受けるとき、シラバスをすべて読み、サンプル問題も一通り解いてから臨んでいる。しかし、今回は**シラバスのセクション2/6を読んでいる途中で、サンプル問題も5/40問しか解いていない状態**。どうやっても翌日までに間に合いそうになかった。

そこで、以前作成した **ChatGPTの新機能「プロジェクト」** を利用した学習のみで挑むことにした。

---

### ISTQB対策プロジェクトの作成手順

ISTQB試験対策のためにプロジェクトを作成する手順は以下の通り。

1. ChatGPTのサイドメニューにある「Projects」の「+」アイコンをクリックし、新規プロジェクトを作成。
2. プロジェクト名「ISTQB Test Analyst Coach」を設定し、プロジェクトを作成。
3. ISTQBの公式ページ（[Certified Tester Advanced Level Test Analyst (CTAL-TA)](https://www.istqb.org/certifications/certified-tester-advanced-level-test-analyst/)）からシラバスとサンプル問題のPDFをダウンロードし、プロジェクトにアップロード。
4. 「Instructions」にプロジェクトの指示・目的を入力。

#### **インストラクションの例**

```plaintext
Help the user pass the ISTQB Test Analyst exam while referring to the attached official documents.
```

これで、ISTQBの学習専用のプロジェクトが完成。

---

### 活用事例

プロジェクトは目的ごとにスレッドを作成し、名前をつけて保存しておくことができる。今回は**シラバス学習用スレッド**と**サンプル問題演習スレッド**を作成。

#### **シラバス勉強スレッド**

新規チャットでシラバス学習用のスレッドを作成し、「ISTQB CTAL-TA Study Guide」などの名前をつけて管理。

##### **スレッド作成プロンプト例**

```plaintext
Let's start the Syllabus Reading & Study Thread! I want to go through the ISTQB CTAL-TA syllabus step by step. 
Guide me through it, provide summaries, and highlight key exam points.
```

##### **実際に使って感じたメリット**

- シラバスの内容を要約してくれるので、**読むべき文字数が圧倒的に少なくなり、時短に貢献。**
- 要約されることで重要ポイントが整理され、**かえって理解しやすくなった。**
- 試験の設問の意図や「〇〇と書いてあったらXXを選ぶべし」などの**試験用Tipsも提示してくれた。**
- シラバスの記述が分かりにくい場合や、実務との乖離について質問すると、**一般的な専門知識を背景にしっかり解説してくれた。**
- 各セクションの最後にサンプル問題を一問ずつ提示してくれたため、**短時間で要点を押さえながら演習できた。**

📸 **ChatGPTによるシラバス要約の例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/84acd7f1-fe4e-41d1-84af-20731569886a.png)

📸 **ChatGPTによる試験用Tipsの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/d2b60c13-044f-46ad-9264-9698430f99d9.png)
「シナリオが"time constraintsや"vague requirements"に言及していたら"exploratory testing"を選んでおけばOK。」という実践的なアドバイス。なるほど😏📝


#### **サンプル問題勉強スレッド**

もう一つ、サンプル問題の出題、解答チェック、解説用のスレッドを作成。

##### **スレッド作成プロンプト例**

```plaintext
In this thread, provide me with each ISTQB CTAL-TA sample question, check my answers, and track my progress.
```

##### **活用ポイント**

- サンプル問題の出題と答え合わせができる。順番に一問ずつ出題してもらうこともできるし、頼めばランダム出題も可能。
- 気になる点はなんでも質問して理解を深められる。

📸 **ChatGPTによるサンプル問題の出題例。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/718d0597-f36c-42a1-a21a-b5046cdd560c.png)


---

### 試験の結果と所感

試験会場に向かう時間も使い、ギリギリChatGPTが用意してくれた要約を一通り済ませることができた。そのおかげで、**シラバスをすべて読み、サンプル問題をすべて解いたときのように「一通り準備した」という実感を持って試験に臨めた。**

結果は…

✅ **合格ライン：65%**
✅ **得点率：77.8%🏆🎯**

短期間での対策だったが、結果としては「**まずまずのスコア**」。今回は成り行きで超時短モードになったが、**ChatGPTの活用でここまでの点数を取れたのは十分な成果だった。**

---

### まとめ

今回の試験対策は**ISTQB CTAL-TAに限らず、シラバスとサンプル問題が公開されている資格試験なら同じ方法で応用できるはず**。

特に、
✅ **短期間で効率的に試験対策したい人**
✅ **試験勉強を計画的に進めたい人**
✅ **GPTsを使用しているが継続的タスクの履歴データ管理に課題を感じている人**

にはおすすめの方法。

**勉強効率化のライフハックツールとして、今後も活用していきたい🔥**
rex0220 プラグイン 5営業日後の計算

rex0220 プラグインを使って、5営業日後の計算を行ってみます。

# 概要

下記の rex0220 プラグインを利用して、5営業日後の計算を行ってみます。
・休日プラグイン（無償）：　祝日設定アプリ
・休日Plusプラグイン：　カレンダー祝日表示
・アプリ集計プラグイン：　祝日データ取得
・計算式プラグイン：　5営業日後の日付計算

![2025-02-21_18h02_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9b4a8ddb-50be-452b-9a5e-24cba513e6a3.png)

- 休日アプリ

![2025-02-21_18h29_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ce69e106-5a84-431e-a36c-fd5a11d6ae89.png)

# アプリ設定

祝日データ取得用に、「作業用1」「作業用2」を配置

![2025-02-21_18h07_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4fee1924-46fe-4ee3-90f8-02eae2b1b8ae.png)


# アプリ集計プラグイン設定

5営業日が年またがりを考慮して、2年分の祝日データを「作業用1」「作業用2」に取得します。

![2025-02-21_18h10_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d7829410-26a9-4d7d-81ad-995ea4a2b8cc.png)

- 対象アプリ条件

日付を基準に2年分を対象にします。

![2025-02-21_18h11_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/107cec97-75bc-4bac-a064-72f3b21ac509.png)

- 集計項目

祝日日付をまとめて、文字列に変換して、「作業用1」「作業用2」にセット
JSON_S(TDS(DATE_FORMAT(date)))

![2025-02-21_18h12_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8fff3c62-0efd-41a7-8d2a-0333a0469a80.png)

# 計算式プラグイン設定

指定日以降の平日の配列から、土日祝日を除外して、5営業日後の日付を求めます。
指定日以降の31日間に平日が5日無いようであれば、期間を延ばしてください。

- 日付から31日分の日付配列を生成
- 土日の日付を除外
- 休日配列を「作業用1」「作業用2」から生成
- 土日除配列から休日配列を除外
- 求めた平日配列から、5番目の日付を取得


![2025-02-21_18h18_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cbf5e686-7a24-4dcd-bf82-93e3bb44bd5e.png)

```.js
OPTION: 

// タイトル表示用 SINGLE_LINE_TEXT
タイトル&" 5営業日後:"&DATE_FORMAT(５日後の営業日,"M/D")

// ５日後の営業日 DATE
LET(
    全日付, ARRAY_FOR(31, idx, DATE_ADD(日付, idx+1, "days")),
    土日除, ARRAY_FIL(全日付, day, NOT(IN(DATE_FORMAT(day, "e"), "0", "6"))),
    休日, DISTINCT(JSON_P(作業用1),JSON_P(作業用2)),
    営業日, ARRAY_DEL(土日除, 休日),
    ARRAY_GET(営業日, 4)
)

// 作業用1 SINGLE_LINE_TEXT (hide)
// 作業用2 SINGLE_LINE_TEXT (hide)
```

# 休日Plusプラグイン設定

カレンダー形式の一覧画面で、祝日を表示して確認しやすいようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f95a988d-613b-4806-b88e-73c107d6ea75.png)
LinuxサーバーでIPブロックする時どれ使えばええか分からない問題

## 前置き

こんにちは、キタです。

普段インフラエンジニアとしてサーバーの運用保守をしていて、
いきなり**海外IPからの大量アクセスが来る現象**にキレたことはないでしょうか？
私はあります。
ちょっとムキっとなります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935946/9ba1ebca-32e5-48f0-84a0-cbfe8b1f3849.png" width="300％">


最近はCloudflareや、攻撃遮断くんなどのWAFを前段に配置していて、そこでブロックされる場合もありますが
構成によってはサーバー側でIPを指定してブロックしなければならない場面もあるかと思います。

既知の人もいるかと思いますが、Linuxにはセキュリティ制御機構が割とあり、
初心者の方は「どの方法を使えばいいの？」と迷うことも多いです。（自分がそうだった）

本記事は、そんな「結局どれ使ったらええねん」と思っている同志の方向けの記事です。


## 結論
結論：手軽にIPブロックするなら firewalld や iptables または nftables でいいと思います。

まずはブロック手法をそれぞれあげていきましょう。

### 1. firewalled（RHEL系の搭載のファイアウォール）
RHEL、CentOS、Fedora などで使われるファイアウォール管理ツールです。
最近のAlmaではデフォルトで入っていないことが多くて悲しくなります…(どのみち止めますが)
特徴としてiptables や nftables を内部で利用し、ゾーンごとの管理が可能となっています。
```bash
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" reject'
firewall-cmd --reload
```
適用範囲: ネットワークパケット

### 2. iptables（古くから使われるパケットフィルタリングツール）
古き良きパケットのフィルタリングを行うツールで、Linuxカーネルの netfilter が利用されています。
特徴として、細かいルール設定が可能です。ただし、次に紹介するnftables へ移行が推奨されています。
```bash
iptables -A INPUT -s 192.168.1.100 -j DROP
service iptables save
```
適用範囲: ネットワークパケット

### 3. nftables（iptablesの後継、より高性能） 
先ほど紹介した iptables の後継として開発され、パフォーマンスや柔軟性が向上しています。
特徴として 1つのルールセットでIPv4/IPv6を扱えて、柔軟な管理が可能です。
```bash
nft add rule ip filter input ip saddr 192.168.1.100 drop
```
適用範囲: ネットワークパケット

### 4. route（ルーティングテーブルによる制御）
OS内のルーティングテーブルを操作して、特定のIPの通信を無効化してくれます。
こちらは一時的な対策向けで、細かい制御にはあまり向かない印象です。
```bash
route add -host 192.168.1.100 reject
```
適用範囲: OSルーティング


### 5. ipset（大量のIPアドレスを効率的にブロック）
こちらは iptables や nftables と組み合わせて、大量のIPを高速にブロックしてくれます。
動的にIPリストを管理できるため、DDoS対策などに有効です。
```bash
ipset create blacklist hash:ip timeout 3600
ipset add blacklist 192.168.1.100
iptables -I INPUT -m set --match-set blacklist src -j DROP
```
適用範囲: iptables や nftables と連携して利用

### 6. TCP Wrappers（hosts.allow / hosts.deny）
libwrap を利用し、特定のIPからの接続を許可・拒否する仕組みです。
正直OSのブロック機構かと言われると微妙ですが一応リストにあげておきました。
特徴としてはSSHやFTPなどの特定サービスに適用可能です。ただし、近年ではあまり見かけません。
```bash
## /etc/hosts.deny に設定
ALL: 192.168.1.100
```
適用範囲: TCPベースの特定のサービス


## まとめ
最後に表でまとめてみました。
| 方法         | メリット                           | デメリット                           | 適用範囲                   | 
| ------------ | ---------------------------------- | ------------------------------------ | -------------------------- | 
| firewalld    | RHEL系の搭載、ゾーン管理が簡単     | 仕組みが少し難しい	                  | パケットフィルタリング     | 
| iptables     | 細かいルール設定が可能	            | nftables に置き換え推奨	             | パケットフィルタリング     | 
| nftables     | 高パフォーマンス、柔軟なルール管理 | 設定が難しい	                        | パケットフィルタリング     | 
| route        | シンプルで分かりやすい	            | 一時的な対策向け	                    | ルーティング               | 
| ipset        | 大量のIPを高速に処理可能	          | iptables や nftables との併用が必要	 | パケットフィルタリング<br> | 
| TCP Wrappers | シンプルなサービス単位の制御	      | 既に非推奨                           | TCPベースの特定サービス    | 

「基本は firewalld / iptables / nftables」
「大量のIPをブロックするなら ipset」
「一時的なブロックなら route」
といった感じでしょうか。

これ以外にも、OSの制御機構であれば SELinux とかも有名ですよね。

正直OSベースで管理するより、それより前段で制御できる構成の方が望ましいと思うので、
今後使う機会は減りそうですが、少しでも参考になれば幸いです。

※ここに無いものや、内容が間違っていればご指摘いただけますと幸いです。

ではでは～
Filemaker JSONArray

FilemakerのJSON関数でもっとも情報が少ないJSONArrayについて覚え書き

## 基本の配列作成
```
JSONSetElement ( "{}";
[ "[0]"; "A"; JSONString ];
[ "[1]"; "B"; JSONString ];
[ "[2]"; "C"; JSONString ]
)
```
結果
```
["A","B","C"]
```
## 要素の追加
```
Let ( [
	%json =
    	JSONSetElement ( "{}";
    	[ "[0]"; "A"; JSONString ];
    	[ "[1]"; "B"; JSONString ];
    	[ "[2]"; "C"; JSONString ]
    	);
	%json =
    	JSONSetElement ( %json;
    	[ "[3]";	"D";	JSONString ]
    	);
%=0];
    %json
)
```
結果
```
["A","B","C","D"]
```
## key付きで配列化
ここで`JSONArray`登場｡もっと良い書き方があればいいのだけれど｡
```
JSONSetElement ( "{}";
[ "data";
	JSONSetElement ( "{}";
    [ "[0]"; "A"; JSONString ];
	[ "[1]"; "B"; JSONString ];
	[ "[2]"; "C"; JSONString ]
	);
	JSONArray ]
)
```
結果
```
{"data":["A","B","C"]}
```
## key付きで要素の追加
だんだん面倒くさくなってきました｡
```
Let ( [
	%json =
		JSONSetElement ( "{}";
		[ "data";
			JSONSetElement ( "{}";
			[ "[0]"; "A"; JSONString ];
			[ "[1]"; "B"; JSONString ];
			[ "[2]"; "C"; JSONString ]
			);
			JSONArray ]
		);

	// 配列要素の追加
	%json =
		JSONSetElement ( %json;
		[ "data";
			JSONSetElement ( JSONGetElement ( %json; "data" );
			[ "[3]";	"D";	JSONString ]
			);
			JSONArray ]
		);

%=0];
	%json
)
```
結果
```
{"data":["A","B","C","D"]}
```
### key付きに追加する要素の番号を自動で決める
FileMaker 2023なら新機能`[+]`が使えるけど､古いFileMakerで動作させるための小細工
```
Let ( [
	%json =
		JSONSetElement ( "{}";
		[ "data";
			JSONSetElement ( "";
			[ "[0]"; "A"; JSONString ];
			[ "[1]"; "B"; JSONString ];
			[ "[2]"; "C"; JSONString ]
			);
			JSONArray ]
		);

	// 配列要素の追加
	%n = ValueCount ( JSONListValues ( %json; "data" ) );
	%json =
		JSONSetElement ( %json;
		[ "data";
			JSONSetElement ( JSONGetElement ( %json; "data" );
			[ "[" & %n + 0 & "]";	"D";	JSONString ];
			[ "[" & %n + 1 & "]";	"E";	JSONString ]
			);
			JSONArray ]
		);

%=0];
	%json
)
```
結果
```
{"data":["A","B","C","D","E"]}
```
M5Core2: 円の描画

次の描画をします。

![IMG_0005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/a9a3e195-9e11-4036-8bbb-3d0e17015cda.jpeg)

![IMG_0006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/434bc617-f715-491a-a598-191444e57056.jpeg)

## プログラム

```cpp/src/main.cpp
#include <M5Core2.h>

// ---------------------------------------------------------------
void draw_circle_proc(int xpos,int ypos,uint16_t color)
{
	for (int it=0; it< 10; it++)
		{
		int rr = 41 + it;
		M5.Lcd.fillCircle(xpos, ypos, rr, color);
		}
}

// ---------------------------------------------------------------
void setup() {
	M5.begin();
	M5.Lcd.fillScreen(BLACK);
}

// ---------------------------------------------------------------
void loop() {
	M5.Lcd.fillScreen(BLACK);
	delay(2000);
	draw_circle_proc(60,120,GREEN);
	delay(2000);
	draw_circle_proc(260,120,GREEN);
	delay(2000);
	draw_circle_proc(60,120,RED);
	delay(2000);
	draw_circle_proc(260,120,RED);
	delay(2000);
}

// ---------------------------------------------------------------
```

## PlatformIO

Build して、 Upload した状況

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/7927e682-0a06-49fd-a810-904cf9616962.png)
Rasberry Pi 5を使って録画サーバー + NASの構築。あとがき+α編

あとがきとisdbscan使用方法編です。
それ以外の記事は以下
1. [導入編](https://qiita.com/tutumun/items/7b8af6ce5ee9fae89b5a)
2. [NAS構築編](https://qiita.com/tutumun/items/31c9b276334c0f94332b)
3. [チューナー編](https://qiita.com/tutumun/items/10d7917771b363418f3e)
4. [あとがき+α編(本記事)](https://qiita.com/tutumun/items/757e0c6f2cba99c076ae)

### isdbscan の使用方法
isdbscan を使用すると、各地域の放送チャンネルをスキャンできます。
先ほどのchannels.ymlは東京エリアのものでしたので、
他地域の方はこれを使うといいかと思います。

#### ダウンロード & インストール
```
cd ~/git
wget https://github.com/kazuki0824/recisdb-rs/releases/download/1.2.2/recisdb_1.2.2-1_arm64.deb
sudo apt -y install ./recisdb_1.2.2-1_arm64.deb
rm ./recisdb_1.2.2-1_arm64.deb
sudo wget https://github.com/tsukumijima/ISDBScanner/releases/download/v1.2.1/isdb-scanner-arm -O /usr/local/bin/isdb-scanner
sudo chmod +x /usr/local/bin/isdb-scanner
```

#### スキャン実行
```
isdb-scanner --exclude-pay-tv
```
このコマンドは 無料チャンネルのみスキャン
有料チャンネルも含めたい場合は
```
isdb-scanner
```
出力結果は ./git/scanned/Mirakurun に channels.yml として保存されるので、それを利用してください。

### あとがき
#### 運用状況
現在、運用開始から約2週間が経過しましたが、特に大きな問題なく動作しています。
ただし、電源の安定性については若干の不安が残っています。

自作ケースについて
ダイソーのコンテナを利用してケースを作成しました。
![IMG_20250209_152411.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/fb0093d1-b4d6-4afa-a9a0-3d4b7ef00abf.jpeg)

100円のコンテナもありましたが、高さが足りなかったため、200円のコンテナを使用しました。

蓋部分：同じコンテナのサイドパネルを取り外して使用。
ケーブルの通し口：はさみでカットして加工。
![IMG_20250209_152440.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/7b3e870b-449c-49f5-ba0a-f236f77080ce.jpeg)
冷却対策：夏場の温度上昇がどれほどになるかがわかりませんが、最悪結束バンドでPC用の8cmファンを取り付けるなどの対策すればいいかな？。

### 感想
全体的長くてに見づらかったので分割して、ChatGPTちゃんに文章校正してもらいました。(多少はましになった？)

本記事はあくまで自分用のメモとして作成したものですが、もし他の方の参考になれば幸いです。
構築の大部分は参考サイト様の情報を基にしています。この場を借りて感謝申し上げます。

ラズパイを触るのは今回が初めてでしたが、Linux 環境でのサーバー構築は良い経験になりました。
当初はNAS のみを構築する予定で Raspberry Pi 4 を購入し、試しに運用していました。
しかし、ある日 某R天ポイントから「8000ポイントが失効するよ」 という通知が届き、
「何に使おうか」と考えた結果、Raspberry Pi 5 ならスペックが向上しており、PCIe も使えるため、1台で録画サーバー＋NASを構築できるのでは？
と思い、今回のプロジェクトをスタートしました。

ただし、事前の下調べが甘かったため、電源問題などのトラブルが発生し、予定よりも出費がかさんでしまいました。
それでも最終的に構築が完了し、動作も安定しているため満足しています。

なお、Raspberry Pi 4 が余ったため、今後は別の用途で活用して遊んでみようと思います。

それでは。
Rasberry Pi 5を使って録画サーバー + NASの構築。NAS構築編

この記事はNAS構築編です
それ以外の記事は以下
1. [導入編](https://qiita.com/tutumun/items/7b8af6ce5ee9fae89b5a)
2. [NAS構築編(本記事)](https://qiita.com/tutumun/items/31c9b276334c0f94332b)
3. [チューナー編](https://qiita.com/tutumun/items/10d7917771b363418f3e)
4. [あとがき+α編](https://qiita.com/tutumun/items/757e0c6f2cba99c076ae)

# NAS構築編

### OpenMediaVault(以下OMV)のインストール
```
cd git
wget -O - https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install | sudo bash
```

### インストール手順
インストールには約1時間かかる場合があります。
待機中は他の作業を進めてもよいでしょう。
ただし、再試行した際には20分程度で完了したため、環境によって所要時間は異なる可能性があります。

インストールが完了したら、ブラウザで以下のURLにアクセスしてください。
以降ラズパイのIPアドレスを192.168.100.100としておきます。これは各自環境に合わせてください
```
http://192.168.100.100
```
当方はルーターでIPアドレスを固定していたため、事前に把握していましたが、
IPアドレスが不明な場合は、ターミナルで以下のコマンドを実行して確認してください。

```
ifconfig
```

アクセスすると、下図のようなログイン画面が表示されます。
初期ログイン情報は以下の通りです。

![Clipboard03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/5c4af0e7-baeb-45dd-93f8-8a5285f13333.jpeg)

ユーザー名：Admin
パスワード：openmediavault
（※Clipboard03.jpg 参照）

ログイン後、各種設定を行っていきます。

### 共有の設定
1. ファイルシステムの設定
左側メニューの ストレージ > ファイルシステム にアクセス。
各アイコンにマウスオーバーすると説明が表示されるので、分からない場合は確認してください。
「既存のファイルシステムをマウント」をクリック。
ファイルシステムのプルダウンから、マウントしたいファイルシステムを選択。
すでにフォーマット済みの場合、リストに対象が表示されます。
未フォーマットの場合は、「ファイルシステムを作成し、マウントします」をクリックし、EXT4 を選択。
デバイスを選択し、マウントを実行。
2. 共有フォルダの作成
ストレージ > 共有フォルダ にアクセスし、「作成」をクリック。
共有フォルダ名を設定し、ファイルシステムを選択した後、保存。
![open_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/e09072c0-46eb-4bf3-8def-4ee24740dd18.png)


3. サービス > SMB/CIFS > 設定 にアクセスし、
下図のチェック項目と同じように設定を行う。
![open_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/cec80216-0daa-471a-aa15-f9d8abfec3d6.png)
ワークグループ名を、自身のネットワークに合わせて設定。
サービス > SMB/CIFS > 共有 に移動し、「作成」をクリック。
先ほど作成した共有フォルダを選択し、設定を完了。

4. ユーザーの作成
ユーザー > ユーザー にアクセスし、「作成 / インポート」をクリックし、新規ユーザーを作成。
ユーザー名、パスワードを設定。
共有フォルダのアクセス権限を設定：
作成したユーザーを選択し、
下図の赤枠内にある共有フォルダのパーミッションを設定する。![open_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/984321b4-2dcd-4c46-8fdf-022ab56bfacd.png)
権限は「Read/Write（読み書き可）」を選択。
![Clipboard04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/07af574f-7427-406d-a3a0-4d47a98fbe03.jpeg)
設定中に「保留中の構成変更」のメッセージが表示された場合は、適宜適用。
![open_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145241/be0dc81b-adfb-48b5-b7ef-07d65260f9c3.png)
5.動作確認
Windowsのエクスプローラーを開き、アドレスバーに
\\\\192.168.100.100\\
を入力。
エンターキーを押すと、ユーザー名 / パスワードの入力を求められるため、
先ほど作成したユーザーの情報を入力。
作成した共有フォルダが表示され、アクセスできれば設定完了。

### もしアクセスできない場合
一度 Windows を再起動してみる。
それでも解決しない場合、最初から設定を見直し、再構築する。

以上でNAS構築編を終わります。
この辺ならまだ戻っても大した時間はかからないので、
失敗したと思ったらOSインストールからさいかいするのもいいかとおもいます。
k8s sealed secretをone-linerで作る

# 要約

k8s上の公開鍵を使う場合
```sh
kubectl create secret generic \
    your_secret_name \
    --namespace=your_namespace \
    --dry-run=client \
    --output=yaml \
    --type=Opaque \
    --from-literal=key=value | \
kubeseal \
    --format=yaml \
    --sealed-secret-file=your_sealed_secret.yaml \
    --controller-namespace=your_sealed_secret_namespace \
    --controller-name=your_sealed_secret_controller
```

ローカルの公開鍵をつかう場合
```sh
kubectl create secret generic \
    your_secret_name \
    --namespace=your_namespace \
    --dry-run=client \
    --output=yaml \
    --type=Opaque \
    --from-literal="ke=value" | \
kubeseal \
    --format=yaml \
    --sealed-secret-file=your_sealed_secret.yaml \
    --cert=your_public_key.pem
```

# 対象読者

* k8s Secretを作るのに `base64` を使って改行が入って動かなかった方
* k8s Secretファイルを手で書いてる方
* たまにしかSealedSecretをつくらないので作り方を忘れている方

# はじめに

SealedSecret作ってますか？私はたまに作ります。たまにしか作らないので

1. 毎回作り方を忘れる
2. 泥臭い方法を毎回使ってしまう

という状況でした。たまにしかやらないとはいえ、たまにはやるのでそろそろ勉強しようと思いました。その結果が概要に記載されたものです。one-linerと言いつつ複数行になっていますが、そこはつっこまないでください。

# もうすこし細かい説明

コマンドを少し解説します。まず前半のk8s Secretの作成部分です。

## kubectl create secret generic

```sh
kubectl create secret generic \
    your_secret_name \
    --namespace=your_namespace \
    --dry-run=client \
    --output=yaml \
    --type=Opaque \
    --from-literal=key=value
```

まず `kubectl create secret generic` は k8s Secretを作成するコマンドです。

サブコマンドの最後の `generic` 以外に `tls` と `docker-registry` がありますが、アプリケーションで使う環境変数やファイルを設定したい場合は `generic` です。

`your_secret_name` は Secretの名前です。 `metadata.name` に設定されます。

`--namespace=your_namespace` はSecretのnamespaceです。 `metadata.namespace` に設定されます。

`--dry-runi=client` はdry runの指定で実際にk8s サーバにSecretを作らないことを意図します。またdry runがclient側で実行されます。

`--output=yaml` は出力形式の指定です。

`--type=Opaque` はSecretのタイプを指定します。こちらもアプリケーションで使う環境変数やファイルを設定したい場合は `Opaque` にしてください。ほかのタイプは[こちら](https://kubernetes.io/docs/concepts/configuration/secret/#secret-types)をご確認ください。

`--from-literal=key=value` は Secret に設定される値です。 `data` の中に設定されるフィールドのキーと値を=で繋いで設定します。値の設定方法はこれ以外に `--from-env-file` と `--from-file` があります。

`--from-env-file` は.env形式のファイルを読み込んでその中の環境変数を全て設定します。以下のようなファイルがある場合、KEY1にVAL1が設定され、KEY2にVAL2が設定されます。
```
KEY1=VAL1
KEY2=VAL2
```

`--from-file` は指定したファイルの中身を値として設定します。キーはファイル名です。`--from-file=key=path/to/file`とするとキーをファイル名から変更できます。

`--from-env-file` 以外は複数指定可能です。

## kubeseal
k8s上の公開鍵を使う場合
```sh
kubeseal \
    --format=yaml \
    --sealed-secret-file=your_sealed_secret.yaml \
    --controller-namespace=your_sealed_secret_namespace \
    --controller-name=your_sealed_secret_controller
```

ローカルの公開鍵をつかう場合
```sh
kubeseal \
    --format=yaml \
    --sealed-secret-file=your_sealed_secret.yaml \
    --cert=your_public_key.pem
```

こちらは余り書くことがないのですが、一応書いておきます。まずは共通の部分です。

`--format=yaml` は出力形式の指定です。

`--sealed-secret-file=your_sealed_secret.yaml` は出力されるSeaeledSecretのファイル名です。

k8s上の公開鍵を使う場合は `--controller-namespace=your_sealed_secret_namespace` と `--controller-name=your_sealed_secret_controller` を指定します。

ローカルの公開鍵を使う場合は `--cert=your_public_key.pem` で公開鍵を含んだファイルを指定します。

# まとめ

SealedSecretのone linerでの作成方法を記載しました。各コマンドについて調べた内容も書きました。
基本、概要部分をコピペして適切に修正して使っていただければと思います。
ローカルのMySQLクライアントからAmazon Auroraに繋げなくなった話

こんにちは、サーバエンジニアの池脇です。
今回はローカルのMySQLクライアントからAmazon Auroraにアクセスしようとした際に繋げなくなった話とその際の解決方法について共有します。

## なにもしてないのにこわれました
ある日、普段通りの業務でサーバ上のデータを見にいこうとすると
```
ERROR 2059 (HY000): Authentication plugin 'mysql_native_password' cannot be loaded: dlopen(/opt/homebrew/Cellar/mysql/9.2.0/lib/plugin/mysql_native_password.so, 0x0002): tried: '/opt/homebrew/Cellar/mysql/9.2.0/lib/plugin/mysql_native_password.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/mysql/9.2.0/lib/plugin/mysql_native_password.so' (no such file), '/opt/homebrew/Cellar/mysql/9.2.0/lib/plugin/mysql_native_password.so' (no such file)
```

このようなエラーが発生しました。
エラーを詳しく見てみるとMySQLのバージョンが`9.2.0`になっている模様……

よくよく考えると直近で`brew update`を行っていたため、HomebrewでインストールしているMySQLのバージョンが最新になっているのでは？？

```
$ mysql --version
mysql  Ver 9.2.0 for macos13.7 on arm64 (Homebrew)
```

犯人はお前かー！！
ということでHomebrewのアップデートを安易に行った自分のせいでした。

:::note
`mysql_native_password`はユーザパスワードのハッシュ化に`SHA-1`を用いており、MySQL5.7まではデフォルトの認証プラグインでした。
MySQL8.0からはハッシュ化により安全な`SHA-256`を用いた`caching_sha2_password`認証プラグインが追加され、デフォルトとして利用されています。
そのため`mysql_native_password`はMySQL8.1で非推奨、MySQL8.4でデフォルト無効となっており、それが原因で上記エラーが発生しているようです。
詳しくは以下をご覧ください。
[MySQL8.4での mysql_native_password 認証プラグインの扱い](https://blog.s-style.co.jp/2024/05/11793/)
:::

## 対応方法を考える
考えるといってもすでに動いているサービスのアップデートは難しい[^1]ためローカルのMySQLクライアントのバージョンを下げる必要があります。
ということでまずはHomebrewのMySQLのページを確認してみましょう。

https://formulae.brew.sh/formula/mysql

![スクリーンショット 2025-02-21 16.12.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/965cb4e4-4b08-46b1-b611-3090b6dc2f5b.png)

その他のバージョンの中に8.0系があったのでこちらをインストールしましょう。

```
$ brew install mysql@8.0
```

今後のことを考えて最新のバージョンと8.0系とを切り替えられるように対応します。
切り替えのコマンドは以下です。

```
$ brew unlink mysql && brew link --force mysql@8.0
Unlinking /opt/homebrew/Cellar/mysql/9.2.0... 99 symlinks removed.
Linking /opt/homebrew/Cellar/mysql@8.0/8.0.41... 99 symlinks created.
```

切り替え後にバージョンを確認してみます。

```
$ mysql --version
mysql  Ver 8.0.41 for macos13.7 on arm64 (Homebrew)
```

問題なく切り替えられました！
その後アクセスの確認も行いましたが、特に問題なく今まで通り作業を進められました。

## まとめ
今回はMySQLクライアントのバージョンアップによってサーバ上のDBにアクセスできなくなった際の解決方法についてご紹介しました。
バージョンアップ周りの問題はよく発生するものであり、対応についても都度考える必要があるため、エラーの内容から対応方針を決めて対応するようにしましょう。

## 参考
- [最近のMySQLのデフォルト認証プラグインの変遷とAWS RDS/Auroraの対応状況をまとめた](https://zenn.dev/sasashu/articles/2afd10c1e7244a)

[^1]:そもそもAmazon Auroraが2025年2月時点でMySQL8.0系までしか対応していない
Wolframを強制的にアクティベートし直す

1. 思い切って[`mathpass`ファイル](https://support.wolfram.com/ja/112)を削除する。
2. Wolframを起動するとアクティベーションされていない状態になっているので、[アクティベートする](https://reference.wolfram.com/language/tutorial/ActivatingMathematica.html.ja)。

私の場合はこの方法で「Wolframについて」に表示される登録者情報が修復されました。
[UI][使いやすさ]カレンダーの罠

# 60代(男性)の方からの問い合わせ
とある別案件で実際にあった問い合わせ的なアレ

## とあるWebシステムにて日付項目をカレンダーで入力をするものだったらしいんだけど。。。
> カレンダーの日付入力の仕方がわからず、
> 1200回ほどタップやスワイプをしたところ手首が腱鞘炎のような症状になってしまった

あ～。。。カレンダーによくある「前月ボタン」とかをポチポチしてたのかな？
例：[bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker)（別にこれが悪いとかじゃなくて、あくまでサンプルイメージとしてね
![スクリーンショット 2025-02-21 161240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/d32af730-da39-49f8-b2f8-91c19bada2e0.png)

で、生年月日かなんかを入力したかったのかな？
→12ヶ月 * 60～69年 = 720～828タップ（60代だから）
他にも何かトンデモ昔の日付をいれるところがあったのかな？
→12ヶ月 * 遠い過去 = 手首破壊

## IT屋視点 **「なんだ、このトンデモ言いがかりは!?」** 
IT屋だったり普段からPCやスマホとかで何か入力をしている方とかであれば、
**「いやいや、年が表示されてるなら、そこをタップすれば一気に戻れるやん」**
的な考えになるので、特段意識せずに入力ができてるのかもしれないね。

うん、そうだよね。だいたいのカレンダーのUIって「月や年」をタップすれば、過去の入力楽になるっていう作りが【当たり前】だもんね！
そこに気が付けないなんて、IT弱々ザァコなんだね（炎上必須
![スクリーンショット 2025-02-21 162332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/72d576aa-8116-412a-9474-7e36467fc581.png)


## まぁちょっと待て
IT弱者は腱鞘炎と戦いながら何百回もタップでもしてろや(ﾋｬｯﾊｰ
と突き放してしまうのは簡単だし、このユーザ以外からはそんな問い合わせなんか来ていないので、特に何も対応しない（使い方をお伝えするぐらいはするだろうけど）で済ませる可能性も有るかもしれない。

確かに【普段から】使ってるような方にはそりゃ【当たり前】だから、
そんな問い合わせの優先度は低くなてしまうのも仕方がないと思ったんだけど。。。

そもそも。。。なことに気がついてしまったんだ。

# そんな過去の日付を入力する（可能性のある）箇所にカレンダーって必要なんか？
たとえば、生年月日のような人によっては大分過去を入力する時に【曜日】の情報っている？って話ですよ。
入力してる時に「俺って火曜生まれなんだぁ」みたいな「へぇ～」感覚にはなるだろうけど、情報としてはマジで必要ないよね。

曜日の情報が必要な時って、何かの予約（打ち合わせ・会場・支払 ...etc）だったり、スケジュール関連（TODOリスト・タイムカード ...etc）みたいな、割と直近（1～3年前ぐらい）や未来のデータを登録する時ぐらいしか意識しないような気もしてるんだが、いかがでしょう？

## UI設計・統一という弊害
【サイト・システム内では別機能・画面において同じような見た目で入力できること】と言う、おそらくIT屋やデザイナー屋たちの暗黙のルール的な考えがあり、それを実現するために画面間の見た目を揃えるためのCSSのフレームワークがあります。
※ほら、画面によって見た目の統一感がないと気持ち悪いでしょ？
![スクリーンショット 2025-02-21 172708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/29171808-8b42-433b-8cd2-2efa081359d5.png)

こういったフレームワークなどには日付を入力するためのパーツだったり書き方があったり、それを使わない場合にはブラウザ標準のカレンダーを使ったりするわけですが、このルールが入力を【逆に】困難にさせてしまっているのかなという気がしています。
→日付項目だったら、このパーツ（見た目）を使うことみたいなルールの問題

## 【当たり前】を疑って考えてみないか？
統一された見た目は、確かに見やすいし洗練された感じはするかと思いますが、
それが使いやすいかについてはまた別問題のように考え・扱う必要があるのかなと。
→見た目が良くても中身がペラい人とか残念だと思うでしょ？

今回のカレンダーのように、直近データが入りそうな場所はカレンダーを使い、過去データを入れるような箇所はテキストで入力させるとかの、登録されるデータを元にした配慮があれば60代のおじいちゃんの手首は守られたかもしれないね。

# まぁでも...
そんな1200回もタップ・スワイプしてる間に、誤タップで年の部分とかをタップして気がついてくれないかなぁと言う、残念な気持ちはある（台無し


# 【カナヘビ】皮、剥いでやったわ
久々にカナヘビのドラ・チャンさんの脱皮が始まり、所々脱げてない箇所があったため、主がムキムキしてあげましたわ。
飼い始め（拉致当初）は自分で脱いで、皮も食べて痕跡残さないような感じでしたが、最近は適当に脱ぐし、脱ぎ漏れがあると【脱がせろ】と言わんばかりに手にアタックしてきて「もうコイツ、野生忘れとるやろ」な感じになってきており、大変嬉しいです!!

## こすりつけてヌギヌギしてまちゅね～～～～（偉い!!
![IMG_0082.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/53ee7966-26a2-440a-a9f0-8279ec97b4b4.jpeg)
## 左から手足部分（手袋かわいい）・お腹・首から背中・尻尾の付け根らへんって感じです
![IMG_0084.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/89aaf7ca-b3cc-4791-ae92-96f72f08967c.jpeg)
## 脱いだ後の水分補給（直掛け
![IMG_0085.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996378/d798ce9e-85b3-4c25-9e6e-b9b34f633918.jpeg)
【RockyLinux 9.5 で WordPress 環境構築】Apacheのインストールと設定

RockyLinux9.5でWordPress環境構築した際のメモです。
今回はWebサーバーApacheをインストールし設定します。

## Apacheのインストール

「httpd」「httpd-tools」「mod_ssl」をインストール

```shell
sudo dnf install httpd httpd-tools mod_ssl
```

httpdを起動し、ステータスを確認
```shell
sudo systemctl start httpd
sudo systemctl status httpd
```

サーバを再起動しても自動的に起動するように設定
```
sudo systemctl enable httpd
sudo systemctl is-enabled httpd
```

ブラウザでサイトURL http://xxx.xxx.xxx.xxx (IPアドレス)にアクセスし、Apatchのテストページが表示れていれば成功です。

## ドキュメントルートディレクトリの作成
```
sudo mkdir /var/www/html/yoursite.com
sudo mkdir chown apache.apache /var/www/html/yoursite.com/
```

## 設定ファイル（httpd.conf）の編集

オリジナルをバックアップ
```shell
sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.org
```

vimで開いて編集
```shell
sudo vim /etc/httpd/conf/httpd.conf
```

以下の部分を編集します。

```conf:/etc/httpd/conf/httpd.conf
# ServerName www.example.com:80
↓
ServerName yoursite.com:80
```

```conf:/etc/httpd/conf/httpd.conf
DocumentRoot "/var/www/html"
↓
DocumentRoot "/var/www/html/yoursite.com"
```

```conf:/etc/httpd/conf/httpd.conf
<Directory "/var/www/html">
↓
<Directory "/home/www/html/yoursite.com">
```

```conf:/etc/httpd/conf/httpd.conf
Options Indexes FollowSymLinks
↓
Options FollowSymLinks
```

```conf:/etc/httpd/conf/httpd.conf
Options Indexes FollowSymLinks
↓
Options FollowSymLinks
```

```conf:/etc/httpd/conf/httpd.conf
DirectoryIndex index.html
↓
DirectoryIndex index.php index.html
```

## 設定ファイルの確認

以下のコマンドでエラーが表示される場合、設定ファイルやディレクトリ構成に問題があります。
```shell
sudo httpd -t
```

## Apacheを再起動
```shell
sudo systemctl restart httpd.service
```

## RockyLinux9.5でWordPress環境構築
1. [さくらのVPS設定](https://qiita.com/tfz/items/58a8a185573ff7080599)
1. Apacheのインストールと設定
1. [PHPのインストールと設定](https://qiita.com/tfz/items/9e962e83cf84f4e20c14)
1. [mariaDBのインストールと設定](https://qiita.com/tfz/items/ffb4eaaba2eea68211fe)
1. [WordPressのインストールと設定](https://qiita.com/tfz/items/95b355127e3f034b78bb)
1. [DNS設定とCertbotによるSSL証明書の取得と設定](https://qiita.com/tfz/items/546cc990465b876bc5de)
useSyncExternalStoreを使ってみた

# はじめに

React18以降に、`useSyncExternalStore`というフックが導入されました（[公式ドキュメント](https://ja.react.dev/reference/react/useSyncExternalStore)）。このフックは、外部ストア（ブラウザAPIやサードパーティの状態など）とReactの状態を同期させるためのものだそうです。今回は、これを使ってメディアクエリを扱うカスタムフックを作ってみました。実際に使ってみた感想やコードを共有します！

# 使ってみた

以下が、`useSyncExternalStore`を使った`useMediaQuery`フックのコードです。ウィンドウサイズに応じてメディアクエリを監視し、結果を`boolean`で返します。

```tsx
import { useSyncExternalStore } from "react";

const subscribe = (query: string) => (callback: () => void) => {
  const mediaQueryList = window.matchMedia(query)
  mediaQueryList.addEventListener("change", callback)
  return () => mediaQueryList.removeEventListener("change", callback)
};

const getSnapshot = (query: string) => () => {
  if (typeof window === "undefined") {
    return false // サーバーサイドではfalseを返す
  }

  return window.matchMedia(query).matches;
};

/**
 * コンポーネント表示
 *
 * ```tsx　
 * // in component
 * const isMobile = useMediaQuery('(max-width: 767px)')
 * return <div>{isMobile ? 'モバイル' : 'デスクトップ'}</div>;
 * ```
 */ 
export const useMediaQuery = (query: string): boolean => {
  return useSyncExternalStore(subscribe(query), getSnapshot(query));
};

```

ウィンドウサイズが変わると、`useMediaQuery`が自動的に再評価され、UIが更新されます。

# `subscribe`と`getSnapshot`について
`useSyncExternalStore`を使う上で、2つの関数`subscribe`と`getSnapshot`の役割を理解するのが大事です。それぞれの仕事を整理してみました。

## `subscribe`の役割
- 外部ストア（ここでは`window.matchMedia`）の変更を監視し、変化があったときにReactに通知します。

## `getSnapshot`の役割
- 外部ストアの現在の状態を取得して返します。`subscribe`が変更を検知したときに呼ばれます。今のウィンドウサイズがクエリに該当するかをbooleanで返します
 - **ポイント**: 「今どうなってるか」を答える役割で、監視はしません。

## 役割分担の意味
- **責務の分離**: subscribeが「タイミング」を、getSnapshotが「値」を担当することで、コードがシンプルに
- **効率性**: 変更があったときだけgetSnapshotが呼ばれ、値が変わった場合にのみ再レンダリング
- **柔軟性**: 外部ストアが何であれ、同じパターンで対応可能

簡単に言うと、`subscribe`は「変化をキャッチするセンサー」、`getSnapshot`は「現在の値をチェックするメーター」です。この2つが協力して、外部の状態とReactの表示を同期させています。

# 感想

- **良かった点**: `useSyncExternalStore`を使うと、従来の`useEffect`＋`addEventListener`の手動管理が不要になり、コードがスッキリした。SSR（サーバーサイドレンダリング）対応も簡単に考慮できるのが嬉しい
- **気をつける点**: `subscribe`と`getSnapshot`の役割分担を理解するのが難しかった。公式ドキュメントをじっくり読むと腑に落ちた

# まとめ

`useSyncExternalStore`は、Reactと外部の状態を同期させるのにぴったりのフックだと感じました。メディアクエリ以外にも、WebSocketやブラウザのAPIを使う場面で活躍しそうです。みなさんもぜひ試してみてください！
【RockyLinux 9.5 で WordPress 環境構築】さくらのVPS設定

さくらのVPSでWordPress環境を構築しましたので、構築メモをシェアします。

## さくらのVPS採用理由
長年愛用させてもらっています。費用が安いうえ、近年ではさくらインターネットのクラウドサービスが国家基盤に採用されており、長期的に安心して利用し続けられるメリットがあります。

## RockyLinux採用理由
もともとCentOS7でWordPressを運用していたのですが、知らぬうちにCentOSが終了となっていました。CentOSを継承するAlmaLinuxとRockyLinuxという2つの派閥があるとのことです。ChatGPT先生的には、AlmaLinuxのほうが企業がバックについているため安心感があるとのことでしたが、さくらのVPSの申し込みページでは、デフォルトでRockyLinuxが選択されていました。特にこだわりがなかったので、こちらを採用することに。

## システム構成
- RockyLinux 9.5
- 仮想CPU 2Core
- メモリ1GB
- SSD 50GB


- PHP 8.2.27
- mariaDB 10.5.27
- WordPress 6.7.2

## 初期設定
「パケットフィルター設定」でWebとSSHのポートを許可します。

公式マニュアルに従い、セキュリティに関する初期設定を行います。

https://manual.sakura.ad.jp/vps/support/security/firstsecurity.html

## おまじない

vimのインストール

```shell
sudo dnf -y install vim-enhanced
```

タイムゾーンの設定
```shell
sudo timedatectl set-timezone Asia/Tokyo
```

remi リポジトリのインポート
```shell
sudo dnf config-manager --set-enabled crb
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm
sudo dnf install dnf-utils http://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf repolist 
```

## RockyLinux9.5でWordPress環境構築
1. さくらのVPS設定
1. [Apacheのインストールと設定](https://qiita.com/tfz/items/f4d74b8a5d93068fe675)
1. [PHPのインストールと設定](https://qiita.com/tfz/items/9e962e83cf84f4e20c14)
1. [mariaDBのインストールと設定](https://qiita.com/tfz/items/ffb4eaaba2eea68211fe)
1. [WordPressのインストールと設定](https://qiita.com/tfz/items/95b355127e3f034b78bb)
1. [DNS設定とCertbotによるSSL証明書の取得と設定](https://qiita.com/tfz/items/546cc990465b876bc5de)
RHEL9のパケットフィルタリング

firewalldを使用したパケットフィルタリング。
## firewalldの有効確認
以下コマンドを使用し、有効になっていることを確認した。
```
systemctl status firewalld
```
## 永続的にTCPポート解放
ファイル転送ソフトに設定したTCPポートを解放するため、以下のコマンドを入力。
```
firewall-cmd --zone=public --add-port=30000/tcp --permanent
firewall-cmd --zone=public --add-port=31000/tcp --permanent
firewall-cmd --zone=public --add-port=65535/tcp --permanent
firewall-cmd --zone=public --add-port=30001/tcp --permanent
firewall-cmd --zone=public --add-port=31001/tcp --permanent
firewall-cmd --zone=public --add-port=65534/tcp --permanent
```
その後、設定を反映。
```
firewall-cmd --reload
```
## TCPポートの状態確認
リロード後に許可されているかを確認する。
```
firewall-cmd --list-all
```
出力結果より先のコマンドで記述したポートが許可されていることを確認した。
```
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  services: cockpit dhcpv6-client http https ssh
  ports: 30000/tcp 31000/tcp 65535/tcp 30001/tcp 31001/tcp 65534/tcp 
  protocols: 
  ...
  ```
  念のため、/etc/firewalld/zones/public.xmlも確認、反映されていたためよしとした。
標本統計量、母数、不偏推定量の記号と式について

## はじめに
標本統計量、母数、不偏推定量の記号と式についてまとめてみました。

## 記号
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/f4a69ee4-5d2d-4631-bc19-ae08fc52f611.png)

## 式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/ab18c689-a525-4b2a-990f-8d4b874c3239.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/706b617b-3999-4e8b-95d9-48fe4a508128.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/612e8775-b8f7-48fb-80fe-03316063aff9.png)

## おわりに
ここまで読んでいただきありがとうございます！
Windows10,11の日本語化（オフライン環境）

# 初めに
AzureでWinodows環境を構築するときに、デフォルトが英語なので日本語にする方法を記載しています。
特にオフライン環境ではインターネット経由で簡単に日本語にするのが難しいので、参考になればと思います。

# 前提
- Visual Studio Subscriptionを持っていること。もしくは、日本語用の言語パック（拡張子が.cab）を持っていること

# 手順
1. Visual Studio Subscriptionにサインインする（[https://visualstudio.microsoft.com/ja/subscriptions/](https://visualstudio.microsoft.com/ja/subscriptions/)）
2. 「ダウンロードとプロダクトキー」のページから、仮想サーバーと同じバージョンの言語パックをダウンロードする。
例：Windows11 24h2の場合は、"Languages and Optional Features for Windows 11, version 24H2"をダウンロードする。
    ```powershell
    # Windowsのバージョンを調べたい場合は、パワーシェルで以下を実行
    Winver
    ```
3. 言語パック（例：mul_languages_and_optional_features_for_windows_11_version_24h2_x64_dvd_eb44bee0.iso）を仮想サーバーのどこでもいいので配置する 
4. 3をダブルクリックする
5. 言語パックをインストールする。以下のコマンドを管理者権限で実行する。
    ```powershell
    # 以下はWindowsのプロセッサがAMD64の場合の例。
    # パスはwindowsのプロセッサや言語に合わせて変える必要がある。
    dism /online /add-package /packagePath:"F:\Windows Preinstallation Environment\x64\WinPE_OCs\ja-jp\lp.cab"
    ```
6. シャットダウンをする
7. Windowsの設定からJapaneseが選べるはずなので変更する
ESP32: アクセスポイントにする

こちらの記事と同様のことを行いました。
[ESP32とPCで通信してみよう！~SoftAP編~](https://note.com/yukuyuku_4123/n/n6d8157d24be9)

Arduino IDE 2.3.4 を使いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f26f63b9-c09f-4ac6-9f63-d96040ef3e25.png)

## プログラム

```text:ssid01.ino
#include <WiFi.h>

const char *ssid = "ESP32_AP";
const char *password = "1234";

WiFiServer server(8000);

void setup() {
  Serial.begin(115200);
  
  // WiFiネットワークを作成
  WiFi.softAP(ssid, password);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);
  delay(2000);

  server.begin(); // サーバーを起動
  Serial.print("AP IP address: ");
  Serial.println(IP);
  delay(2000);
}

void loop() {
  WiFiClient client = server.available(); // 接続の待機

  if (client) { // 接続されたとき
    Serial.println("New Client.");
    
    while (client.connected()) { // 接続されている間はデータの受信を続ける
      if (client.available()) {
        String request = client.readStringUntil('\r'); // リクエストの読み込み
        Serial.println("Received: " + request);
        
        // レスポンス
        client.println("Received: " + request);
        delay(1);
        client.stop(); // 接続を閉じる
        Serial.println("Client disconnected.");
      }
    }
  }
}
```

何故か SSID が　ESP_660449 になります。

## 接続テスト

テストに使う　python のプログラム

```py:test01.py
#! /usr/bin/python

import socket

# ESP32のIPアドレス
esp32_ip = "192.168.4.1"
port = 8000

# ESP32に接続
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((esp32_ip, port))

# 送信する文字列
message = input("送る文字列を入力\n")

# ESP32にデータを送信
client.sendall(message.encode())

# データを受信して表示
response = client.recv(4096)
print(response.decode())

# 接続を閉じる
client.close()
```

## テスト方法

パソコンを ESP_660449 に接続する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8b1b14f2-ae2d-45fa-bfa5-73eb57ae6ad9.png)


Python のプログラムを実行する

```text
$ ./test01.py 
送る文字列を入力
Good Morning
Received: Good Morning
```

ESP32 シリアルモニターの表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1f18143b-75d3-46c3-ba95-31312989e5ff.png)