Diary

Diary

日々学んだことをアウトプットする場として初めてみました

iphone の画面を mac 上に表示する方法

開発中などに iphone の画面を mac 上に表示させたいことがあるかと思います。

android には scrcpy という優秀なツールがあるのですが、iphone ではどうやら QuickTime Player を使えばできるらしいので、今回はその紹介をしたいと思います

起動方法

0. maciphone をケーブルで繋げる

1. QuickTime Player を起動する

2. File > New Movie Recording を起動する

f:id:kokoichi206:20220313203252p:plain

3. 起動した録画画面で、Camera の設定から iPhone を選択する

f:id:kokoichi206:20220313203414p:plain

以上で、無事 iphonemac 上に描画されます

参考

おわりに

この QuickTime Player を使った方法では PC 上からの操作はできないので、その点は残念です。

最初は xcode からエミュレーターと同じように起動させられろう、と思って探していたのですが設定が見つかりませんでした。ご存じの方がいたら教えていただきたいです。

bash でコマンドの実行結果をファイルとして扱う

プロセス置換(Process Substitution)を用います。使い方と一緒に、ぜひ名前も覚えましょう。

使い方

# 通常のファイル入力の場合
$ cat test.txt

# コマンドの実行結果をファイルとして扱う場合
$ cat <(echo "hoge from echo command")
hoge from echo command

ファイル名<(コマンド)で置き換えるだけです!

<(の間にスペースはいりません。

少し具体的なコマンドで見てみます

diff コマンド

diff <(echo 3.0+3 | bc) <(echo $((3.0+3)) )
1c1
< 6.0
---
> 6.

片方をファイルにして、もう一方をプロセス置換にすることもできます

$ cat file.txt
file

$ diff file.txt <(echo "content")
1c1
< file
---
> content

ファイル読み込み:while read ...

ファイルの中身を読み込みながら1行ずつ処理を行う場合、次のように書くことができます

while read line
do
    echo "$line"
done < file.txt

この while ループに入力させている file.txt の部分に、プロセス置換を使うことが可能です。

### expected outputs
# hoge
# pien
while read line
do
    echo "$line"
done < <(echo -e "hoge\npien")

おわりに

ファイル入力しか受け付けないコマンドに対し、『ちょっとしたテストコードを試したいが、わざわざファイルを用意するのもめんどくさい』といったケースに使えると感じました。

他にも有用なユースケースがあれば教えていただきたいです。

ラズパイサーバーに100万アクセスし温度を計測してみた

自作ラズパイサーバーに高負荷?(40分100万アクセス)をかけ、その際の温度変化を計測してみました。

結果

[目次]

環境

- クライアントサイド
  - zsh 5.8 (mac)
  - go version go1.16.10
- サーバーサイド
  - raspberry pi 4
  - OS: ubuntu 20
  - Apache/2.4.52 (Ubuntu)
  - mydns のドメイン

ラズパイに高負荷をかける

https://mysite.jp の部分には自分のアクセスしたいアドレスを入れてください(決して知らない外部のURLにしないでください

bash で行う

この方法が最速ではないですが、以下の方法では 1000 アクセス 8 秒くらいでした。

time (seq 1000 | xargs -I ZZ -P 5 curl -s "https://mysite.jp" > /dev/null)                                                                                                             
( ... ; )  8.19s user 5.01s system 194% cpu 6.782 total

以下のように background で各アクセス処理を走らせるようにすることでスピードアップできると思います。ただ自分には、バックグラウンド処理をうまく待つことができず、時間が測れませんでした。

time (seq 10000 | xargs -n 1 -P 5 curl -s "https://kokoichi0206.mydns.jp" > /dev/null 2>&1 &)
( ...)  0.00s user 0.00s system 11% cpu 0.009 total

golang を使った方法

こちらのQiitaの記事をそのまま使わせてもらいました。

記事内の Local サーバーを使った方法を試したところ、1 万アクセス 1 秒かからなかったので期待していたのですが、実際の URL に対して行うとかなり遅くなりました。

1000 1_0000 100_0000
2.82 28.479 2657.5

ほぼ線形に変化しているようです(サーバー側で同時アクセ数の制限とかある?)。

ということは、常に一定の負荷がかかっていると思って良さそうです。

ラズパイの温度を計測する

ラズパイの温度

以下のコマンドでラズパイの温度を取得できます。

$ cat /sys/class/thermal/thermal_zone0/temp
55991

注意点としては何故か 1000 倍されていることで、上の例は 55.99 度ということになります。

定期的に測定する

以下のような measurement.sh ファイルを用意し、定期的に測定しました(1秒に1測定しています)。

#/bin/sh -eu
#
# Description
#   measure the temperature regularly

date=`date '+%Y%m%d_%H%M%S'`
while :
do
    temp=`cat /sys/class/thermal/thermal_zone0/temp`
    echo `date '+%Y%m%d_%H%M%S'` "$temp" >> "temp_$date"
    sleep 1
done
# Ctrl + C で止める
$ bash measurement.sh

1列目に時間、2列目に温度を記録するようにしています。例としては以下のようなデータが取れます。

20220210_134439 46738
20220210_134440 48686
20220210_134441 48199
20220210_134442 48686

gnuplot でグラフを出力する

なぜ gnuplot を使って描画してるかって?

ワンライナーで使えるからです!!!!

measurement.sh で2列分データを取りましたが、結局1列しか使っていません。

gnuplot -e 'set terminal png; set output "./temperature.png"; set xlabel "time [s]"; set ylabel "temperature [°C]"; plot "temperature" using 0:($2/1000) title "temperature"'

2500 秒くらいで急に落ちてるのは 100 万アクセスが終わった時間になります。

綺麗なカーブを描いていたので log スケールで取ってみたら、綺麗な直線になりました!

gnuplot -e 'set terminal png; set output "./temperature.png"; set xlabel "sec"; set ylabel "temperature"; plot "temperature" using 0:($2/1000) title "temperature"'

最初の方の点が少ないので、より細かく見るために測定間隔を 0.1 秒にして測り直しました。

(おまけ)フィット

両対数を取って線形になる、ということは、以下のような式が成り立つことを意味してます

\displaystyle{
\log(y-y_0) = a*\log(x-x_0) +b\\
y = c*(x-x_0)^a + y_0

}

以下のコマンドで、x0 を0に固定してxが20から1500までの範囲でフィットしてみます。

gnuplot -e 'f(x)=a*x**b+c; fit[20:1500] f(x) "temperature" using 0:($2/1000) via a,b,c; set terminal png; set output "./temperature_fit.png"; set yrange [45:70]; set xlabel "time [s]"; set ylabel "temperature [°C]"; set key right bottom; plot "temperature" using 0:($2/1000) title "temperature", f(x) lw 5'

結果:(y=a*x**b + c)

a               = 13.1365          +/- 1.717        (13.07%)
b               = 0.121676         +/- 0.009238     (7.593%)
c               = 37.0958          +/- 2.04         (5.498%)

理論わからんけどフィットできたぞおおおおお

おわりに

本当はラズパイサーバーに高負荷をかけてサーバーをダウンさせてみたかったのですが、うまくいかなかった意外にラズパイが丈夫だったので代わりに温度を測ってみました。

http 通信が、ローカルで試した時よりも速度が出なかったのが敗因だと思っています。知らない間に DOS 対策の WAF など(?)働いてるかもしれないので、いつかじっくりと調べてみます!

awk 1 とは何か

awk 1という表現についてメモしておきます。

awk

大前提として、awkの基本パターンは『(マッチ)パターン+アクション』です。

そして awk では以下のように記述します

# awk 'pattern {action}'
$ echo 'hoge fuga pien' | awk '/fuga/ {print $0}'
hoge fuga pien

どちらか一方の省略

実は「パターン」or「アクション」はどちらか一方を省略することができます。

パターンが省略された場合

パターンが省略された場合、全ての行に対してアクションが行われます。

$ echo -e 'hoge fuga pien\npoe ho'
hoge fuga pien
poe ho

$ echo -e 'hoge fuga pien\npoe ho' | awk '{print $1}'
hoge
poe

アクションが省略された場合

アクションが省略された場合、{print $0}と同等のアクションが行われます。

$ echo -e 'hoge fuga pien\npoe ho'
hoge fuga pien
poe ho

# awk '/fuga/ {print $0}' と同等
$ echo -e 'hoge fuga pien\npoe ho' | awk '/fuga/'
hoge fuga pien

awk 1

以上awkの基本的性質を押さえておくと、awk 1という表現の意味が見えてきます。

この表現は、アクションが省略されたものであるり、また、パターンが『1』であることが分かります。

よって、awk 1 とは全ての入力行に対し{print $0}を行うものとなります。

これにより最終行に改行を入れることなどができます。

# 行末に改行がない
xx@yy:~$ echo -en 'hoge'
hogexx@yy:~$

xx@yy:~$ echo -en 'hoge' | awk 1
hoge
xx@yy:~$

なお、awk では 0 より大きな値は真の判定がなされるため、awk 3などでも同様の効果があります。

# 0 より大きな値
xx@yy:~$ echo -en 'hoge' | awk 3
hoge
xx@yy:~$

おわりに

今回は、ぱっと見で何をしているのかわからなかった awk コマンドについて記載してみました。

次やるときに迷わないようしたいです!

Android アプリ内で使用 OSS を表示させる

今回は、必要な OSS の一覧を Google Play services を使って簡単に表示させてみたいと思います。

注意点としては、表示のために新たに Activity を立ち上げる必要があることです。

見た目

f:id:kokoichi206:20220206213339p:plain

環境

- Android Studio: Arctic Fox | 2020.3.1
- gradle: build:gradle:7.0.4
- 使用api: services-oss-licenses:17.0.0

実装

プロジェクトレベルの build.gradle

dependenciesに、次の classpath を追加します。

buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4'
    }
}

アプリレベルの build.gradle

pluginsdependenciesに必要なものを追加します。

'com.android.application'が追加されていることを確認するようにしてください。

plugins {
    ...
    id 'com.android.application'
    id 'com.google.android.gms.oss-licenses-plugin'
}


android {
    ...
}


dependencies {
    ...
    // OSS License display
    implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
}

AndroidManifest に登録

activity を登録しておきます

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application
        ...>
        ...

        <activity
            android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
            android:theme="@style/Theme.CountDownTimer" />
        <activity
            android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
            android:theme="@style/Theme.CountDownTimer" />
    </application>
</manifest>

使い方

表示させたいタイミングで、以下のような Activity をスタートさせます。

import com.google.android.gms.oss.licenses.OssLicensesMenuActivity

startActivity(Intent(this, OssLicensesMenuActivity::class.java))

POM dependencies というものに基づきアプリに関与した OSS を表示してくれているため、おそらく大量のライセンスが表示されると思います。

また、タップすることで個別のライセンスを表示できます。

生成物

表示されているライセンス情報一覧は、以下の build フォルダに生成されています。

app/build/generated/third_party_licenses/res/raw/

Links

おわりに

OSS利用規約により、使用 OSS のライセンスを表示させないといけないケースは多いと思います。とはいえ、そこに多くの時間はかけられないので、このようなものを公式が用意してくれているのはありがたいです。

Jetpack Compose で横画面に対応する!

Jetpack Compose で横画面を検知しレイアウトを変更する』ことをやってみたいと思います。

環境

- build:gradle:7.0.4
- compose_version = '1.0.1'

レイアウト

次のように、横画面か縦画面かを判断しレイアウトを変更できるようにことがこの記事のゴールです。

縦画面

f:id:kokoichi206:20220205002300p:plain

横画面

f:id:kokoichi206:20220205002334p:plain

現在の画面の向きを取得する

Composable 関数の中で現在の画面の向きは、以下のメソッドで取得することができます。

LocalConfiguration.current.orientation

縦画面かどうかを判断する

従って、縦画面かどうかを変数として表すには次のようにConfiguration.ORIENTATION_PORTRAIT(縦画面)と比較してあげます。

isVertical =
    LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT

// 縦画面か横画面かに応じて次のいずれかが入る
// 縦
// Configuration.ORIENTATION_PORTRAIT
// 横
// Configuration.ORIENTATION_LANDSCAPE

縦画面や横画面の変更を検知する

画面の向きの変更に伴い、基本的には再描画が走るため、特に特別な処理は必要ないように思います。

val isVertical =
    LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT

サンプルプログラム

冒頭の写真の物を作った際のコードを貼っておきます。

サンプルコード

@Composable
fun ShowName() {
    val isVertical =
        LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT

    if (isVertical) {
        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .weight(1f)
                    .background(Color.Blue),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "First Name!", fontSize = 24.sp,
                    textAlign = TextAlign.Center
                )
            }
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .weight(1f)
                    .background(Color.Red),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "Last Name!", fontSize = 24.sp,
                    textAlign = TextAlign.Center
                )
            }
        }
    } else {
        Row(
            modifier = Modifier.fillMaxSize(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .weight(1f)
                    .background(Color.Blue),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "First Name!", fontSize = 24.sp,
                    textAlign = TextAlign.Center
                )
            }
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .weight(1f)
                    .background(Color.Red),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "Last Name!", fontSize = 24.sp,
                    textAlign = TextAlign.Center
                )
            }
        }
    }
}

Links

Re-gaining orientation #1

おわりに

今回は Jetpack Compose で『縦画面と横画面を検知しレイアウトを変更する』ということをやってみました。

Jetpack Compose で3点ボタンのドロップダウンメニュー

成果物

今回は、Jetpack Compose で以下のようなものを作りたいと思います。

  • 縦に3つ点の並んだアイコンを表示
    • MoreVert と言うらしいです
      • More read, vertical ??
  • クリック時にそこからメニューを表示させる

写真

クリック時の挙動

環境

- build:gradle:7.0.4
- compose_version = '1.0.1'

実装

色々と頑張って作ったのですが、きちんとドキュメントに書いてありました。。。そのため説明は割愛します。。。

また、どんなアイコンが利用可能かは fonts.google.com をみると良いです。

// メニューの開閉をコントロールするため
var expanded by remember { mutableStateOf(false) }
Box(
    modifier = Modifier
        .wrapContentSize(Alignment.TopStart)
) {
    IconButton(
        onClick = {
            expanded = true
        }
    ) {
        Icon(
            Icons.Filled.MoreVert,
            contentDescription = Constants.DESCRIPTION_MORE_VERT_ICON,
            tint = MaterialTheme.colors.surface,
        )
    }
    DropdownMenu(
        modifier = Modifier
            .background(MaterialTheme.colors.background)
            // タップされた時の背景を円にする
            .clip(RoundedCornerShape(16.dp))
            .background(MaterialTheme.colors.onSurface),
        expanded = expanded,
        // メニューの外がタップされた時に閉じる
        onDismissRequest = { expanded = false }
    ) {
        DropdownMenuItem(
            onClick = {
                // Do something
            }
        ) {
            Text(
                text = "1",
                fontSize = 24.sp,
                color = Color.White,
            )
        }
        DropdownMenuItem(
            onClick = {}
        ) {
            Text(
                text = "2",
                fontSize = 24.sp,
                color = Color.White,
            )
        }
        DropdownMenuItem(
            onClick = {}
        ) {
            Text(
                text = "3",
                fontSize = 24.sp,
                color = Color.White,
            )
        }
    }
}

おわりに

Jetpack Compose で実装できる範囲が広がってきてとても楽しいです。

今後もできることが増えたら発信していけたらと思います!