Chrome 80 (2020年2月予定) からは挙動が変更され、SameSite 属性がない (なにも対応していない場合) は SameSite=Lax の挙動がデフォルトになる。かなり厳しい制約が増えるので対応必須。

また、既存の挙動に戻すためには SameSite=None を指定する必要があるが、SameSite=None は Secure 属性が必須になる。

ということでいずれかが最低限必須

  • https 化 と Secure 属性
  • SameSite=Lax で問題ないサイトづくり

最低工数

  • 常時 https 化する
  • Secure 属性と SameSite=None 属性をつける

既に https 化されているなら最も手軽で追加の検証がいらない。

→ 今まで通りの挙動。CSRF 耐性は特になく、セキュリティは向上しないが不具合はでない

ちょっとは頑張れる

  • SameSite=Lax 属性をつける

→ ほぼ今まで通りだが、外部からのフォーム POST など、CSRF に繋がりそうなケースで挙動がかわり安全になる。XHR や iframe でも cross-site の場合はデフォルトでクッキーが送られなくなるので、対応のうえ全体で再度QAが必要

もっと頑張れる?

SameSite=Strict にすると、あらゆる外部サイトからのページ遷移のときにクッキーが送信されなくなる。最初に開くと必ず非ログイン状態になり、そのあと遷移するとログイン状態が復活したりする。ユーザー体験上、Strict をそのまま既存のセッションクッキーに適用するのは困難。

副作用が発生するクッキーだけを Strict クッキーに分けるような設計をすれば活用できるが、サイトのページ遷移から見なおす必要がある。

個人の見解では Strict を使うケースはないんじゃないかと思う。SameSite=Strict は銀の弾丸ではなく、アプリケーションの問題は CSRF だけではない。結局、総合的に他の施策も必要なので、SameSite=Strict している暇があったら他のことをしたほうが良さそう。

  1. トップ
  2. tech
  3. SameSite 属性結局どうすりゃいい?

接続済み SSH セッションからファイルをダウンロードする というエントリを2012年ぐらいに書いて、その中で uutransfer という、screen ウィンドウを通じて uuencode したファイルを転送して書きだすツールを紹介しました。

便利に使っていたんですが、最近 tmux に移行した ので、このツールが動かなくなって困りました。ということで書きなおして独立したレポジトリに移動しました。

  1. トップ
  2. tech
  3. uutransfer for tmux (接続済み SSH セッションからファイルをダウンロードする)


ITU-T G.227 にあるフィルタを実装して、無線機の特性試験の試験方法に登場する「疑似音声信号発生器」を WebAudio で作ってみる。

ITU-T G.227

Conventional Telephone Signal という名前の勧告。伝達関数が書いてある。600Hz ぐらいにピークのあるフィルタになっている。

ホワイトノイズをこのフィルタに通すことによって疑似音声となる。なので、この周波数特性を持つフィルタを設計する。

フィルタの設計方法

フィルタの知識がないので、試行錯誤しながら以下のようにすすめていった。

  • 周波数特性をそのままFIRフィルタにする
  • 最初から実数 FIR フィルタとして設計してみる
  • 双一次変換を使って IIR フィルタにしてみる

結論からいえば、今回の場合はアナログフィルタの伝達関数が示されているので、そこからデジタル IIR フィルタに変換するのが一番良かった (と思う)

求めるのは Jupyter Notebook 上で行なった。

周波数特性をそのままFIRフィルタにする

FIR フィルタは周波数特性がわかっていれば IFFT で作ることができる。ほぼ何も考えずに作れる。

最初は対称をつくらず IFFT して、最後に実数だけとるのを作った。

実数 FIR フィルタとして設計する

フィルタを左右対称にすればほぼ実数フィルタになるはずだが、低域の減衰が急峻すぎるせいかこれでも虚数が出てきてしまう。しかたないのでこのまま虚数を捨てて実数フィルタとして評価した。

まぁまぁうまくいくけど、かなり重くなってしまう。そして、それなりに G.227 の特性から誤差が発生して気持ちがわるい。FIR なので次数を増やせばそれだけ近似はできるが、どんどん重くなっていく。

なお FIR フィルタを WebAudio で使いたい場合は、ConvolverNode を使えば良い。

アナログフィルタを双一次変換 (bilinear transform) してIIRフィルタを得て FIR フィルタで補正する

↑補正なし↓補正

アナログフィルタ(周波数連続という意味)からデジタルフィルタ(離散という意味)をつくる方法の一つに双一次変換がある。scipy で簡単にできるので、これを試す。

今回の場合、アナログの伝達関数はわかっているので、この規格に書いてある伝達関数を双一次変換してIIRフィルタの係数を得る。つまり以下を変換してデジタルフィルタを得たい。


なぜ微妙に括弧がついてるのかわからないが、結局これは次数ごとに書きなおすと見なれた以下の形になる。ほぼ scipy.signal.freqs などが受けとる形になっている。4次。

ただ、p が なので、これを角周波数 をとる関数に変えたい。

python で上記通り係数計算して、signal.bilinear() に渡してあげると、デジタルフィルタの係数になる。ただ、双一次変換は周波数歪みが起こるので、完全にアナログフィルタの特性と一致するわけではない。

こういう場合どうするのかよくわからなかったが、次数の少ない FIR で容易に補正できそうだったため、アナログフィルタの周波数特性との差分をとって補正する FIR フィルタを追加で設計する。

IIR フィルタを WebAudio で使う場合は IIRFilterNode を使えば良い。feedForward に分子 feedBack に分母の係数を渡せば動いてくれる。

ということでできたのが冒頭にリンクしたレポジトリとなる。https://github.com/cho45/pseudo-audio-signal

  1. トップ
  2. tech
  3. ブラウザで動く擬似音声発生器 (ITU-T G.227 フィルタ)

  • Type-C コネクタ
  • 25MHz / 32.768 kHz 水晶つき
  • NRST / BOOT ボタン

裏面に WeAct と書いてあった。

何もせずそのまま USB に繋ぐとシリアルポートとして認識される。

Bus 020 Device 025: ID 0483:5740 STMicroelectronics STM32 Virtual ComPort 
00:01:10,04012019
VrefintAdc: 1.2133V
TempSensorAdc: 24.75C
FlashID:0 ERROR!

こういう出力がずっと流れている。

プログラム方法

この MCU は System Memory という領域を持っており、ブートローダーが最初から書きこまれている。詳細は AN2606

USB 経由で DFU するには、基板上の BOOT0 を押しながら、NRST を押せば良い。

Bus 020 Device 008: ID 0483:df11 STMicroelectronics STM32  BOOTLOADER  Serial

として認識される。

platformio

https://docs.platformio.org/en/latest/boards/ststm32/blackpill_f401cc.html

blackpill_f401cc というのがある。たぶんこれなので、一旦これで試す。

platformio init --board=blackpill_f401cc

残念ながら mbed framework が使えないみたいなので、一旦 arduino でいく src/main.cpp

#include "Arduino.h"

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

void setup() {
	pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
	digitalWrite(LED_BUILTIN, HIGH);
	delay(500);
	digitalWrite(LED_BUILTIN, LOW);
	delay(500);
}
pio run

.pio/build/blackpill_f401cc/firmware.bin ができるので、BOOT0 を押しながら NRST を押し、USB DFU モードにする。この状態で dfu-util で書きこめる。

dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D .pio/build/blackpill_f401cc/firmware.bin 

mbed のカスタムボード定義

とりあえず mbed のほうが好みなので mbed を使えるようにしてみる。こういうことするとハマりやすいのであまりよくないが…

403 Forbidden に従いながらカスタムボードを定義する。

platformi.ini

[env:f401cc]
platform = ststm32
board = f401cc
framework = mbed
build_flags = -I$PROJECTSRC_DIR/TARGET_F401CC

boards/f401cc.json

# https://github.com/platformio/platform-ststm32/blob/develop/boards/blackpill_f401cc.json をコピペ

custom_targets.json https://github.com/ARMmbed/mbed-os/blob/e1c3de649dd9c16d9548f73b4bbb71858af904f7/targets/targets.json#L4834 から抜き出してコピペ

{
	"F401CC": {
		"inherits": ["FAMILY_STM32"],
		"core": "Cortex-M4F",
		"default_toolchain": "GCC_ARM",
		"extra_labels_add": [
			"STM32F4",
			"STM32F401",
			"STM32F401xC",
			"STM32F401VC"
		],
		"supported_toolchains": ["GCC_ARM"],
		"device_has_add": ["MPU"],
		"device_name": "STM32F401CC"
	}
}

cp -r ~/.platformio/packages/framework-mbed/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F401xC/TARGET_DISCO_F401VC src/TARGET_F401CC

#include "mbed.h"

DigitalOut led(PC_13);

int main() {
	for (;;) {
		led = 1;
		wait(0.2);
		led = 0;
		wait(0.2);
	}
}

これで pio run が走って .pio/build/f401cc/firmware.bin ができるはず。

time dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D .pio/build/f401cc/firmware.bin 

で書きこみ。

  1. トップ
  2. tech
  3. STM32F401CC の安いボード

別表第35とかに出てくる「標準符号化試験信号」の生成について調べた。

擬似信号発生器は、標準符号化試験信号(ITU-T勧告O.150による9段PN符号)を発
生させる。
と書いてある。

ITU-T O.150 は n 段(stage)のシフトレジスタで構成されるテスト用の疑似乱数列について定義している。n段の符号はnビットのシフトレジスタに対応する。

具体的な生成方法は wikipedia の LFSR を読むのがわかりやすい。

9段のPN符号

「4.1 511-bit pseudo-random test pattern」となっているところが9段のもの。

「The pattern may be generated in a nine-stage shift register whose 5th and 9th stage outputs are added in a modulo-two addition stage, and the result is fed back to the input of the first stage. The pattern begins with the first ONE of 9 consecutive ONEs.」と文章で書いてある。

5th and 9th と書いてあるところが帰還多項式に対応しており、この場合

になる。また初期状態も定められており、全ビット1から初めるとしている。

JavaScript での実装

以下のような任意のビット数(ただし32ビット以下)の LFSR のコードを書いた。全ビットが0でない限りは最大周期で全ての状態が出現する。

/**
 * Linear-feedback shift register
 *
 * reg: n bits register state
 * n: Bits(n) (up to 32bits)
 * taps: feedback polynomial (eg. x^16 + x^14 + x^13 + x^11 + 1 => [16, 14, 13, 11])
 * ref. https://en.wikipedia.org/wiki/Linear-feedback_shift_register
 */
function LFSR(reg, n, taps) {
	const mask = n === 32 ? (-1>>>0) : (1 << n) - 1;
	reg &= mask;

	const bit = taps.
		map( (tap) => reg >> (n - tap) ).
		reduce( (r, i) => r ^ i ) & 1;

	return ( (reg >>> 1) | ( bit <<  (n-1) ) ) & mask;
}

const start = 511;
let lfsr = start;
let period = 0;
do {
	lfsr = LFSR(lfsr, 9, [9, 5]);
	console.log('output:', lfsr>>(9-1), 'internal:', (lfsr | (1<<9)).toString(2).slice(1));
	period++;
} while(lfsr !== start);
console.log('this feedback polynomial period:', period);
  1. トップ
  2. tech
  3. 標準符号化試験信号 PN符号 LFSR

ちょっと困ったことが起きており、一昨日からワンオ… | Fri, Oct 11. 2019 - 氾濫原 書いてからワンオペしてたがとりあえず終わった。

入院する前、調子を崩して家にいる状態だと、保育園から毎日毎日「何の病気なのか」と聞かれ続け、知らねーよ判ったら苦労しねーよと内心苛立っていたが、とりあえずそれがなくなってストレスは一つ減った。

生活品を届けにいったとき先生から説明をうける。ハッキリ原因がわからないので、安全な治療からはじめて、それがいつまでにうまくいかなかったら次はこうする、という方針を聞く。洒落ためがねをしていて頭が良さそう(医者なんだからもちろんそうなのだが、その上で)とぼーっと考えていた。

運悪く、保育園の弁当を持ってこいイベントが発生間近であり、まぁ冷凍食品のからあげを詰めたり、梨を剥いて詰めたりしてしのいだ。からあげは大変好評であった。

その間に台風19号があって避難したりして、なかなか面倒に。一人親の苦労ってのは責任が単一にかかるってのもあるよなあとか、大人が一人だけだと満足にトイレもいけないなとかいろいろ考えさせられる。子どもが5歳で良かったとか、近くに (妻方の) 親戚がいたので助かったとか思った。

台風後に子どもが発熱。幸い機嫌は良く、一日経ったら解熱して問題なかった。

病院は12歳以下の面会はお断りなので、あまり子どもをつれてお見舞いにいくという感じではない。そういえばと思ったのでテレビ電話で通話。子どもは喜んでたみたい。テクノロジー。

洗濯物は仕舞うのが面倒なので山積みにして (山になるほどではないが)、宝探しだぞと子どもに探させた。割と楽しくて一石二鳥

週があけて入院診療計画書が渡された。事前に主治医から聞いた内容が文書になった感じ。週単位の入院計画でなかなか暗い気持ちにはなる。

と思ったら翌日に、経過がよければ次の週末に退院の予定となる。一回説明するから来てくださいと言われたので (必要なの?とは思いつつ) 早退して聞きにいった。部屋で座って説明されることになって、重病なのか?と不安になったがそういうわけではなく、ものすごく丁寧な先生というだけだった。紙に図解付きで明確に説明されるので、資料作りながらプレゼンしてる感じですごいな〜と考えてた。

Android で外部キーボード使用時の日本語入力を快適にする (SKK) | tech - 氾濫原 というのを書いたが、設定できない部分で自分にあわない挙動があったので、fork して変更した。

以下の点だけ

  • egg-like-newline な挙動に (変換中の RET で改行を入力しない)
  • 辞書登録時に何も入力せず RET した場合は元の状態に戻るように

GitHub Actions で自動ビルドするようにしてある。

  1. トップ
  2. tech
  3. SKK for Android の自分用フォーク

Android では、アプリのサイズをできるだけ減らしたりするために、リリース前にアプリ全体のコードの最適化 (いわゆるツリーシェイキング) が推奨されている。動作としては、実行されるコードを解析で割り出しで、不要なコードを全て削除、というものになる。

基本的には minifyEnabled true を build.gradle に書けばよくて、簡単なアプリケーションなら、マニフェストから起動される Activity を解析してそこから呼ばれるクラスやメソッドは削除されないようになるので、これだけですむ。

が、リフレクションや JNI、または capacitor のように JavaScript のエンジンを一度経由して呼ばれるクラスなどは、この解析パスで到達できない。結果として、性質上、実行時にエラーが起こることになる。

capacitor で keep すべきもの

capacitor の場合、JavaScript 経由で呼ばれるものには全て keep しておく必要がある。

  • com.getcapacitor.plugin.* のうち、利用しているもの。
    • 名前も含めて keep しないとダメ。JS 側から見える名前はリフレクションで取得されるため
  • その他、利用しているプラグイン以下のクラス

-keep public class com.getcapacitor.plugin.App {
    static *;
    public *;
}
-keep public class com.getcapacitor.plugin.Device {
    static *;
    public *;
}
-keep public class com.getcapacitor.plugin.Filesystem {
    static *;
    public *;
}

-keep public class org.apache.cordova.CordovaPlugin

-keep public class fr.drangies.cordova.serial.**
-keepclasseswithmembers class com.hoho.android.usbserial.driver.** {
    static *;
    public *;
}

-printconfiguration /tmp/full-r8-config.txt
-printusage /tmp/usage.txt

`-keep public class com.getcapacitor.plugin.Filesystem` だけだと名前が変わってしまう。ProGuard の指定方法がややこしつてよくわからなかったが、上記のようにしたらうまくいった。

cordovarduino という Cordova のプラグインを利用しているので、それ系の設定もある。

`-printusage` で指定したファイルには「削除された」クラスやメソッド名が出力される。必要なメソッドが意図せず削除されているかも?と思ったらこのファイルを見てみる。

  1. トップ
  2. tech
  3. capacitor で Android 向けに minifyEnabled true

手元にある Elecraft KX3 の測定をしてみる。

(ちなみに当局の KX3 は「平成17年12月以降にアマチュア局の保証を受けて免許を受けた無線機」に該当するのでスプリアス確認保証は不要、のはず)

測定方法について

以下を根拠に測定する

新スプリアス規定

測定結果を提出データとして使うためには測定器(スペアナ)が1年以内に校正されていなければならないので、現実的に個人でこれを行うのは難しい。

しかしアマチュアであれば JARD に対してスペアナ(校正済みでなくてもよい) の測定結果をもって保証してもらうという手がある。

測定周波数

アマチュアの場合広い帯域を一括で免許をうけるので、どの周波数を使うのかと思うが、割り当て帯域幅によって異なり、帯域幅が1MHz以下なら指定周波数 (免許状に書いてある、周波数帯域の中央) で測定をすれば良いらしい。別表第35

ただし電波形式は免許を受けるすべての形式で行う必要がある。

具体的な測定方法

スプリアス領域における不要発射等の測定方法の陸上関係無線設備(一般)にしたがう。

スペアナの設定のうちRBW, VBW, 検波モードが必ず指定された通りになっていることを確認すること。

スプリアス探索時

  • 掃引周波数幅 (基本周波数別に別途規定)
  • 分解能帯域幅 (RBW): 各スプリアス周波数毎に選択
  • ビデオ帯域幅 (VBW): RBW の等倍から5倍程度
  • 検波モード: ポジティブピーク
  • 掃引時間: 測定精度が保証される最小の時間
  1. 基本波の中心周波数か 2.5Bn (Bn=必要周波数帯幅) 以上離れたスプリアス成分を探索する
  2. 探索した各スプリアス成分の振幅値が許容値以下の場合は、探索値を測定値とする
  3. 許容値を超えた場合は振幅測定行い、平均値を測定値とする

スプリアス振幅測定

探索したピークに周波数をあわせて振幅をはかる

  • 中心周波数: スプリアス周波数
  • 掃引周波数幅: 0Hz
  • 分解能帯域幅 (RBW):
    • 9kHz 〜 150kHz : 1kHz
  • 150kHz 〜 30MHz: 10kHz
  • 30MHz 〜 1GHz: 100kHz
  • 1GHz〜: 1MHz
  • ビデオ帯域幅 (VBW): RBW の等倍から5倍程度
  • 検波モード: サンプル
  • 掃引時間: 測定精度が保証される最小の時間

実際にやってみる

面倒なので 40m (7100kHz) の CW だけでやる。変調をかけ最大送信電力にするということになっている。できるだけ厳しい条件でやるという意図だと思われるので、短点連続(帯域が最大)でやってみる。技適の手順だと25ボーとか、外部変調装置がある場合その最高速度みたいな手順みたいだが…

10W 7100kHz の場合、帯域外領域のスプリアス発射強度の許容値は 50mW (17dBm) 以下かつ、基本周波数の平均電力より40dB低い値。スプリアス領域での不要発射の強度の許容値は 50μW (-13dBm)以下。

  • 10W = 40dBm
  • 30dB 50W のアッテネータで 10dBm (0.01W)
  • 10dB 2W のアッテネータで 0dBm。これをスペアナに入力

必要周波数帯 (BN) は基本的に占有周波数帯幅の許容値と同値になるので CW の場合は 0.5kHz。スプリアス領域 は 2.5BN 離れた領域なため、7100±1.25kHz の外側がスプリアス領域。

7MHz の場合、基本波が9kHz〜100MHzのケースのためなのでスプリアスの測定範囲は 9kHz〜1GHz。ただし10倍高調波まで見る。

帯域外領域

帯域外領域の測定を勘違いしていました。別表第一 スプリアス発射又は不要発射の強度の測定方法 によると帯域外領域は無変調で行うようです。

ということで撮りなおしました。(Ref Offset を40dBいれているので、直読できるようになってます)

以下の画像はキーイング状態なので正確な測定ではないです。

一旦必要周波数帯と帯域外発射を見る。帯域外発射の範囲は 7100±1.25kHz なので、7100kHz を CENTER にして 2.5kHz SPAN で見てみる。

「帯域外領域のスプリアス発射強度の許容値は 50mW 以下かつ、基本周波数の平均電力より40dB低い値。」基本周波数の平均電力より -64dB 低いので後者の条件は達成、10W は 40dBm なので、帯域外領域の発射強度は -24dBm。50mW は約17dBmなので達成している。

スプリアス領域

上下にあるので、下から見ていく。

9kHz〜150kHz

下側 RBW=1kHz の範囲

なにもなさそう。

150kHz〜7100kHz

下側 RBW=10kHz の範囲

なにもなさそう。

7100kHz〜30MHz

上側 RBW=10kHz の範囲

高調波が出てる。40dBm -62 なので -22dBm。50μW (13dBm) 以下なので合格

30MHz〜70MHz (基本波の10倍)

RBW=100kHz の範囲

見つからず。

「ITU-R 勧告SM.329-10における指針」に従って、基本周波数の10倍高調波まで見れば良いことにはなっている。つまり 7MHz なら 70MHz まで見れば十分なはず。

スプリアス振幅測定

スプリアス強度が許容値を超えていた場合はどのぐらい超えたかを確定させるため、スプリアス振幅測定を行う必要がある。

今回は超えていないがこれもやってみる。14.2MHz を CENTER にして、ゼロスパンにする。

ref

  1. トップ
  2. tech
  3. スペアナでスプリアス測定してみる (KX3 CW)

1Fに住んでいて、ハザードマップでは最悪2mの浸水、ということは事前に調べてあった。土曜日10時ごろには既に、浸水地域に対してエリアメールで警戒レベル4が出た。実際まだ上陸まで時間がだいぶあるのに多摩川の水位が非常に上がっていた。子どももいるので暴風域に入ってから移動はしたくないし、万が一のときマンションの階段をかけのぼるのもあまりやりたくない。とかいろいろ考えた結果避難を決断。11時ごろに傘がさせる程度の雨の中避難所に (かっぱは着てたが)。

避難したことがなかったので、ちゃんと避難所が開設されているのか不安だったが一応開いていた。一旦かなり狭い部屋に案内されたあと、人が増えてきたので体育館が解放された。

そこで近くに住む妻方の親戚も避難してきて合流。食料や貴重品に不安があったので、子どもを親戚にあずけて一旦帰宅。短時間にだいぶ風雨が強くなっており、往復だけでずぶぬれに。

ところで避難所も浸水地域のため、体育館も安全ではなく、加えてさらに避難者が増えていたので、全体的に体育館は使わず、校舎内の一定階数以上を使うようにと再三の変更があった。

小学校側の担当者と市の担当者がいるみたいで、若干せめぎあいがあるみたいだった。小学校側としては児童のものがあり授業の円滑な継続のためには教室などは解放したくないようだった。当初は特別教室しか解放されていなかったが、増え続ける避難者に対して足りなくなり解放されていた。

21時ぐらいに台風が最接近して、急激に納まっていった。風雨の状況が全くわからない場所にいたので、そのへんの恐怖感は全くなかった。22時ぐらいから帰りはじめる避難者もいた。24時ぐらいにはほぼ完全に風雨がおさまっていたが、子どもが寝ていたし自宅の状況もわからないし、水位も下がりきっているわけではないので、そのまま明るくなるのを待った。

結局何事もなく、停電も断水も浸水もなかった。影響ある地点は越水まで1m程度でなんとか決壊しなかった。治水事業に感謝。

避難は結果的には辛いだけで無駄だったが、判断自体は間違いではなかったと思いたい。ただ避難先はもっと先に考えといたほうがよかった。漠然と公設避難所と思っていたが、これはかなり厳しいなと思った。ホテルとかに避難できればたぶんベストだと思った。

ちょっと困ったことが起きており、一昨日からワンオペ。

普段ルーチンに入っていないので、一番面倒なのが食事。平日は朝食だけ用意すれば良い。もともと延長保育にしてもらっているので昼食・夕食は保育園で出してくれる。休日はまだ考えてない。

洗濯ものは自分と子供だけなら洗ったものを着るという単純ローテできるので、実用上は別に仕舞う必要がなく、洗って乾燥したのを出しておくだけでなんとかなる。もともと洗濯・乾燥まではルーチンに入っているので困ったことは起きない。

掃除はもともと気になったときにしかやってないので負荷は増えない。床面はルンバがある程度綺麗に保ってくれる。あとはコードレス掃除機でさっとやるぐらい。

子どもは習いごと、勉強を見るのがそこそこ時間をとる。

まぁもう5歳になると結構聞きわけある年齢だし、やることやったら何やっててもいいルールにしていると、一人でゲームやったりして、その間は手があけられるのはありがたい。事情を話せばある程度はわかってくれるし、なんなら洗濯物とかを手伝ってくれてありがたい。