OmniAICreator/Qiita-1.07M huggingface dataset:
【Windows11】"このwindowsdefenderリンクを開くには新しいアプリが必要です"という画面が出てきたときの解決方法

## 発生した問題の詳細
### Windowsセキュリティを開けない
[Windowsキー]->[設定]->[プライバシーとセキュリティ]に移動。  
![354ee6884b45835b198bc97cf5f91130bf94fa91286a94f1ca292629fb0b2c53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/e3902482-fe86-e615-f647-3b30b3136435.png)
"Windowsセキュリティを開く"や"ウイルスと脅威の防止"をクリック。  
しかし、以下のポップアップが表示され、所望のページに移動できません。  
![c17d83b1ed7a985000059f4c5e2964bda56aa7b041878e5dcfaf843208a4cdab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/c1e286ee-7c98-74cf-0439-65cc3f1a1522.png)
Microsoft Storeでアプリを探すをクリックしても"windowsdefenderは見つかりませんでした"という画面に移動するだけでした。  


## 解決方法
管理者にてwindows PowerShellに以下を実行すると解決できそうです[[参考サイト](https://www.kaias1jp.com/entry/2021/10/05/123600)]。

```
Get-AppxPackage Microsoft.SecHealthUI -AllUsers | Reset-AppxPackage
```

![ca04708e8e41f55fe204b78a73b222f304bea89ae49f887fda92cc08a1f236a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/9217b19d-f525-0bf3-1bff-62a849d6c5a0.png)


ただ僕の場合は上記の方法では解決できないようでした。  

赤字の文章を読むとReset-AppxPackageパッケージをインストールする必要がありそうです。
```
# 赤文字部分
Reset-AppxPackage : パッケージが見つかりませんでした。
Microsoft.SecHealthUI_1000.22000.1.0_neutral__8wekyb3d8bbwe を削除できません。
このパッケージは現 在のユーザーによってインストールされていません。
Get-AppxPackage を使用して、インストール済みのパッケージの一覧を確認してください。
発生場所 行:1 文字:51
+ Get-AppxPackage Microsoft.SecHealthUI -AllUsers | Reset-AppxPackage
+                                                   ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Reset-AppxPackage], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.Windows.App
   x.PackageManager.Commands.ResetAppxPackageCommand
```


追加で[調査](https://answers.microsoft.com/ja-jp/windows/forum/all/windows%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA/d14e7112-95f9-4787-823c-3c3a5bb0b1e9)し、Windows PowerShell(管理者)にて、


```
Get-AppxPackage -allusers *Microsoft.SecHealthUI* | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}
```

を実行してみました。
![d117d7dc88ab7eb6352f681c2f044ea0b3025f46eada8580a93e908c6ae855b1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/b44208a0-ebdf-49f9-3c08-38eb6edad478.png)
 
確認のためもう一度下記を実行してみます。  
```
Get-AppxPackage Microsoft.SecHealthUI -AllUsers | Reset-AppxPackage
```
成功したみたいなので、Windowsセキュリティを開いてみようと思います。  
[Windowsキー]->[設定]->[プライバシーとセキュリティ]に移動し、
![354ee6884b45835b198bc97cf5f91130bf94fa91286a94f1ca292629fb0b2c53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/9be38f8c-e5d1-0c28-cdba-b19ba2c8ab71.png)
"ウイルスと脅威の防止"をクリック。
![87a23813ab610e34ef8ac2d56cd86c80766c52c7f10a53f68b5949eb1d40a17e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1407933/c2b52b29-5fca-9bff-a1b2-bf5e56010f0b.png)
無事開くことができました。
SAPシステムインストール時の/etc/hostsの書き方

SAPシステムインストール時のOS設定です。
DNSで名前解決していることも多いですが、
うまく名前解決できてない場合は、hostsを使いましょう。

ファイルの場所は、下記です。
>Windows："C:\Windows\System32\drivers\etc\hosts"
>Unix/Linux: /etc/hosts

記載方法ですが、順番が重要で、
左から、IPアドレス、FQDN、ホスト名の順で書きます。
~~~
192.168.10.1    hostA.beex.local    hostA
192.168.10.2    hostB.beex.local    hostB
192.168.10.3    hostC.beex.local    hostC
~~~

962955 - Use of virtual or logical TCP/IP host names
2936683 - Oracle Linux 8: SAP Installation and Upgrade
2772999 - Red Hat Enterprise Linux 8.x: Installation and Configuration
RailsアプリケーションをCloudRunで動かしてみるまで

# ゴール
* Cloud Run でRailsアプリケーションを動かせるようにする。
* ローカルからContainerRegistryにコンテナをPushし、そこからCloudRunにコマンドでデプロイする。


# 実行環境
* Ruby
  * 3.1.2
* Ruby on Rails
  * 7

持病の関係で1年ほどブランクがあり、仕事に戻るため知識を取り戻す&Dockerをそれなりに使えるようにするために、RailsアプリケーションをCloudRunにデプロイする方法をまとめてみました。


# Railsアプリケーション
* 今回はDB周りは無視したいので、 `--skip-active-record` で `rails new` します。
* またこの記事はRailsアプリケーションの開発が目的ではないので、アクセスするとただ文字列が表示されるだけのRailsアプリを用意します(Railsじゃなくてもw)

## 準備
* `$ rails _7.0.3_ new --skip-active-record kaesudake `
* `$ bundle exec rails g controller tops index`


```ruby:config/route.rb
root 'tops#index'
```

```ruby:app/controllers/tops_controller.rb
class TopsController < ApplicationController
  def index; end
end
```

```erb:app/views/tops/index.html.erb
<h1>Hello 返すだけ！！</h1>
```

# Dockerfile, docker-compose.yml, build-docker.sh

Cloud Run はデフォルトでリッスンするポートは `8080` のようなので、 `8080` に指定します。(もちろん変えれます)

```Dockerfile:Dockerfile
FROM ruby:3.1.2

RUN mkdir /app
WORKDIR /app

COPY . /app

RUN gem install bundler & \
    bundle install

ENTRYPOINT ["/bin/sh", "-c"]

CMD ["rm tmp/pids/server.pid; bin/rails assets:precompile && bin/rails s -p ${PORT}"]
```

```yml:docker-compose.yml
version: "3.8"
services:
  app:
    image: kaesudake
    ports:
      - 8080:8080
    stdin_open: true
    tty: true
    environment:
      PORT: 8080
    volumes:
      - .:/app
```

```sh:build-docker.sh
docker build --no-cache -t kaesudake .
```

# イメージの作成
私はzshを使っているので、下記コマンドを実行して、イメージを作成します。

```zsh
zsh build-docker.sh
```

# Artifact Registry に Push
GCPのArtifactRegistryにimageをPushします。
その前に コマンドラインツールのgcloudをセットアップします。
セットアップ方法は [公式ドキュメント](https://cloud.google.com/sdk/docs/install?hl=ja#installation_instructions) をご参照ください。

```zsh
docker tag kaesudake <ArtifactRegistryのURL>/kaesudake
docker push <ArtifactRegistryのURL>/kaesudake
```

# ArtifactRegistryのイメージを利用してCloudRunにデプロイ
先ほどArtifacｔRegistryにPushしたイメージを利用して、CloudRunにコンテナをデプロイします。
コンソールに未認証のリクエストを許可するかどうかを尋ねるプロンプトがでるので、今回は `y` を選択します。未認証のリクエストを許可すると、誰でもアクセスできるようになります。

```sh
gcloud run deploy --image <ArtifactRegistryのURL>/kaesudake
```

処理が完了すると、最後に `Service URL` が表示されるので、そのURLにアクセスすると、Railsアプリの `root` にアクセスできます。

今回は以上です。
次はCloudSQLと接続したRailsアプリをCloudRunにデプロイできるようにしてみたいと思います。
Kindle蔵書一覧を出力するツール作成時の工夫

# 成果物概要
Kindlist
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/226bb20c-9f8c-0e7c-c829-6b4c28f1e04a.png" alt="Kindlistアイコン" title="Kindlistアイコン" width="250">
Kindle for PCのXMLファイルを解析して、Excel形式に変換する機能を提供します。
書籍一覧が記載されたExcelファイルを、Kindle書籍管理にご活用下さい。
<a href="https://www.vector.co.jp/soft/winnt/util/se523241.html" target="_blank">Vector</a>よりダウンロードが可能です。

# :tada::tada::tada: お知らせ :tada::tada::tada:
窓の杜にてご紹介頂きました！
<a href="https://forest.watch.impress.co.jp/docs/review/1417161.html" target="_blank">Kindleで購入済みの電子書籍をExcelで管理するには？ 簡単にXLSX形式に変換できるツール</a>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/38822e84-74da-46cd-d952-2a4871532bfa.jpeg" width="900px">


# 画面イメージ
![KindlistMain.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/4a981833-ac51-6fc3-5a1d-feace1d60bc5.jpeg)
![VerInfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/3b11d2a4-b384-68d8-5fbc-0a5fe40750c7.png)


# 動作に必要なソフト
<a href="https://dotnet.microsoft.com/ja-jp/download/dotnet/thank-you/runtime-desktop-6.0.4-windows-x64-installer" target="_blank">.NET Desktop Runtime 6.0.4 (x64)</a>以降
Kindle for PC (またはKindleSyncMetadataCache.xml)

# 使い方
基本は「Kindlist.exe」を起動して「変換」ボタンを押すだけ。
詳細は<a href="https://note.com/tsukasa_labz/n/ndf065a8538d0" target="_blank">note</a>または付属のReadmeをご参照ください。

# 技術情報
開発はVisual Studio 2022とC#で行っています。
XMLを解析してKindleInfoという独自クラスに書籍情報を設定しています。
KindleInfoのListに設定した内容をClosedXMLを使用してExcel形式で出力しています。
この辺りは特筆すべきことは無いと思います。

# 困ったこと
取得した書籍情報を書籍名順でソートし、Excel出力したところ以下のようになってしまいました。
![old.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/f2439c84-87bf-abe8-e010-1cd97ac80675.jpeg)
本来は1、2、3 ･･･ 9、10、11、12 ･･･と並んで欲しいところ。
実際には1、10、11、12 ･･･ 16、2、3と並んでしまいました。
これはプログラム言語(C#)標準のソート機能を利用しているため、仕様通りとなります。
しかし今回は蔵書管理を行いため、自然順(エクスプローラ順)ソートを行う方法を調べてみました。

# 対応内容
独自に自然順ソートを実装している強者の方もいらっしゃいましたが
今回は<a href="https://docs.microsoft.com/ja-jp/windows/win32/api/shlwapi/nf-shlwapi-strcmplogicalw" target="_blank">StrCmpLogicalW</a>というWindows APIを呼び出す方法を採用しました。


```C#:NaturalSortComparer.cs
/// <summary>
/// 自然順で文字列比較
/// </summary>
public class NaturalSortComparer : IComparer, IComparer<string>
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int StrCmpLogicalW(string x, string y);

    public int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }

    public int Compare(object x, object y)
    {
        return this.Compare(x.ToString(), y.ToString());
    }
}
```

これにより最小限の実装で、書籍名が自然順(エクスプローラ順)にソートできるようになりました。
![new.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229681/88f04198-2079-3964-802b-f5f41200d811.jpeg)

# スペシャルサンクス
アイコン制作：みなみ様
命名：みなみ様
広報：<a href="https://twitter.com/suikasu123" target="_blank">すいか</a>様

# 感想
普段はあまり意識していませんでしたが、エクスプローラのソート順というのは非常に優秀なんだと実感しました。

# 参考情報
<a href="https://qiita.com/taka_hira/items/8a9181c0733de2c9f8ee" target="_blank">Kindle蔵書一覧を取得する方法</a>の記事と<a href="https://qiita.com/taka_hira/items/8a9181c0733de2c9f8ee#comment-b9071ac2bc7e91f482f6" target="_blank">@error_401</a>さんのコメントを参考にさせて頂きました。
【Flutter】結局、url_launcherはどう実装すべきなのか。 


[_url_launcher_](https://pub.dev/packages/url_launcher) を 6.0.20 -> 6.1.2 にアップしたところ `launch` と `canLaunch` が Deprecated になっていたため書き直したが、挙動が変わったため修正。

#### 元のコード

```dart
  await canLaunch("アプリのカスタムURLスキーム")
    ? await launch("アプリのカスタムURLスキーム")
    : await launch("ウェブのURL");
```

このコードに問題があったことは認識していて、Androidの場合、特定のアプリにおいては想定している経路では処理されていない。

`twitter` などのURLスキームはアプリをインストールして必要な設定をしても `canLaunch` が _false_ を返してくる場合があり、ウェブブラウザでURLを起動される。
結果的に、ディープリンクとしてサポートしているアプリが起動されていた。

そのため、`canLaunch` を使用せずに、`try` `catch` で実装していたこともあったが最近は `canLaunch` を使用していた。

#### 書き直したが挙動が変わってしまったコード

```dart
  await canLaunchUrlString("アプリのカスタムURLスキーム")
    ? await launchUrlString("アプリのカスタムURLスキーム")
    : await launchUrlString("ウェブのURL");
```

どうやら、起動モードなどの引数を省略した場合、該当の URL を WebView で表示するようになってしまったようだ。

引数などを設定することも考えたが、ドキュメントに以下の記述があった。

[Checking supported schemes](https://pub.dev/packages/url_launcher#checking-supported-schemes)
> However, canLaunchUrl can return false even if launchUrl would work in some circumstances (in web applications, on mobile without the necessary configuration as described above, etc.), so in cases where you can provide fallback behavior it is better to use launchUrl directly and handle failure. For example, a UI button that would have sent feedback email using a mailto URL might instead open a web-based feedback form using an https URL on failure, rather than disabling the button if canLaunchUrl returns false for mailto.

ということで、　`try` `catch`　で実装することにした。

#### 修正したコード

```dart
  try {
    var launched = await launchUrlString("アプリのカスタムURLスキーム");
    if (!launched) {
      await launchUrlString("ウェブのURL");
    }
  } catch (e) {
    await launchUrlString("ウェブのURL");
  }
```

これ、 `catch` しているのは、Android で起動が失敗している場合の対応で、 `launched` で判断しているのが iOS で起動が失敗している場合の対応。。。
Docker 環境で Laravel を動かしたらエラーが発生した話

# Docker 環境の Laravel でエラー

Rocky Linux の Docker 環境に入れた Laravel を起動してブラウザから開くとエラーが発生。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/c42749a9-813a-44d1-7967-2fd3c8dc7277.png)

ログファイルを append mode でオープンできないようです。

```
The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: 
Failed to open stream: 
Permission denied The exception occurred while attempting to log: 
```

Docker コンテナが参照しているホスト側ディレクトリの所有者を確認。root が所有者となっています。コンテナ内からは sail ユーザーでアクセスしているので書き込みできません。

```bash
# ls -al [project_dir]/storage/
合計 4
drwxr-xr-x.  5 root root   46  5月 18 13:43 .
drwxr-xr-x. 13 root root 4096  5月 18 13:35 ..
drwxr-xr-x.  3 root root   38  5月  6 04:52 app
drwxr-xr-x.  6 root root   81  5月  6 04:52 framework
drwxr-xr-x.  2 root root   43  5月 18 14:24 logs
```

# 対策（非推奨）

以下、全てホスト側からの操作となります

コンテナ名を調べる（NAMES列）

```bash
$ docker ps
```

コンテナ内の sail ユーザーの UID を調べる

```bash
$ docker exec -it [コンテナ名] /usr/bin/grep sail /etc/passwd
sail:x:[UID]:0::/home/sail:/bin/bash
```

storage ディレクトリの所有者を sail に変更する

```bash
$ chown [UID] [project_dir]/storage/ -R
```

※logs ディレクトリだけ所有者変更すると後ほど別のエラーも発生するので上位の storage ディレクトリから変更しました

# 対策（推奨）

テスト環境ということで root ユーザーにてコンテナの作成 `curl -s "https://laravel.build/example-app" | bash` をしていたのが良くなかったようです。

**一般ユーザーで環境を作り直すことでエラーが出なくなりました！！**

一般ユーザーですと`コンテナ内の sail ユーザーの UID はホストのユーザーの UID と同じものがセット`されます。これで同じ所有者となるため storage/logs に読み書きが可能となります。

なぜ root ユーザーが NG なのか？

ホストで root ユーザーにて Laravel の Docker コンテナを作るスクリプトを実行
↓
上記スクリプトでコンテナに sail ユーザーを作成するが、このときホストのユーザーの UID と同じものをセットしようとする
↓
ところがホストのユーザー（root）の UID は 0
↓
これはコンテナ内の root でも割り当て済みなので使えない。そのため他の UID をセットする
↓
結果、コンテナの sail ユーザーの UID がホストのユーザーの UID と異なってしまい、参照先ディレクトリの所有者とみなされず書き込み権限が与えられない

# 動作確認

再度ブラウザからアクセスすると正常に Laravel のページが表示されるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83224/a2c2f9ff-1881-e14c-4b57-0067923e3aaf.png)

# sail ユーザーとは

コンテナ内のプロセスを確認してみると PHP の Web サーバーを起動しているプロセスの所有者は sail であることが分かりました。
そのため storage ディレクトなどに sail ユーザーが読み書きできる権限が必要となるのです。
環境によっては sail とは異なるユーザーで PHP が動作している可能性もありますので、ユーザー名は適宜確認してみてください。

```bash
docker exec -it [コンテナ名] /bin/ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1   4360  3216 ?        Ss   05:13   0:00 bash /usr/loc
root          10  0.0  1.1  33144 22232 ?        S    05:13   0:00 /usr/bin/pyth
sail          11  0.0  2.7 123196 50172 ?        S    05:13   0:01 /usr/bin/php 
sail          18  0.0  2.8 236460 52948 ?        S    05:13   0:01 /usr/bin/php8
root          87  0.0  0.0   7060  1588 pts/0    Rs+  06:00   0:00 /bin/ps -aux
```
【GitHub】リポジトリの複製時にでたエラーについて

複製は[公式ドキュメント](https://docs.github.com/en/repositories/creating-and-managing-repositories/duplicating-a-repository)に記載されている方法を使用します。

この問題はゆめみさんのコードチェック課題を複製しようとして起きた問題なので実際に[こちら](https://github.com/yumemi-inc/ios-engineer-codecheck)のリポジトリを例にします

# リポジトリのベアクローンを作成
```
$ git clone --bare https://github.com/yumemi-inc/ios-engineer-codecheck.git
```
![スクリーンショット 2022-05-18 14.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/34a6e32a-3fe9-677f-eed1-1a22d5f652f5.png)
ベアクローンを作成が完了しました

# 新しいリポジトリにミラープッシュ
作成したベアクローンに移動します
```
$ cd ios-engineer-codecheck.git
```

ここでGitHubで新しいリポジトリを作成します。
今回は適当にサンプルを作りました。
![スクリーンショット 2022-05-18 14.59.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/620c75fa-3c3d-c7d3-9465-fdf843fc18a3.png)

```
$ git push --mirror https://github.com/SNQ-2001/Sample.git
```
**ここでエラーが発生しました。**
![スクリーンショット 2022-05-18 15.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e7225f49-2268-c1bd-ad62-f7407f0b2d90.png)

エラー文
```
 ! [remote rejected] main -> main (refusing to allow a Personal Access Token to create or update workflow `.github/workflows/copy-issues.yml` without `workflow` scope)
error: failed to push some refs to 'https://github.com/SNQ-2001/Sample.git'
```

# 原因
「workflowを作成する権限がないよ」とのことです。

# 解決策
Personal Access Tokenでworkflowにチェックを入れます。

![スクリーンショット 2022-05-18 15.11.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ed65a5ca-f6d0-464d-c715-e99305455af2.png)

![スクリーンショット 2022-05-18 15.12.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c1aade2e-f3c1-3dc0-046e-a3325bb296ef.png)

![スクリーンショット 2022-05-18 15.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/f52a620c-af6b-6ad3-f000-d3b7146e1a18.png)

自分がコマンドラインに登録しているトークンに入ります。
![スクリーンショット 2022-05-18 15.13.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e0eee675-07dc-3ca2-cb31-d807dae99162.png)

![スクリーンショット 2022-05-18 15.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4ec8241d-5042-6f89-5552-bca4b9700c00.png)

# 改めて実行してみる
成功！！
![スクリーンショット 2022-05-18 15.17.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1ad34536-ba74-d934-9bc3-e95d389376d8.png)

ちゃんと複製もできてます
![スクリーンショット 2022-05-18 15.18.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b9994942-eeaf-b291-b62c-cf07e18aea3d.png)

# おわり
権限関係ややこしやー
nRF SDK:今さらPPIというものを理解する

# PPIとは
今回は珍しく旧SDK(nRF5 SDK)の話です。(もちろんnRF Connect SDKにもありますがそれは後ほど)
PPIというのはProgrammable Peripheral Interconnectの略です。具体的にはペリフェラル同士の割り込みを結び付けてCPUを介さずにペリフェラルを動かすというもので、この程度の説明はたしかマニュアルにも書かれていたような気がするのですが、ぶっちゃけ何のことかさっぱり分かっていませんでした。色んなCPUを触っていますが、おそらく他のCPUにはこんな機能はないと思います。

:::note
他のCPUにないというのが何のことか理解できなかった理由ということで・・・
:::

## でも・・・
そうは言ってみたところで、正直なところ具体的に何に使えばいいのか分からない・・・そりゃそうですよね。他のCPUではそんな機能がないのでそんなのすぐに使えって言っても無理があります。
と思ったところでそういえば誰かが過去にPPIのことを書いているのでは？と思って調べてみたら・・・ありました。

https://qiita.com/yosukek/items/ca0c202bf52c220e48fc

まさにこれです。ここではGPIO(入力)→TIMER(出力)ですが、これはなんでもかまいません。例えば私が作ったサンプルだと以下のようにTIMER(入力)→GPIO(出力)です。

```main.c
    // Timer
    ret_code_t err_code;
    uint32_t time_ticks;
    nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;

    // Configure timer1
    err_code = nrfx_timer_init(&m_timer1, &timer_cfg, timer_event_handler);
    APP_ERROR_CHECK(err_code);
    // Set timer interval
    time_ticks = nrfx_timer_ms_to_ticks(&m_timer1, 100);
    nrfx_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);

    // GPIOTE Handler
    if (!nrfx_gpiote_is_init())
    {
        err_code = nrfx_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }

    // Output
    nrfx_gpiote_out_config_t const out_config = {
        .action = NRF_GPIOTE_POLARITY_TOGGLE,
        .init_state = 1,
        .task_pin = true,
    };

    err_code = nrfx_gpiote_out_init(BSP_LED_0, &out_config);
    APP_ERROR_CHECK(err_code);

    nrfx_gpiote_out_task_enable(BSP_LED_0);

    // PPI
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_ppi_channel_t channel;
    err_code = nrfx_ppi_channel_alloc(&channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_assign(channel,
        nrfx_timer_compare_event_address_get(&m_timer1, NRF_TIMER_CC_CHANNEL1),
        nrfx_gpiote_out_task_addr_get(BSP_LED_0));
    APP_ERROR_CHECK(err_code);

    /* Enable (D)PPI channel. */
    err_code = nrfx_ppi_channel_enable(channel);
    APP_ERROR_CHECK(err_code);

    nrfx_timer_enable(&m_timer1);
```

上記のサンプル(メイン部分だけ抜粋)を動かすと500ミリ秒毎にLEDが点いたり消えたりします。飛び先の関数としてtimer_event_handlerを指定していますが実際に飛ばす必要はありませんし、実際に飛んだ先の関数内には何も記述していません。(ので記載を省略しています)
マイクロオーダーのタイマーイベントでI/Oを制御しようとすると割り込み待ちでずれてしまうことも多々あります。そういう場合にCPUを介さずに制御することでそういった遅延をなくすことができます。また、おそらくですが消費電力も少なくなります。
# 実はPPIのサンプルは存在している
ちゃんと理解せずに使っていたので気が付きませんでしたが、実はPPIを使ったサンプルというのは最初から用意されています。A/D変換(saadc)のサンプルです。しっかり読むとPPIを使ってTIMER(入力)→SAADC(出力)という制御をしています。

:::note
コピペで使っていたので何をしているのか全く理解していなかったのさ。てへぺろ
:::
# まとめ
操作して動かす場合はGPIOによるPPIを、一定間隔で繰り返すものはTIMERでのPPIを組んで積極的にCPU負荷(と消費電力)を減らしていきましょう。
Rails 検索機能を実装する

### １、ransackのgemをインストール
```gemfile
gem 'ransack'
```

### ２、アクションに検索処理を実装
```boards_controller.rb
def index
  @boards = Board.page(params[:page]).includes(:user)
  @q = Board.ransack(params[:q])
  @results = @q.result
end
```
params[:q]には実際に検索した値がデータとしてが入っている。
ransackメソッドは引数に渡した値を元にDBからデータを抽出している。
resultメソッドはransackメソッドで検索した内容をActiveRecordのオブジェクトに変換する。

### ３、検索フォームを作成する。
```_search.html.erb
<%= search_form_for @q, url: url do |f| %>
  <%= f.search_field :title_or_body_cont,class:'form-control', placeholder:"検索ワード" %>
  <%= f.submit "検索", class: 'btn btn-primary' %>
<% end %>
```
ransackジェムにより```search_form_for```メソッドが使えるようになる。
```search_form_for @q```はフォームに入力した検索ワードをindexアクション内のparams[:q]として@qに送っている。
```title_or_body_cont```はtitleとbodyから完全一致という意味である。（https://pikawaka.com/rails/ransack#_contメソッド）

###　参考にしたURL
https://pikawaka.com/rails/ransack#_contメソッド
【python】S3上のcsvファイルから、dynamoDBにデータをインポートするAWS lambdaのサンプルコード

こちらでスプレッドシートをcsvに変換してS3に保存したので、csvからdynamoDBのテーブルを作成しました。

https://qiita.com/at_sushi/items/8b71927e72ac2a7465d5

サンプルコード
-

```python
import os
import boto3
import pandas as pd

s3_client = boto3.client("s3")
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("任意のテーブル名")


def lambda_handler(event, context):
    bucket_name = os.environ['bucket_name']
    prefix = os.environ['prefix']

    s3 = boto3.client('s3')
    obj = s3.get_object(Bucket=bucket_name, Key=prefix)
    df = pd.read_csv(obj['Body'], dtype='object')

    for index, item in df.iterrows():
        try:
            table.put_item(
                Item = {
                    "foo"  : str(item['foo']),
                    "bar"  : str(item['bar']),
                    "baz"  : str(item['baz'])
                }
            )
        except Exception as e:
            print(e)

```

※ 実行するたびにテーブルが上書きされます
ターミナルでマウスでクリックしたりドラッグしたりすると変な文字が表示される問題

## 問題背景
ある日突然ターミナル状で作業をしているとターミナル画面をクリックしたりドラッグしてコピーしようとすると変な文字が表示されるようになる。
```shell
****@****MacBook-Pro-2 ~ %  <ffffffff>N#<ffffffff>N
zsh: no matches found: ?N#?N
****@****MacBook-Pro-2 ~ %   
```
## 解決策
'マウスレポーティングを許可'という項目にチェックがついている可能性があるのでそのチェックをはずす。

![スクリーンショット 2022-05-18 14.58.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47662/6d8e518e-17f6-86db-fe0c-efb4fd33adc7.png)

無事元に戻りました。
それにしてもマウスレポーティングとはなんなのでしょう。調べてもあんまり記事は出てきませんがマウスのイベントを表示されるかどうかを変更するのかな？
Git の補完が brew 版と MacOS 版で違う

# つまり……

MacOS の標準の Git の補完を使うことにした
→ と思ったけどやっぱり新しい方を使うことにした

## やったこと

```shell-session
$ cp /usr/local/Cellar/git/2.36.0/share/zsh/site-functions/* ~/.zfunctions/Completion/.
```

## なにかが足りない

```
$ git push -[TAB]
```

で補完できなかったりしたので，気になって見てみた

```
$ echo $fpath
/usr/local/share/zsh/site-functions /usr/share/zsh/site-functions /usr/share/zsh/5.8/functions
```

brew を先に見てるようだった

```
$ ls -l /usr/local/share/zsh/site-functions/_git
/usr/local/share/zsh/site-functions/_git -> ../../../Cellar/git/2.36.0/share/zsh/site-functions/_git
$ ls /usr/share/zsh/5.8/functions/_git
/usr/share/zsh/5.8/functions/_git
```

## 中身結構違う

```
$ head /usr/local/share/zsh/site-functions/_git.a
#compdef git gitk

# zsh completion wrapper for git
#
# Copyright (c) 2012-2020 Felipe Contreras <felipe.contreras@gmail.com>
#
# The recommended way to install this script is to make a copy of it as a
# file named '_git' inside any directory in your fpath.
#
# For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git',
$ head /usr/share/zsh/5.8/functions/_git
#compdef git git-cvsserver git-receive-pack git-upload-archive git-upload-pack git-shell gitk tig

# Some parts of this completion's behaviour are configurable:
#
# Say you got your own git sub-commands (git will run a program `git-foo'
# when you run "git foo") and you want "git f<tab>" to complete that sub
# commands name for you. You can make that sub-command known to the completion
# via the user-command style:
#
#     % zstyle ':completion:*:*:git:*' user-commands foo:'description for foo'
```

試しに，brew 版を使わないようにしたら上記補完できたのでこちらにすると良さそう．

```
$ mv /usr/local/share/zsh/site-functions/_git /usr/local/share/zsh/site-functions/_git.a

$ git push -
not a git repository
option
--all                          -- push all refs under refs/heads/
--atomic                       -- request atomic transaction on remote side
--delete               -d      -- delete all listed refs from the remote repository
(snip)
```

## そもそも

```
$ where git
/usr/local/bin/git
/usr/bin/git
$ /usr/local/bin/git --version
git version 2.36.0
$ /usr/bin/git --version
git version 2.32.0 (Apple Git-132)
```

あまり変わらなそうなので，こだわらなければ brew 版をアンインストールしてもいいかも．

## Refs

- [Git switch の補完ができなかった - Qiita](https://qiita.com/atm-snag/items/c89a15cb8d05ab0e7aa3)
warning LNK4098について

# warning LNK4098
自分は136件のエラーと下のような警告がでました。
「warning LNK4098: defaultlib 'LIBCMTD' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。」
調べると、ソリューションの初期設定が原因であることがわかりました

# 解決策
ソリューションエクスプローラーのプロパティページ->
C/C++->コード生成->ランタイム ライブラリ->
* デバックなら
マルチスレッド デバッグ DLL (/MDd)をマルチスレッド デバッグ (/MTd)に変更しましょう。

* リリースなら
マルチスレッド DLL (/MD)をマルチスレッド (/MT)に変更しましょう。

# おわり
ライブラリを作る過程でwarning LNK4098が出ました。
忘れた時のメモ書きと困っている人の解決策になればいいと思って投稿しました。
この記事を見て解決できたという人はいいねをお願いします。
Powershell で.gitignore のグローバル設定を行う

こんにちは、PDF印刷からSPAまでを行ったり来たりで頭がバグりそうな中年です。

さて、どうしても案件的にWindows環境でGitを使う必要がありいつも通り設定していたところ、.gitignore のグローバル設定でハマったのでここで共有しておこうと思います。

## よく見かける方法がどうにもならなかった

まず成功した方法は下記の通り。

```PowerShell
git config --global core.excludesfile $env:USERPROFILE\.gitignore
```

あとは.gitignoreファイルを編集すればOKです。

もう少しちゃんと書くならこっちかな？

```PowerShell
git config --global core.excludesfile $env:USERPROFILE\.config\git\ignore
```

よく見かけるこいつはダメでした。

```PowerShell
git config --global core.excludesfile %USERPROFILE%\.gitignore
```

## PowerShell では環境変数の取得方法が違う

コマンドプロンプト以降長らく使われてきた % 記号による環境変数の取得ですが、こいつが使えなくなっています。

そんな事3億光年前に気づけよという話ですが、普段使い慣れてないのですっかりハマってしまいました。

アホみたいに初歩的なことですが、同じように無駄な時間を使う人が少しでも減るように、ここに残しておきます。

そんじゃあまたね。
LINE WORKS API 2.0 を PowerShell で叩いてみる (その2 : ユーザー一覧の取得と Pagination)

前回は、LINE WORKS API を利用するための Token を埋め込んだ Header オブジェクトを生成ました。
今回は、前回生成した Header オブジェクトを利用して、LINE WORKS ユーザーの一覧を取得してみます。

ユーザー一覧を取得する API は[こちら](https://developers.worksmobile.com/jp/reference/user-list?lang=ja)

ユーザー一覧に限らず、LINE WORKS API 2.0 の一覧取得 API は Pagination に対応しており、取得件数制限を超えたために全件が取得できなかった場合には responseMetaData.nextCursor が返ります。次回はリクエスト時のクエリ パラメータ cursor に nextCursor を入れてアクセスすると残りが取得できます。
nextCursor は URL エンコードする必要があることに注意が必要です。nextCursor に含まれる文字によっては、URL エンコードを忘れてもエラーになないので、たまにエラーになる、という場合は URL エンコードを忘れていないか確認してみてください。

また、LINE WORKS API 2.0 には [RateLimit](https://developers.worksmobile.com/jp/reference/rate-limits?lang=ja) があり、プランと API により、毎分の呼び出し可能回数が異なります。
今回は、どのプランでも問題にならないよう、毎秒 １ 回、API を呼び出します。

取得したユーザー一覧から、一意のキーとなる `email`、`userId`、`userExternalKey` と、`lastName`、`firstName` を表示してみます。

```powershell
$APIEndPoint = 'https://www.worksapis.com/v1.0/users'
$nextCursor = $null
do {
    if (![String]::IsNullOrEmpty($nextCursor)) {
        $callUrl = "$APIEndPoint`?cursor=$nextCursor"
        Start-Sleep 1 #sec  RateLimit 対策
    }
    else {
        $callURL = $APIEndPoint
    }

    $Response = Invoke-RestMethod -Uri $callURL -Method GET -Headers $Header
    
    $Response.Users | select email, userId , userExternalKey, @{Name = "lastName"; Expression = { $_.userName.lastName } } , @{Name = "firstName"; Expression = { $_.userName.firstName } } 

    $nextCursor = [System.Web.HttpUtility]::UrlEncode($Response.responseMetaData.nextCursor)
}while (![String]::IsNullOrEmpty($nextCursor))

```
LINE WORKS API 2.0 を PowerShell で叩いてみる (その1 : JWT の処理)

先日 LINE WORKS API 2.0 がリリースされましたので、早速使ってみます。

LINE WORKS API を利用する際には、JWT でアクセストークンを取得しますが、[ドキュメント](https://developers.worksmobile.com/jp/reference/authorization-sa?lang=ja)を見ても PowerShell から利用するのはちょっと難しいですよね。
PowerShell で JWT を取り扱うには、[powershell-jwt](https://github.com/Nucleware/powershell-jwt)が便利です。

powershell-jwt を利用して、LINE WORKS API を利用するための Token を取得し、取得した Token を埋め込んだ Header オブジェクトを生成してみましょう。

```powershell
$PrivKeyPath = '.\private_202212345678.key'
$ClientId = 'bJLxxxxxxxx'
$ClientSecret = '8Adxxxx'
$SvcAccount = 'xxxxx.serviceaccount@yourgroupname'
$Scope = 'user,bot,orgunit'

Import-Module powershell-jwt

$rsaPrivateKey = Get-Content $PrivKeyPath -AsByteStream

$iat = [int](Get-Date -UFormat %s)
$exp = $iat + 3600

$payload = @{
    sub = $SvcAccount
    iat = $iat
}
    
$jwt = New-JWT -Algorithm 'RS256' -SecretKey $rsaPrivateKey -PayloadClaims $payload -ExpiryTimestamp $exp -Issuer $ClientId
    
$requestHeader = @{
    'Content-Type' = 'application/x-www-form-urlencoded'
}

$requestBody = @{
    assertion     = $jwt
    grant_type    = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
    client_id     = $ClientId
    client_secret = $ClientSecret
    scope         = $Scope
}

$url = 'https://auth.worksmobile.com/oauth2/v2.0/token'
$response = Invoke-RestMethod -Uri $url -Method POST -Headers $requestHeader -Body $requestBody

$Header = @{
    Authorization  = "Bearer " + $response.access_token
    'Content-Type' = 'application/json'
}
```

`Invoke-WebRequest` や `Invoke-RestMethod` で LINE WORKS API 2.0 を呼び出す際に、`-Headers` に `$Header` オブジェクトを渡してあげれば、PowerShell から LINE WORKS API 2.0 が利用できます。

これで、PowerShell から LINE WORKS API 2.0 を呼び出す準備ができました。

 **2022/5/20 追記** 
powershell-jwt の利用には、PowerShell 6.2 以降が必要です。
IBM Cloud: Secrets ManagerとCertificate Managerの機能比較

# 概要
Certificate ManagerがEOSになり、代替サービスとしてSecrets Managerがあります。
本記事では、Certificate ManagerとSecrets Managerについて、SSL証明書管理の機能比較について記載します。


# Certificate Manager概要
Certificate Managerは、SSL/TLS 証明書の取得やインポート、保管、管理が可能です。
証明書を使用する必要がある場合、デプロイ/更新の自動化ができます。
また、サービスが証明書の有効期限日を継続的にモニターし、今後有効期限が切れる証明書や再インポート、注文、更新などの他のライフサイクル・イベントを Slack やコールバック URL から通知します。
**※2022年9月30日でEOM、2022年12月31日でEOSとなります**

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/24bdd1b1-7913-630a-d6a4-4b3ee05ec051.png width=100%>


参考：[IBM Cloud docs：Certificate Manager の概要](https://cloud.ibm.com/docs/certificate-manager?topic=certificate-manager-about-certificate-manager)

# Secrets Manager概要
Secrets Managerでは、**シークレット**と呼ばれる機密情報を管理します。シークレットには、以下の様な、機密システムにアクセスするために使用する情報が該当します。
- ユーザー認証情報
- SSL証明書
- IAMキー (IBM Cloudサービスで使用)
- 外部APIキーなど

その他の情報は以下を参照ください。
[Qiita：「IBM Cloud：Secrets Managerの概要」](https://qiita.com/takason/items/3860854b54e0dd4550d7)


# 機能比較まとめ (2022/05/20 現在)
||Certificate Manager|Secrets Manager|
|:--:|:--:|:--:|
|対象|SSL証明書|id/password、SSL証明書、APIキー、外部APIキーなど|
|SSL証明書の注文|Let's Encryptにて無料|Let's Encryptにて無料|
|SSL証明書の保管|ダッシュボードで管理。証明書のインポートも可能。|ダッシュボードで管理。証明書のインポートも可能。|
|SSL証明書のデプロイ|証明書のダウンロード/デプロイの自動化可能|現状、証明書デプロイ機能なし|
|SSL証明書のモニター/アラート|SlackやコールバックURLによる通知が可能|ロギング/モニタリング可能。現状、通知機能なし|
|SSL証明書の更新|証明書が自動で更新されるように構成可能|現状、自動更新機能なし|

# 最後に
Secrets Managerについては出てきたばかりのサービスであるため未実装の機能がありますが、今後機能追加があれば随時更新していきたいと思います！（2022/05現在）
JavaScriptでUnicodeの濁点・半濁点を分離する

濁点・半濁点を分離する関数の作成中、Unicode上での濁点・半濁点の扱いに戸惑ったのでメモ書き。

## NFDとNFC
Unicodeの中にも、
**NFC**：Normalization Form Canonical Composition (合成済みの文字)
**NFD**：Normalization Form Canonical Decomposition (複数文字を結合した文字列)
と種類があるらしい。

JavaScriptの文字列はデフォルトではNFCとして扱われるが、
`'文字列'.normalize('NFD')`
でNFDに変換できる。

## 表記の違い
それぞれencodeURIでエンコードすると分かりやすい。
```javascript:nfc.js
console.log( encodeURI('か'.normalize('NFC')) );
//%E3%81%8B

console.log( encodeURI('が'.normalize('NFC')) );
//%E3%81%8C
```
```javascript:nfd.js
console.log( encodeURI('か'.normalize('NFD')) );
//%E3%81%8B

console.log( encodeURI('が'.normalize('NFD')) );
//%E3%81%8B%E3%82%99
```

NFCでは「か」と「が」は別の文字と区別されているのに対して、NFDでは「か + ゛」といったように濁点用の文字(%E3%82%99)が用意されていることが分かる。
ちなみに半濁点「゜」(%E3%82%9A)もあった。

## 一応結果
最初は１０行くらいあったdakuten関数が１行にまとまってかなりのダイエット成功。
NFD/NFCとか聞いたこともなかったので他の人がハマらないようお役に立てると幸いです。

## 引用
参考にさせて頂きました。より詳しい部分が解説されています。

https://t2y.hatenablog.jp/entry/2019/06/29/150125#:~:text=Unicode%20%E3%81%A7%E3%81%AF1%E3%81%A4%E3%81%AE%E6%96%87%E5%AD%97,NFC%E3%80%81NFD%20%E3%81%A8%E5%91%BC%E3%81%B3%E3%81%BE%E3%81%99%E3%80%82
rails5 progate 整理メモ

# いいねした投稿の一覧を表示しよう（1）
 「いいね！」をした投稿を一覧で表示するために、likesアクションをusersコントローラ内に作成しましょう。
## ルーティングを設定
```routes.rb
get "users/:id/likes" => "users#likes"
```
## usersコントローラーのlikesアクションを設定
```users_controller.rb
.
.
.
  def likes
  end
.
.
.
```
## アクション名と同じhtml名を設定
likes.html.erbを作成する。

## いいねした投稿の一覧を表示させるためのリンクを作成する
```html
.
.
.
    <ul class="user-tabs">
      <li class="active"><%= link_to("投稿", "/users/#{@user.id}") %></li>
      <li><%= link_to("いいね!", "/users/#{@user.id}/likes") %></li>
    </ul>
.
.
.
```
これでlikesアクションを作動させるためのリンクを作成

# いいねした投稿の一覧を表示しよう（2）
## likesアクションの中身を設定する
インスタンス変数を定義する
```users_controller.rb
.
.
.
def likes
    # 変数@userを定義してください
    @user = User.find_by(id: params[:id])
    
    # 変数@likesを定義してください
    @likes = Like.where(user_id: @user.id)
    
  end
.
.
.
```
## 一つずつ取り出されたLikeインスタンスのuser_idからPostモデルを取り出す
likes.html.erb
```likes.html
.
.
.
    <!-- 変数@likesに対してeach文を用いてください -->
    <% @likes.each do |like| %>
      <!-- 変数postを定義してください -->
      <%= post = Post.find_by(id: like.user_id) %>
    <% end %>
.
.
.
```
## find_byメソッドを用いて、idが「like.post_id」のPostインスタンスを取得してください
```likes.html
.
.
.
    <% @likes.each do |like| %>
      <!-- 変数postを定義してください -->
      <% post = Post.find_by(id: like.user_id) %>
    <% end %>
.
.
.
```
```likes.html
.
.
.
   <% @likes.each do |like| %>
      <!-- 変数postを定義してください -->
      <% post = Post.find_by(id: like.user_id) %>
    <% end %>
.
.
.
```
## ```<% post = Post.find_by(id: like.user_id) %>```
なんで<%=をつけなくていいのだろうか？
## each文に対応する<% end %>を追加してください
```html
      <% @likes.each do |like| %>
      <!-- 変数postを定義してください -->
        <% post = Post.find_by(id: like.post_id) %>
.
.
.
    <!-- each文のendを追加してください -->
    <% end %>
```   
もっと下に```<% end %>```に書かなくてはいけなかった。
freee for salesforce を使ってSalesforceのオブジェクトから取引データを作成する


取引を作りたいのですが、freee請求書作成画面からレコードを選択して作成します。今回は売上なので「収入取引」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9adf3b9f-e50c-5c1d-1c0e-71266da01c8e.png)

freeeに取引が作成されると、Salesforce側にもfreee取引オブジェクトにレコードが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cdc5a734-520c-1a24-51a4-f286c0ae014d.png)
Herokuに自動デプロイされなくなった件（追加修正）


## 追記分というかまとめと修正。 2022/05/29

書いたものの見づらくなったのでここだけ見ればOKの状態にしておく。

1. herokuに不具合があり自動デプロイができなくなった。(自動デプロイが直ることはなさそう)
1. 更新するにはheroku cliをインストールする必要がある（ほかのやり方もあるかも？）
1. ローカルにGithub上のレポジトリをclone。
1. それとは別にheroku用にcloneしたファイルを置くフォルダを作る。
1. heroku用フォルダ内に移動してgit init(gitファイルはコピーしない）
1. heroku git:remote -a [アプリ名]　でアプリを認識。
1. heroku用フォルダにcloneしたファイルを配置。
1. heroku用フォルダに移動し、以下のコマンドを打ち込む。

``` heroku cli
$ git add .
$ git commit -am "make it better"
$ git push heroku master
```

更新の際は7と8だけすればよい。



<hr>

## Herokuと連携してたポートフォリオがGithub更新しても自動更新されないぞ！



ログインのメアド忘れてしまったので新しく取り直して、環境を作ることに


githubと連携ができない！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/32265b90-5590-bc48-c711-66bb1f6071f2.png)


***

[参考資料]
https://kanaxx.hatenablog.jp/entry/2022/04/18/011926



どうやら、Githubとの連携はボタン一つでできなくなった模様。

***

https://devcenter.heroku.com/ja/articles/heroku-cli


HerokuCLIというものを使って環境を構築するらしい。

## まずはDLしてインストールできてるか確認。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/a1d1d958-79d1-1ed7-4077-ac69195867fc.png)

***

## Herokuにログインしてみる。

```
heroku login​
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/f77a4101-7e97-4aed-6039-7a3c432537bb.png)


<hr>

## 手動でherokuにpushする必要がある

ローカルにgithubのプロジェクトをDLして設置。

その前にDLしたものを配置するディレクトリまでいき。

```
git init
```

***

## GithubからプロジェクトをDLする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/b658e92e-6596-0d30-9006-333dc1eba3d9.png)

をクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/0ea0147e-543f-c03a-143b-e47e65e60040.png)

ZipでDLして対象のフォルダに設置する


```
// local　環境の話
git add .
git commit -m "herokuにdeploy"
```
***

## アプリを追加だ！（GUIでgit連携しようとしてapp作ってあった）

```
heroku git:remote -a [アプリ名]
// 新規でapp作る場合は
heroku -a [アプリ名]
```

*** 

エラーが出た！！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/e75a1673-b3a9-e019-d27e-dcb1d7b4e965.png)

どうやらHerokuCLIのversionが古いらしい

```
heroku update
```
コマンドを使いversionの引き上げ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/700498b6-ef4c-8559-e66f-30dae53e2882.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/294779d6-1dfd-1296-242a-0ce277fb8874.png)


<hr>

再度実施。

```
heroku git:remote -a [アプリ名]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/13dd0744-05f0-21fa-d690-96cf7f636104.png)

***
## アプリを認識したのpushする。

```
git push heroku master
```

で完了！！
netstat - ポート使ってるの誰だ

## 0.概要
アプリが起動しない時、セキュリティソフトや権限の問題の場合もあるが、
ネットワーク系アプリではポートが既に他のアプリで使用されている事が原因の場合がある。
(例としては、VMwareが443ポートを使っているなど。）
このような場合はnetstatで調べる事ができる。


## 1. Windows
netstat -oオプションでPIDがわかる。

```
>netstat -ano

アクティブな接続

  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:443          0.0.0.0:0              LISTENING       7976
```
tasklistコマンドでPIDに該当するプロセスがわかるのでアプリの設定を変える等で対処する。

```
C:\>tasklist /fi "PID eq 7976"

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
vmware-hostd.exe              7976 Services                   0     10,780 K
```


他、タスクマネージャーなどPIDからプロセスがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461232/06ad62a5-10f5-38cc-763b-4f5ef58f6395.png)

## 2. Linux
netstat -pオプションでPIDとプロセス名がわかる。

```
# netstat -anp | grep 443
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2281/(プロセス名)
```
※ 例はUbuntu。ディストリビューションによる差異は未確認。

## 捕捉:sockstat
netstatにPIDを出力するオプションが無いOS(BSD系など)ではsockstatでポートとプロセスの紐づけを確認できる

```
] sockstat -n
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
root     dhclient   148    4 udp    *.68                  *.*
root     syslogd    208    3 dgram  /var/run/log          -
root     smbd       370   10 dgram  /usr/pkg/lib/samba/private/msg.sock/370 -
root     smbd       370   34 dgram  -                     /var/run/log
root     smbd       370   38 tcp6   *.445                 *.*
root     smbd       370   39 tcp6   *.139                 *.*
root     smbd       370   40 tcp    *.445                 *.*
root     smbd       370   41 tcp    *.139                 *.*
root     sshd       401    3 tcp6   *.22                  *.*
root     sshd       401    4 tcp    *.22                  *.*
```
OpenTelemetry CollectorでECSのメトリクスを取得する

# 概要

最近OpenTelemetryというものを知りました。ここではOpenTelemetryについて調べた内容と、ECSのメトリクスをprometheusへ送信してみた際の設定内容を記載します。

# OpenTelemetryとは

OpenTelemetryはベンダーに依存しないテレメトリーデータの取り扱いを可能にしてくれます。これまでテレメトリーデータはPrometheusやDatadog、CloudWatchなど、かくプロダクトによって独自に扱われていたため、移植性などに課題がありました。OpenTelemetryではテレメトリーデータを統一的に扱う方法を提供することで、この課題を解決しようとしています。詳しい説明は[こちらで](https://opentelemetry.io/docs/concepts/what-is-opentelemetry/)。

# OpenTelemetry Collector

OpenTelemetryが開発しているOpentelemetryCollectorは、テレメトリーデータを取得、変換、送信を行います。例えばprometheus exporterで取得したデータをdatadogとprometheusへ送信する、といった使い方ができます。データ取得部分がreceiver, 変換部分がprocesser,送信部分がexporterと呼ばれています。様々なreceiver, exporterが開発されており、柔軟にデータの取得送信ができそうです。残念ながら現時点でDatadog Agentのreceiverは実装されていない様です。[PullRequest](https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/5836)が作られていましたが、閉じられてしまっています。

## AWS ECS Container Metrics Receiver

[AWS ECS Container Metrics Receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/awsecscontainermetricsreceiver)は、ECSのメトリクスを取得するためのreceiverです。ECSのメタデータエンドポイントからタスクのメトリクスを取得してくれます。

## AWS Prometheus Remote Write Exporter

[AWS Prometheus Remote Write Exporter](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/awsprometheusremotewriteexporter)は、Amazon Managed Service for Prometheusに対してメトリクスを送信してくれます。内部でPrometheus Remote Write Exporterを使っていて、AWSの認証などの処理を追加している様です。

# 設定ファイル

OpenTelemetry Collectorの設定はコード以下の様にしました。

``` config.yaml
receivers:
  awsecscontainermetrics:
processors:
  resource:
    attributes:
      - key: aws.ecs.service.name
        value: "${ECS_SERVICE_NAME}"
        action: upsert
exporters:
  awsprometheusremotewrite:
    endpoint: https://aps-workspaces.ap-northeast-1.amazonaws.com/workspaces/{workspace_id}/api/v1/remote_write
    resource_to_telemetry_conversion:
      enabled: true
service:
  pipelines:
    metrics:   
      receivers: [awsecscontainermetrics]
      processors: [resource]
      exporters: [awsprometheusremotewrite]
```

``` Dockerfile
FROM debian
RUN apt-get update
RUN apt-get install -y wget
RUN wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.42.0/otelcol-contrib_0.42.0_linux_amd64.deb
RUN dpkg -i otelcol-contrib_0.42.0_linux_amd64.deb
COPY config.yaml /etc/otelcol-contrib/config.yaml
CMD ["otelcol-contrib","--config=/etc/otelcol-contrib/config.yaml"]
```

config.yamlの`exporter.awsprometheusremotewrite.resource_to_telemetry_conversion`の設定は必須です。どうやらprometheus exporterは[job, instance以外のラベルを全て捨ててしまうようです](https://github.com/aws-observability/aws-otel-collector/issues/958)。この設定を入れないとtask名などの情報が全て抜け落ちてしまいます。

# グラフ化

データが取得できたことの確認のために、grafanaで可視化しました。

![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223111/e91c43ad-4178-bc22-a15d-f4ae502677d6.png)


いい感じです。ここからdatadogへのexporterを追加してみたり、cloudwatchに転送してみたりと色々試していきたいです。
opentelemetry collectorを間に挟むことで、datadogを使っていたけれどprometheus+grafanaを試してみる、とかそういうことが今までよりも簡単にできるようになるかもしれないです。
USTは米ドルから切り離され、LUNAは最大60％低下します

5月8日の早朝、USTは米ドル価格から切り離され、0.98ドルまで下落しました。LUNAも続いた。元のTerraネットワークトークンも関与しており、同じ日に65ドルを下回りました。この記事を書いている時点（5月10日の午後12時）の時点で、USTは$0.7641に下がっています。LUNAは$25,7113に下がりました。

USTは接続に失敗したために問題があります

今週末（5月7日）のクラッシュは、すでに「悲惨な」市場に新たな打撃を与えました。Terraエコシステムは、協調攻撃を受けたようです。カーブとバイナンスのステーブルコイン交換取引で最大2億8500万UST。 、USTは米ドルから切り離され、0.98ドルまで下落しました。その兄弟トークンLUNAは同じ日に20％下落し、65ドルを下回り、3か月ぶりの安値となりました。


デカップリングの前に、テラの創設者であるド・クォンはツイッターで次のように答えた。人間は絶滅の危機に瀕している」と語った。

![pasted image 0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657115/6958a9ca-a8cd-efb8-ca94-6e808642d0c5.png)


Curve Financeはまた、「一部の人々は大量のUSTを販売し始めました。しかし、多くの抵抗があったため、アンカー価格は回復しました。維持するために大量のドル価値を集めるために。価格、大量のETHおよびstETH （リドに賭けられたETH）が売却されました。その間、カーブの取引量は大幅に改善されました。」

![pasted image 0 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657115/76659c68-8ee1-6be3-0a8e-f86c694ce2fe.png)


5月7日の「攻撃」により、TerraLUNAの主力はショートポジションで急上昇しました。一方、キーワード「ポンジースキーム」は数時間世界中で人気がありました。Twitterの一部の暗号オピニオンリーダーは、USTが0.992ドルに下がったスクリーンショットをリリースし、「歴史的な瞬間」と呼んでいます。

これは計画的な「協調攻撃」ですか？


墜落後、USTを使用する最大の合意であるアンカープロトコルは、年利約18％を維持しましたが、預金額はUSTの20％未満であり、ローンも24％減少しました。
![pasted image 0 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657115/6d75981c-51e5-8d40-8234-a45651182e39.png)


出典：アンカープロトコル

一部の人々は、フォークイベントが一連の主要なアンカープロトコルの撤回に起因すると信じています。先週の終わりに、アンカープロトコルのUST預金の合計は140億ドルから112億ドルに減少しました（USTの総循環供給は180億ドルでした）。さらに、Curve流動性プールでは、Terraの作成者であるTerraformLabsが前後2回の引き出しを行いました。Terraform Labsは、初めて1億5,000万ドルのUST流動性をCurveから削除しました。次に、あるアドレスが8400万ドルのUSTをイーサリアムに接続し、4分後にUSTを販売しました（後で、そのアドレスがTerraform Labsのアドレスではないことが証明されました）。しかし、撤退と売却のタイミングが偶然であったため、市場はパニックに陥り、誰もがUSTの売却を急いでいました。


その後すぐに、TerraformLabsはさらに1億ドルのUST流動性をCurveから削除しました。その後、USTは分裂し始め、別のアドレスがETHを販売し、1億ドル以上でUSTを購入し始めました。さまざまな活動が、これをTerraコミュニティの「共同攻撃」として表明しています。


*協調攻撃：システムの脆弱性の存在と攻撃ツールの広範な使用により、ブロックチェーンネットワーク攻撃がより頻繁に発生します。その中で、協調攻撃は一種の脅威です。協調攻撃は、慎重に計画および実行される攻撃のグループです。それは、分業とさまざまな部門の協力を通じて、共通の攻撃目的を達成します。協調攻撃ツールは、多くの場合、より自動化され、インテリジェントになっています。現在、ブロックチェーンコラボレーション攻撃はますます一般的になり、検出して効果的に防御することは困難です。


私たちを救う

この頭痛の危機に直面して（Terraの創設者であるDo Kwonはそうは思いませんが）、あらゆる分野の人々が行動を起こしました。5月8日、TRONの創設者であるジャスティン・サンは、USTを購入しているとツイートし、ド・クォンに「秘密の計画があるかもしれない」と答えた。



5月9日、ジャスティンはUST/USDD流動性プールがユニスワップに展開されたとの声明を再度送信しました。同日、LFG（Luna Foundation Guard、Terraエコシステムの非営利組織）は、Terra経済システムの安定性を保護するために、USTが米ドル。





市場が通常に戻った後、LFGは7億5000万のUSTローンでBTCを購入します。取引は市場の変動に応じていつでも行われ、最終的にはLFGリザーブプールでBTCとUSTのバランスを徐々に維持します。


アップデート


5月10日の朝、米ドルからの深刻な切断が0.66ドルに下落したため、カーブのUST/3CRV比率は大幅に不均衡になりました。現在、UST / 3CRV比率は93.48％/ 4.74％に達しています。

Terraエコシステム非営利団体のLunaFoundationGuard（LFG）は、できるだけ多くのUSTアンカー価格を確保するために、5月10日の09:20:26に28,205.5ビットコインを撤回しました。投稿の時点で、アドレスのBTC残高はクリアされています。


今日の午後12時の時点で、USTは23.18％下落して0.7641ドルを見積もります。LUNAの見積もりは$25,7113、59.39％オフです。


DefiLlamaのデータによると、Terraの現在のオンチェーンDeFiキーボリュームは、過去24時間で44.39％減少し、129億ドルに減少しました。現在、下降傾向は続いています。


USTの発散によって引き起こされた墜落は、市場センチメントをさらに解き放ち、全体的な市場の下落を悪化させ、全体が極端なパニックに陥りました。





イベントの進行状況を引き続き監視し、最新情報をお届けします。Gate.ioブログを購読して、USTに関する最新の状況について連絡を取り合うことを歓迎します。
5.4 (標準) F分布

## 方針

F検定で使うF分布の期待値を求める問題．

## 答案

![5.-9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/ceadc15d-747e-88da-ebb0-63212b8dda60.jpeg)
![5.-10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/190180d2-9d32-9987-c73c-c2143cb73a18.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
5.3 (難) t分布2

## 方針

期待値，分散を求めるだけなら(別解)の通り繰り返し期待値・分散を使う方が楽だが，前半と後半で一貫性を持たせるために定義通り積分計算する方法を推す．

## 答案

![5.-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/2b6636d3-fbfa-a0ac-9e5c-5f9b20934e61.jpeg)
![5.-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/145c5098-d8f2-c5d7-3367-f8bc2d8cc362.jpeg)
![5.-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/fb47bf5a-727e-17dd-42c9-6ea5a1c9a3cb.jpeg)
![5.-8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/e14d9f87-2837-5b14-d0d0-bbf8fc998e82.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
STM32G031でアナログサーボをmodbusで制御(送信(RS485)(その3)


x 動作確認済み2022/5/18 14:14


目的
サーボ関係の続き
都合よくmobusの規格を解釈して
最小限で実装

仕様

20個程度のアナログサーボーを数珠繋ぎでデジタルシリアル化
コスト削減と軽量コンパクト化と簡易化を狙う

FCは、RS485が電気的に約32個しか繋がらないので256個で1バイト
データは、8ビットなので1バイト
8バイト固定のショートパケット

関数化

servo(0,123); //ID 0 DATA 123

ローレベル関数の共通化

modbus_send(0x10,123); //FC 0x10 DATA (int)123


シンクロ(同期)が速い　戻りは、int
data = modbus_receive(0xc0); //FC 0x40 re(0xc0)


![o_con460.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a4aab9dd-cc6e-fc53-7bd6-03e34ab03a00.jpeg)



![o_con442.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/49c02df7-212d-4f30-91a0-1751df77abf0.jpeg)


![o_con461.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d6063c16-52d1-ee5f-e0ca-2babbdd3e20c.jpeg)


![o_con463.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/77b7b55f-e0ee-14fe-8cc8-53a20b94e82f.jpeg)




プログラム



```c++


//ser_modbus_servo_M_031_1

// tx PA14(PB6) 8PIN
// rx PC14(PB7) 1PIN

#include <Arduino.h>


//プロトタイプ宣言
//prototype declaration
//
void servo(int id,int data);
void modbus_send(int id,int data);
unsigned short calc_crc(unsigned char *buf, int length);


//初期化処理
void setup() {

  delay(3000); //not Delete!!

  // シリアル通信の速度を500000bpsにする。
  //Serial set 500kbps
  Serial.begin( 500000 );

} //setup


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

  //サーボに値の設定
  //The servo set value
  servo(0,123); //ID 0  DATA 123 (0x7B)

  delay(1000); //1秒待つ

}//loop


void servo(int id,int data){

  //パケットの送信
  //send packet
  modbus_send(0x10 + id, data );
  

}//servo


void modbus_send(int id,int data){

  int ii;                    //カウンター counter
  unsigned char out_buff[8]; //バッファー buffer

  //バケットに値を設定
  // packet move
  out_buff[1 - 1] = 0x00;                  //Slave_Addr
  out_buff[2 - 1] = id;                    //Func_Code
  out_buff[3 - 1] = 0x00;                  //Addr1
  out_buff[4 - 1] = 0x00;                  //Addr2

  out_buff[5 - 1] = 0x00;                  //Data1
  out_buff[6 - 1] = (data & 0xff);         //Data2
  out_buff[7 - 1] = 0x00;                  //CRC_1
  out_buff[8 - 1] = 0x00;                  //CRC_2

  //チェックサムの計算
  //Checksum Calculation
  int ret = calc_crc( out_buff , 6);
  out_buff[7 - 1] = (char)(  ret     & 0xff);
  out_buff[8 - 1] = (char)( (ret>>8) & 0xff);


  //送信処理
  //send 8 byte
  delay(1);
  for (ii = 0; ii < 8; ii++) {
    Serial.write(out_buff[ii]);
  }//for
  delay(1);

} //modbus_send


// buf    受信データ
// length 受信データ長(CRCを除く)
unsigned short calc_crc(unsigned char *buf, int length) {
  unsigned short crc = 0xFFFF;
  int i,j;
  unsigned char carrayFlag;
  for (i = 0; i < length; i++) {
    crc ^= buf[i];
    for (j = 0; j < 8; j++) {
      carrayFlag = crc & 1;
      crc = crc >> 1;
      if (carrayFlag) {
        crc ^= 0xA001;
      }
    }
  }
  return crc;
}




```