年中アイス

いろいろつらつら

hakoに機能追加

ECSを本格利用し始め、デプロイの管理にhakoを使うことにしました。最近ECSに機能追加があり、hako未対応のものを使いたくなったこともあり、hakoに追加してみることにしました。

作った機能

いくつか機能を追加して、プルリク投げてマージされたもの、プルリク中のもの、まだ確認中のものと4つ作っています。必要に応じて順次追加していて、投げれそうなものはPRにしています。主に、internalなmicro serviceを動かすユースケースでECSを使っているので、それに応じたものがあります。

health check grace periodサポート

ECS導入する時に使いたかったので、追加してプルリクしました。さすがにこれは単純な設定値の追加なのですぐマージされました。

github.com

この変更で初めてhakoいじったんですが、Rubocopのエラーに悩まされて、自分で変更した部分がルールに合っていなかったものと、Rubocop自体のアップデートのせいなのかエラーになっていたものとありました。

NLBサポート

gRPCをコンテナにして、ECSで動かす予定で、NLB(Network Load Balancer)をサポートしました。PR反応がないので、とりあえず置いたままです。

github.com

一つのALBに複数のECSサービスを紐付ける

hakoはデフォルトで、設定を書いたymlファイル名のALBを作ります。ただ、開発環境などで、hakoファイルごと(サービスごとに)ALBできるとお金かかるので、ポートを変えて、ALBを指定して同一のALBを使うようにしたものです。ポートが変わるので、internal ALB前提です。

GitHub - reiki4040/hako at feature/add-service-to-exists-elbv2

NLBサポートを先にPR出してるのは、これをNLBにも適用したいためですが、これは方針が本家の人が考えるのと合うのかという点があります。一応自分の環境でもしばらく使ってみてからにしようかなという状態です。

ECSのcontainer health checkのサポート

2018/03にECSに追加されたばかりの機能で、とりあえず使ってみようとのことで実装しました。設定値は反映されることを確認しました。AWS SDKのバージョン上がってます。

GitHub - reiki4040/hako at feature/container_healthcheck

機能追加したhakoを使うためのブランチ

上記をまとめて動作確認する用に、featuresと言うブランチを作って、そこに上記未マージ分をまとめて、バージョン番号変えてgemを作って試しています。自分の変更を入れたgemを作る方法は後述しています。

hakoをいじるにあたってのメモ

Rubyは普段使っていない言語なので、とりあえず自分でhakoのコードいじったときのメモです。

まず、変更したコードの実行について。exe/hakoがあったので、lib/hako/version.rbを変えてとりあえずexe/hako --versionしてみましたが、変更したバージョンは出てきませんでした。

調べてみるとbundlerを使って関連ライブラリを入れて、bundle exec hakoといった形でやる必要があったようで、それをやったらローカルの変更が反映されて実行することができました。

  • bundlerのインストール
gem install bundler
  • 関連ライブラリをローカルの環境(プロジェクト?以下に)インストール
bundle install --path=vendor/bundle --binstubs=bundle_bin

—binstubs=bundle_binはrbenv用っぽいので使わなければ不要かも。

  • bundle execで実行するとローカルの変更分が実行されます。
bundle exec hako —version

これでとりあえず自分でhakoのコードを変更したものをhakoコマンドとして実行できます。 また、hakoはrspecでのテストとrubocopでのコードスタイルチェックが実行できます。

bundle exec rake

最初これやってなくて、テスト未実行状態でした。

自分でgemを作って使う

hakoは、bundle exec rake installでpkg/以下にgemファイルが作られます。 それを対象サーバでgem install --local <gem>とすれば、インストールでき、使用することができます。

これで、自分の環境で変更を入れたhakoを使うことができます。

RubyAWS SDKのリファレンス

Ruby SDKのdocumentがよくわからなくても、aws cliで同様の機能(API)の調べて動かすと、項目とか、実際の値も見れてわかりやすかったです。Rubyに限らず、分からなかったらwas cliで動かしてみるのわかりやすいです。

所感など

普段はGoを書くことが多く、Rubyはツール使ってるぐらいで、作法がよくわからない感じでコード書きましたが、とりあえず欲しい機能は実現はできています。rakeで足回りのことができるようになっていたので、実現したいことのコードを書くぐらいで済んだのかなと思います。

一応本家に取り込んでもらいたいなーとは考えつつ*1自分の環境で使って、使い勝手を確認中です。個人的には、Goでワンバイナリで配布できるようなものを作りたくはありますが、まずhakoを使って運用してみて、どうあるのが自分としては好みなのか(使いやすいのか)考えていこうかなと思ってます。

参考など

*1:あまり環境固有の機能実装はしない

API Gateway+LambdaのSlack通知APIをCloudFormationで作る

以前、三編に分けて、SlackへPostするWebAPIを、API Gateway+Lambda+node.jsで作りました。

しかしその後、AWS ConsoleのLambdaのUIが変わったので、一部のキャプチャが参考になりづらくなってしまいました。キャプチャし直すのも手間なので、今度はCloudFormationを使って自動で構築します。

CloudFormationで自動構築する

CloudFormation templateを作ったのであとは実行するだけです。READMEにも書いてますが、以下3段階です。

  • SlackのWebhook URLを発行
  • CloudFormationを実行
  • CloudFormationの結果をもとに、slackへのpostを実行

SlackのWebhook URLを発行

前編を参考に発行します。 公式のWebhookドキュメントも一応添えておきます。

発行できたら、apigateway.json"SLACK_WEBHOOK_URL":"none"を取得したURLで置き換えます。(noneを置き換えます。)

CloudFormationを実行

awsコマンドを使って、stackを作成します。stackの構築が終わるまで、数分かかります。

aws cloudformation create-stack --stack-name PostSlackCfn --template-body file://apigateway.json --region ap-northeast-1 --capabilities CAPABILITY_IAM

CloudFormationの結果をもとに、slackへのpostを実行

結果を取得します。

aws cloudformation describe-stacks --stack-name PostSlackCfn

この結果のOutputの部分のapi keyとpost urlをコピーしておきます。

API keyは別途取得する必要があり、前述のapi keyを使って取得します

aws apigateway get-api-key --api-key <your api key id> --include-value

--include-valueオプションがないと、API keyは表示されません。

curlで投げて、HiとSlackに届けばOKです。

curl -XPOST <your post url> -H "x-api-key: <your api key>" -H 'Content-Type: application/json' -d '{"message":"Hi"}'

届かない場合は、CloudWatchLogsでLambdaのログを確認したり、後編に書いているように、API Gatewayのテスト実行をやるなどで調べてみてください。

まとめ

API Gatewayは手で設定していくのは面倒なので、CloudFormationの方が向いてますね。今回、CloudFormation初めて扱いましたが、基本的な構成要素を理解するまで、作成、削除を繰り返したので時間がかかりました。

課題としては、WebHookURLみたいなリポジトリに入れたくないような値はどう扱うのがいいのか。また、もっと大きなくくりでは、CloudFormationが失敗した時に、全部消して最初からになったので、実運用で失敗した時に、うまくリカバリできるのかが不安要素。今回はそこまで調べてないです。

主にCloudFormation化について書いたので、元々の構成詳細については、三編それぞれ見てもらえればと思います。

ここからは、つまづいた点などのメモ。

最初参考にした記事

AWS CloudFormation が Amazon API Gateway をサポートしたので使ってみた | Developers.IO

ここを参考にcloudformationでAPI gatewayのサンプルを作成してみました。 APIを定義して、Resource(URL Pathになるところ)を定義して、Methodを定義する形。とりあえずすぐできました。

DeploymentとMethodで起きる順序問題も、ここにあるDependsOnで理解しました。

/に対してMethodを定義したい

参考にしたのは、Resourceを作る前提でしたが、もともと/に直接POSTで動かしていたので、どうやるのかなと。 結果Resource定義なしでMethodのResourceには、{ "Fn::GetAtt": [“PostSlackCfn”, "RootResourceId"] } を指定すればよかったです。

Lambda関連を追加したら、create stackでエラー

An error occurred (InsufficientCapabilitiesException) when calling the CreateStack operation: Requires capabilities : [CAPABILITY_IAM]

調べると以下のようなものが出てきました。

IAMが絡むと必要になるようで、LambdaとそのRoleを追加したタイミングで発生したようです。 —capabilities CAPABILITY_IAMを追加したら動くようになりました。*1

Lambdaの環境変数を定義したい

これはすぐ見つかりました。

でも秘匿情報はコミットしたくないので、どう別管理するのがいいのかは未解決。今回はサンプルで自分のローカルで変更して実行で済ませています。

Stageを定義しないとUsagePlanにStageを指定できないが、DeploymentとStageを両方書くとStageがすでにあるエラーが出る

DeploymentでStageが作られるので、それをUsagePlanに指定しようとしましたが、うまく指定の仕方がわからず。Deploymentで作成させるStageの名前を入れても、そんなものはないと怒られる始末。さらにDeploymentとStageで同じ名前にすると、すでにあるからダメと。

結局解決策わからず、Stageを定義しないと指定できないので、以下を参考に、Deploymentではダミーを作って、Stageを別定義して、それをUsagePlanに指定しました。

参考

*1:CAPABILITY_IAM、はっきり理解はできてません。権限いるから明示的に許可するってことでしょうか

GoでJSONの数字/数値を扱う

JSONはデータの表現形式です。表現はできますが、項目があるかや、型が何であるかを検査する仕組みはありません。*1

そのため、システムや実装が分かれている場合に、数値を期待しているが、JSONの表現上、数値か数字かがずれていることが起き得ます。どういうことかというと、"numeric":1234 (数値)なのか、"numeric":"1234" (数字)なのかが違う、または不定ということ。仕様の齟齬や、実装ミスなどで発生します。

動的型付け言語の場合、よしなに扱ってくれたりしますが、Goにそれをやられると型エラーが発生してしまいます。GoでJSONを読み込む場合、encoding/jsonパッケージjson.Unmarshal()を使って、structに読み込む方法があります。しかし、stringで定義していたら、数値がNG、int系で定義していたら、数字がNGです。

stringは数値がダメ(playground)

type Num struct {
    Number string
}

num := Num{}
err := json.Unmarshal([]byte(`{"number":1234}`), &num)
    
// json: cannot unmarshal number into Go struct field Num.Number of type string

int64は数字がダメ(playground)

type Num struct {
    Number int64
}

num := Num{}
err := json.Unmarshal([]byte(`{"number":"1234"}`), &num)

// json: cannot unmarshal string into Go struct field Num.Number of type int64  

Goの場合、Unmarshalで読み込めないと、黒魔術的にJSONを解析する必要がある*2ので、Unmarshalで済ませたいのです。その際に、json.Numberを使います。

使い方は簡単で、数値数字不定になっている属性の型をjson.Numberにして、そのstructを使ってUnmarshalします。そうすると数字でも数値でもabcdeなどの文字列でも、Unmarshal時点ではエラーになりません。型の不一致で、JSON全体の読み込みを止めなくて済みます。もちろん使う時に数値変換は必要で、Int64()を使いますが、数字以外の文字列の場合はエラーになります。(ParseInt失敗するのと同様)

type Num struct {
    Number1 json.Number
    Number2 json.Number
    Number3 json.Number
}

num := Num{}
// Unmarshalではエラーにならない
err := json.Unmarshal([]byte(`{"number1":1111,"number2":"2222","number3":"abcde"}`), &num)
// 数値はエラーにならない
num1, err := num.Number1.Int64()

// 数字はエラーにならない
num2, err := num.Number2.Int64()
    
// 数字以外の文字はエラー
// strconv.ParseInt: parsing "abcde": invalid syntax
_, err = num.Number3.Int64()

json.Number使ったUnmarshal(playground)

補足:JSON出力する時のjson.Number

json.Numberは、Marshalすると、数値として出力されます。数字、数値どちらで読み込んでいても数値になります。数以外の文字列の場合は、Marshal時にエラーになります。このjson.Numberを使って読み込んで、そのままMarshalする場合は、この数値になる動きを意識しておく必要があります。

json.NumberのMarshal

type Num struct {
    Number1 json.Number `json:"number1"`
    Number2 json.Number `json:"number2"`
}

num := Num{}
// 数値、数字を読み込む
err := json.Unmarshal([]byte(`{"number1":1111,"number2":"2222"}`), &num)

// JSONに出力
j, err := json.Marshal(num)

// 数値として出力される
// {"number1":1111,"number2":2222}
fmt.Println(string(j))

*1:JSON Schemaなど別の仕組みを使用するとチェックしたりできるようです

*2:map[string]interface{}で延々名前探して型確認して変換の繰り返し。。。

Amazon echo (Alexa) がやってきた

スマートスピーカーが盛り上がってきてますが、Amazon echoの招待メールが来て、ポチって届きました。前の日にだいぶ購買欲落ちたってツイートしてたら、その翌日に招待メール来ました。招待メールから4日以内に注文しないと、購入権がなくなるので、注文しますよね。

f:id:reiki4040:20171130172437j:plain:w300

ハードの感想としては、大きすぎず小さくもなく重い。350ml缶ホルダーみたいな感じです。プラグ部分は、一昔前のアダプタとまではいきませんが、少し大きなブロックぐらいはあるので、密集してると邪魔になるかも。

セットアップ

早速セットアップ

  • 本体は電源コード繋いで、コンセントに挿すだけ。コードちょっと邪魔だなーという印象。上部の縁が青に光って、1分ほどでオレンジの待機状態に。
  • iPhoneにAlexaアプリを入れて、amazonアカウントにログイン。
  • 本体のボタンを5秒押すと、セットアップモードになって、echoがWiFiホストになるようで、iPhoneの設定からそこに接続。
  • そうすると、今度はechoが接続するWiFiを選ぶ画面になって、自分のとこのWiFiを設定し、しばらくセットアップ待ち。ここで私は何回かエラー1や、登録エラーなどが発生し、詳細はヘルプを見てくださいと。ただ、ヘルプのどこだよそれはって感じで、4,5回リトライで成功。echoから少し離れた位置でやってたから失敗したのか?と思って、echoの目の前でやったら成功しました。

使ってみる

ポチった後に、echoの動画などを見ていたのと、前からGoogleのCMはOK, Googleと言ってるのを見て、掛け声の後に間を空けないとダメなのか?と思っていて、それがすごくテンポ悪くて嫌だなーと思ってました。試しに「アレクサ天気教えて」と、ひと続きで話してみたら、普通に認識したので、この懸念は払拭されてよかったです。

とりあえず、天気、ニュースを試してみた感想は、alexaが読み上げる?テキストは機械の合成音声で、単語によっては発声とテンポが聞き取りづらい(抑揚とペースが一定すぎる)のがあるのと、話題と話題の間が短すぎで、話半分に聞くぐらいがまだいいかも。ニュースコンテンツなどは配信側のコンテンツっぽいので、それはそっちの品質次第。

割と便利そうなのが、音楽を流す(amazon music)、タイマー、リスト登録。*1

  • 音楽はジャズを流してみたいなのでサラッと流れてくるので、ちょっと気分を変えたい時に声操作は便利。
  • タイマーは料理するので声だと手を使わなくて楽チン。
  • リスト登録は「買い物リストにだしの素入れて」-> 「何を登録しますか?」(聞き返された)-> 「だしの素」で、追加されました。ふと買おうと思ってたものを追加するのに便利です。ただ、alexaアプリのそのリストが少し深いところにあるのが難点。

あとは、FireTVとつなごうとしたんですが、「問題が発生しています。しばらくして行ってください」と使えないので、一旦断念。試してる途中、意図せず「FireTVでYoutube再生して」-> 「よくわかんないけど、これ(なんか商品名を言った)をカートに追加しますか?」みたいな返答されて、「いいえ」回答。アプリから音声注文はまだOFFってる状態(デフォルトONだったよ!)ですが、amazonカートにもの突っ込めるのかな。

スキル

250社ぐらい初回からスキルに参加したようですが、ニュース配信や自然の音あたりで、初期のマーケットという感じ。iPhone3GSの時のAppStoreが、ちょっとしたアプリたくさんの感じだったのに似てて、これからどんどん増えてって高度になってくんだろうなーと思うと楽しみです。自分で作るのもできるようなので挑戦したいところ。野良スキル(自分だけとか仲間内だけで使える機構)ができるのかが気になる点です。

感想

iPhoneのSiriは全く使わない人ですが、Alexaはなぜか使い始めました(掛け声?)そんなに滑舌は良くないですが、昔に比べたらはるかに音声認識は進歩していて、とりあえずちょっと使う分には十分になってるのを実感しました。*2

スピーカーに話しかけるの違和感ないなと思ったんですが、普段娘(1歳)に話しかけてるのと似てたので、違和感もなかったのかなという気がします。娘には「〇〇、それとって」「〇〇、これないない(片付け)して」みたいな、まだしゃべれない一方通行やってるせいです。ちなみに娘はAlexaがニュース読んでると、あいつ誰だよみたいな反応をしてました。

友人から聞き出した、スマートホーム向けのNature Remoという製品、echo招待メール来た時は12月出荷分あったんですが、それから1日足らずで品切れになり、来年予定しかなく撃沈。一定数echo出荷されて、注文入ったのか、すぐ注文しなかったのを後悔。スマートホーム化は少し先になりそうです。娘にリモコン奪われないように、FireTV始め、家電の音声操作拡充させたいところ。早くしないと、今度は音声操作を乗っ取られそうです。*3

SF感あふれるワクワク感を抱けました。年末年始、技術的に遊ぶにはもってこいかも。そして5年ぐらいでスマホみたいにあって当たり前になりそう。

2017/12/2 追記

友人からNature Remo注文受付復活の報を受けて、無事注文完了しました。12月中旬から下旬発送予定だそうです。楽しみ。

*1:echoじゃなくても同様のことできるってのは置いといて

*2:話しかけ方は理解のある(機械が認識しやすいことを意識した)感じでやってるからというのもあると思います。

*3:ネイティブ音声操作世代になるのか・・・!

CircleCI 2.0でGoのテスト触ってみた

CI周りを触ってみている中で、Dockerイメージが動くようになったという、CircleCI 2.0が気になったので触ってみました。ちなみに1.0も触ったことはないです。参考で見たページだと、2.0はBeta版の時期もありましたが、今は正式にリリースされています。

circleci.com

cstoreで試してみる

適当なプロジェクトとして、cstoreに入れてみることに。cstoreは、ライブラリとしてシンプルなのと、たまたまちょっとテスト書いてあったのでお試し対象に。

  • CircleCIで、Add Project -> .circleci/config.ymlがなくて失敗
  • プルリクで追加 -> 成功

の予定でしたが、Add Projectしたら、CircleCI1.0モードで動いて、一通りGoで行われるべきことが動いていました。1.0はCircleCI用の設定ファイルおかなくても、言語指定すると、ベースとなる動作(dependencyのgo get, go test ,go buildなど)が勝手に動くようです。これはこれで、ベースができてていいですね。

2.0は今の所、実行コマンドは自分で記述する必要があります。cstoreはライブラリかつ依存はシンプルだったので、go getしてgo testをやるだけの設定を作りました。

https://github.com/reiki4040/cstore/pull/2 https://github.com/reiki4040/cstore/pull/3

version: 2
jobs:
  build:
    working_directory: /go/src/github.com/reiki4040/cstore
    docker:
      - image: circleci/golang:1.9
    steps:
      - checkout
      - run: go get github.com/BurntSushi/toml
      - run: go get gopkg.in/yaml.v2
      - run: go test -v -race ./...

circleci CLIで事前確認ができるのをすっ飛ばして、プルリクしてマージして、インデントミスっているという愚。go getの追加とともに修正したのでプルリクが二つに分かれてます。

ローカルで事前確認

CircleCI 2.0はCLIを使って事前にテスト実行ができます。 インストールは公式参照

まず作成したconfig(.circleci/config.yml)をチェック。

circleci config validate

そのあと、ローカルでのテストビルド。

circleci build

実際にdocker imageを落としてきて実行してくれます。circleci/golangの1.9は400MBぐらいありました。

これを行えば、事前にチェックして、しょうもないミスは防げると思います。*1

ビルド結果

CircleCIサービス上のビルド結果は、誰でも見える*2ので、機密情報が出るようなのは避けましょう。そもそも書いてあったらPublicリポジトリの時点でアウトですが、何か外部から取ってきて出力みたいなのがあると、デバッグのつもりで漏洩しちゃいます。privateリポジトリは、見えないと思いますが扱ってないのでわからず。

通知

メールでビルドに関しての通知がきますが、Slackなどへの連携も可能です。 すべて通知するか、失敗(fail)と失敗後の成功(fixed)のみを通知するかを選べます。

Goのサンプル試して誤プルリクをやらかす

最初、公式のGoのサンプルを試してみてたんですが、fork後にコード少し改変して動かしてみるかーと思って、適当にやってたら、いつの間にか公式サンプルにプルリク出してしまっていました。びっくり。一言書いて、closeしました。

たぶんですが、CircleCIの画面上に、open pull requestと言うボタンがあり、不意にそれを押してしまって、自動でプルリクが作成されたのかなと。同様のことをしてしまったであろう人もいました。

料金

料金ページには、Linux向けは、1コンテナのシリアル実行で、月1,500分(25時間。30日で割ると約50分ぐらい)までのビルドであれば、ユーザやリポジトリの数を問わず無料(Freeプラン)で、ビルド時間が無制限になる有料プランは、$50/Month(2コンテナ, 2並列から)からのようです。*3

感想

Goでテスト書いて、それを実行するぐらいは簡単にできますね。Github認証で、すぐ試せるのも楽です。

前のCodeBuildでは、buildspec.ymlに実行する内容があり、動かすイメージはCodeBuild側の設定でした。CircleCIは、実行イメージと実行内容を.circleci/config.ymlに書いて、CircleCI側で実行マシンのスペック設定、実行の確認で少し異なります。今時点では使い込んでないので、どちらがどういいのかまでは、あまりわからず。

公式のGoサンプルでは、Goをビルドしてバイナリを作って、PostgreSQLのイメージとともに起動してテスト実行みたいな感じで作ってあったので、go testのコード単体ではなく、バイナリに対しての挙動テストも実行できるようです。*4

設定ファイル(.circleci/config.yml)が、docker composeと実行スクリプト的な役割になる感じなので、結構いろんなことができそうです。この他のコンテナを起動したりといった辺りは、CodeBuildにはないですね。

workflowの機能も付いているようなので、それも試してみたいところですが、とりあえずここまで。

参考

*1:CLIで完全にエミュレートできるのかは不明ですが、、、

*2:README.mdなどに付けられる、CircleCIのバッジからのリンク先

*3:publicリポジトリにCircleCIつけて、プルリクでsleepかけるテスト入れられて1500分超えたら、どうなるんだろ?

*4:Freeプランの1コンテナだと、サンプルはビルド+PostgreSQLのコンテナで2個になりそうですが、動くのかな・・・?

docker for macのホストを指すドメイン名

手元のMacで開発をしていて、コンテナからホスト上で動作しているサーバに繋ぐ必要がありました。単純にlocalhostを使うとコンテナ自体を指してしまうので、それでは通信できません。ホストのIPをいちいち指定するのもなーと思っていたんですが、docker for macにはホストを表すdocker.for.mac.localhostというドメインがありました。*1 https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

2018/01/17 更新

docker.for.mac.localhostは、docker.for.mac.host.internalに変わるそうです。 Docker Community Edition 17.12.0-ce-mac46 2018-01-09 (Stable)から、docker.for.mac.host.internalが追加され、docker.for.mac.localhostはまだ継続して使えますが、おそらくどこかのバージョンで消えるものと思われます。

これでコンテナ -> ホスト上のサービスに、共通の設定で繋ぐことができます。

docker host portなどで調べると、nginxなどのWebサーバをコンテナで起動して、それにホストから接続するための設定のexposeや-pオプションが出てきます。ホスト->コンテナの方向の情報が多く、探すのに手間取りましたが、用意されていました。

ホストのポートを指定できるので、sshトンネリングなどで外部サーバとの通信経路を作っておけば、ローカルのコンテナから、外部サーバとの通信を行うといったことも可能です。

*1:docker 17.06からみたい

格安Android(g06+)買ってみた

持っているガラケーのバッテリー寿命が来て、5分も通話すれば落ちるぐらいになってしまいました。*1もう一度ガラケーに変えるという手もあるんですが、契約もめんどいので、MNPして格安SIMに電話番号も移そうかなと検討しています。それで今回移行する端末候補を買ってみました(まだMNPしたりSIM入れてないです)

選定条件は、基本電話を受けるだけなので、以下あたり

  • 4インチ以下の大きさ
  • android6以上で、新し目ないし、アップデート提供
  • 価格が高すぎない

最初、docomoXperiaシリーズのcompactを白ロムで買おうかなと思ったんですが、やはり3-6万ぐらいします。流れで、最近はかなり安いandroidもそれなりに出回っていることを知り、調べて行った結果、g06+*2というandroid7搭載で9,000円ぐらいのスマホを購入しました。1-2万円台ぐらいのHUAWEIのは、5インチ以上ばかりなので落選。

simseller.goo.ne.jp

amazonはOCN SIMセット*3

女性や子供など手が小さい人向けに特化し、4インチ液晶、2GBメモリという割り切った端末。同価格帯のよりはメモリが多いとのこと。外観は一昔前のAndroidという感じで高級感はないですが、シンプルで変ではないです。

ボディ標準色の赤色は、明るすぎず暗すぎずという感じで個人的には好きです。フロントは黒で、交換用のバックカバーが購入時に選べるので、そっちに変えることもできます。

android7が入ってるとはいえ、iPhoneほどの操作感はさすがになく、もたついたり、各種UIの慣れもあって雲泥の差。値段は1/10なので、そう考えると値段の割にはいいと思います。ただ、カメラは確実にチープなので使えないです。

個人的に電話を受ける+androidアプリの実験用なので、十分満たせると判断してます。androidはこういう特化型が出てくるのが面白いですね。Amazonでポチって翌日すぐ届くのもお手軽でした。

細かい使い勝手などは、他にも紹介されているので、細かいレビューはそっちを見た方が詳しいです。

2018/04/09 追記

急にWiFiが不安定になることが多くなり、SIMなし状態で使うのが厳しくなったので、別のAndroidに買い換えました。WiFiに繋がってるんだけど、通信ができていない/超低速状態になり、端末の再起動やWiFi設定を一旦削除したり試しましたが、解決せず。繋がることもありますが、使いたい時に使えないのは結構なストレスなので、買い換えとなりました。さすがに4インチの他の端末はないので、5インチ超を受け入れることに。

*1:私はガラケー(電話受け用)とiPhone7(データ+SMSのみのSIM)の2台持ち

*2:goo久々に名前聞いたなー

*3:2017/09/20 amazon CAPTCHA出てたのでただのリンクに変更しました