電子工作〜まずはモーターを動かしてみる
電子工作始めてみた
猫との暮らしをより良くできるものが作れたら〜と思い電子工作を始めた
まずは安全ないたずら防止としてキッチンに猫が上がったら霧吹きで水をかける装置を作ってみたい
ということで、、
じゃーーーん!秋月電子ECで色々購入しました〜(注文翌日に届くという爆速感)
これらの材料を使ってまずはモーターを動かすところまでが今日の目標!
モーター動かすぞお
モーターはタミヤのギアボックスを買い、組み立て始めたけど...
部品多っ!小さい部品多っ!!猫が誤飲したらどうするんじゃ^-θωθ-^
開始10分ほどでギアボックスの組み立ては諦め、DCモーターのみを使うことにした
DCモーターを動かす記事を見てこれらの材料を調達したが、使い方がイマイチわからぬ。。
なんかいい動画ないかなーと探すと電子工作入門Udemy講座があった!!!
会社でUdemy学び放題入っていて良かった〜〜〜〜
動画を見ながらブレッドボードに線を差し込んで、、、はい!モーター動いた!!
てゆうか、モーター動きすぎなんですよねー。。こんな激しく動くと思わなかった
あとモーター動くと焦げ臭い?感じがしてなんか嫌
さあここからが本題だ!
自動で霧吹きが出る装置を作りたいのでモーターを動力に霧吹きのレバーを引けるようにしたい
ということで、このモーターに紐を結んでその紐を霧吹きのレバーにも結んで電源ON!!
はい。モーターが激しく回りすぎて紐が吹っ飛びました〜〜
紐の結び目ををセロテープで補強したところで全然ムダ!!
モーターの回転する軸に割り箸を挟んでみても割り箸が吹っ飛ぶだけ
見つけた課題
やってみないと分からないのが電子工作!次はこんな改善をしたい
- モーターの回転速度を遅くするorギアをつけるなどして回転速度を遅くする?
- 霧吹きのレバーに結びつけた紐を巻き取れるようにする
- ただ回転するだけだと紐は巻き取られないってことも今日分かった笑
Puppeteerをtypescriptで使う
前回はseleniumを使ってみたので今回は別のブラウザ操作ライブラリPuppeteerを使ってみます!
Seleniumをtypescriptで使ってみる - buto > /dev/null
Puppeteerインストール
npm install puppeteer
ブラウザ操作コードを書きます!
今回もこちらのログイン画面を操作します
puppeteerはchroniumという軽量chromeが一緒にインストールされているので
特に指定しなければchromeが動いてくれます
const puppeteer = require('puppeteer'); const assert = require('assert'); /** * ログイン成功 */ (async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://localhost:3000'); // IDパスワードを入力 const userId = await page.$('#loginId'); await userId.type('xxxxx'); const password = await page.$('#password'); await password.type('xxxxxx'); // ログイン const loginButton = await page.$('#loginButton'); await loginButton.click(); await page.waitForTimeout(3000); // 支払い一覧ページへ遷移していること assert.strictEqual(await page.url(), "http://localhost:3000/payment"); await browser.close(); })();
seleniumと比較するとコード量が少ないです!
あらかじめ npm run serve
で開発サーバにアプリをホスティングしておき
node loginTest.ts
で上記テストコードを実行しましょう!
ブルーのchroniumアイコンが起動します
動きはseleniumと同じです
Seleniumをtypescriptで使ってみる
画面開発でコーディングと動作確認を交互にしていると 毎回フル桁を入力して、ボタン押下して、結果確認して…の流れが結構辛い。
ということで、javascriptコードでブラウザ操作を自動実行してくれるseleniumを始めよう!(今更感)
seleniumインストール
何事もまずはnpm installから!!
npm install selenium-webdriver
次にseleniumが使うブラウザドライバーをダウンロードします
ダウンロードしたドライバーはプロジェクトのルートディレクトリに配置しておきます
TypeScriptでブラウザ操作コードを書く
シンプルなログイン画面にID、パスワードを入力してログインボタンを押下してみます
まずはtsファイルを作成してお作法コードを書きます インストールしたseleniumを使うよ!宣言とchromeの設定です
const webdriver = require('selenium-webdriver'); const { Builder, By, until } = webdriver; const assert = require('assert'); const capabilities = webdriver.Capabilities.chrome(); capabilities.set('chromeOptions', { args: [ '--headless', '--no-sandbox', '--disable-gpu', `--window-size=1980,1200` ] });
次にテキストボックスへの入力、ボタン押下、結果のassertを行います
/** * ログイン成功 */ (async () => { const driver = await new Builder().withCapabilities(capabilities).build(); await driver.get("http://localhost:3000"); // IDパスワードを入力 let userId = await driver.findElement(By.id('loginId')); userId.sendKeys("xxxxx"); let password = await driver.findElement(By.id('password')); password.sendKeys("xxxxx"); // ログイン let loginButton = await driver.findElement(By.id('loginButton')); loginButton.click(); await driver.wait(until.elementLocated(By.id('paymentList')), 10000); // 支払い一覧ページへ遷移していること assert.strictEqual(await driver.getCurrentUrl(), "http://localhost:3000/payment"); driver.quit(); })();
あらかじめ npm run serve
で開発サーバにアプリをホスティングしておき
node loginTest.ts
で上記コードを実行しましょう
自動でchromeが起動してログインを再現してくれます!!
Flutter インストールからメニュー表示まで
久しぶりにモバイルアプリを作ってみたくなったのでflutter始めました
iOS・Androidを同じコードで開発できるので効率的です
Flutterインストール
まずはhomebrewでFlutterをインストールしてdoctorコマンドでFlutterの利用開始チェックをする
(XcodeとAndroidStudioが入っていればチェックOKなはず)
brew install flutter flutter doctor
Flutterプロジェクト作成
インストール完了したらFlutterプロジェクトを作成します
--org
オプションでパッケージ名を指定できます(指定なしだと com.example
となる)
flutter create --org package project_name
プロジェクトが作成できたら標準出力に従ってアプリを起動!
cd project_name flutter run
プロジェクト作成直後の画面 カウントアップボタンのみがあるシンプルアプリ
画面をカスタマイズ
↑画面コードは project_name/lib/main.dart
に書かれているのでこちらを修正していく
まずはこんな感じで画面を修正しました
- アプリタイトルを変更
- AppBarの表示文字・カラーを変更
- サイドメニュー(Drawer)を追加
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'framboise nail', // ブラウザタブ表示名 theme: ThemeData(primarySwatch: Colors.blue), home: const MyHomePage(title: 'my page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.pinkAccent.shade700, ), drawer: Drawer( // サイドメニュー child: ListView( children: <Widget>[ DrawerHeader( child: const Text( 'risa', style: TextStyle( fontSize: 24, color: Colors.white ), ), decoration: BoxDecoration(color: Colors.pinkAccent.shade700), ), const ListTile( title: Text('カタチから探す'), ), const ListTile( title: Text('スクエア'), trailing: Icon(Icons.square), ), const ListTile( title: Text('ラウンド'), trailing: Icon(Icons.circle), ), const ListTile( title: Text('オーバル'), trailing: Icon(Icons.egg), ), const ListTile( title: Text('ポイント'), trailing: Icon(Icons.water_drop), ) ], ), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const <Widget>[ Text( 'You have pushed the button this many times:', ), ], ), ), ); } }
このようにプロジェクト作成直後から画面をカスタマイズできました!
サイドメニューは利用頻度が高そうなのでサラッとコード書けるようにしておきたい
ちょっとしたカスタマイズですが、何時間も掛かってしまいました…
webpack フロントエンドでも環境変数を扱う
React+SpringBootアプリでローカル、ステージング、本番環境用に環境変数ファイルがあって、それぞれに接続するAPIアドレスなどが定義されているのはよくあるケース
SpringBootで環境変数を読み込むのは何度も行ってきましたが、Reactで環境変数にアクセスしたことなかった!
今回フロントエンドはwebpack+Reactだったのでwebpackを使って環境変数を読み込む
そもそもwebpackの話
web資材(js、css、画像などのファイル)をpacking(まとめる)するツール
この記事のようにindex.jsなどのエントリポイントから参照される各モジュール(画面コンポーネントなど)をひとまとめにできる!
まとめる設定をwebpack.config.jsファイルに記述する
DefinePluginで環境変数を読み込む
あらかじめlocal.envなどの環境変数ファイルをサーバ内に環境変数として読み込まれるようにしておく
今回はdockerだったのでdocker-compose.ymlにビルド実行するコンテナのenv-filesにlocal.envを指定した
webpack.config.jsにDefinePluginを記述して環境変数をフロントエンドのグローバル変数に置き換える
local.envに定義したAPI_GATEWAYはprocess.env.でアクセスしグローバル変数API_HOSTに格納
const webpack = require('webpack'); module.exports = { mode: 'development', plugins: [ new webpack.DefinePlugin({ 'API_HOST': JSON.stringify(process.env.API_GATEWAY || "") }), ] };
実際にAPI接続するモジュールで declear const API_HOST: string;
と記述すると環境変数の値が利用できる
環境変数を扱う方法にはdotenv、dotenv-webpackもあるがライブラリを追加したくない場合はこの方法が使える
AWSメッセージキュー SQS
昨日はSNSがモバイル通知、分析用Firehorseなど複数の宛先へデータを流すことができると学んだので
今日はSQSの特徴を学んでいく!!(SESはEメール通知専用っていうのは知ってるからスキップ)
Amazon SQS
SNSのアイコンと比べると宛先は1つになる?中央の四角がキューを表している??
貯まったメッセージは受信側(Consumer)がキューに問い合わせを行うと、キューからメッセージが配信されて、受信側はメッセージを取得することが出来ます。
SNSはメッセージ発行元(publisher)から一方通行でデータが流れたけど
SQSはpublisherがキューにメッセージを入れて、consumerがポーリングでキューからメッセージを取り出すようだ
SQSを試してみる
マネジメントコンソールでSQS作成をしてみると、スタンダードとFIFOが選べる
配信順序を気にしなければスタンダードで良さそう(FIFOの方が割高)
スタンダードキューを作成してみたのでメッセージの送受信をクリックしてみた
メッセージ本文を入力してメッセージ送信をクリック!
メッセージがキューに送られたので利用可能なメッセージが1となった
自動でポーリングされないようだったのでメッセージをポーリングをクリックするとポーリングが開始された
メッセージが届きました!
SNSと連携
SQSのメニューにSNSサブスクライブとあったので昨日作成したSNSトピックを紐付けてみた
SNSで「わああああああ〜!」とメッセージを発行してみると
昨日作成したSMS通知がちゃんと届いたのと同時にSQSにもメッセージが渡ってきた!
SNSからSQSにメッセージを渡せる機能なのか!
EC2上のアプリからSNSで通知+SQSにデータを流してSQSから他のEC2アプリにデータを連携する時使えそう!
SQSはアプリ間連携に使えるメッセージキューということが分かった
AWSメッセージキュー SNS
AWS資格試験の模擬テストにメッセージキューが頻出するけど違いが分からない、覚えられないのでまとめておく。
AWS複数種類のメッセージキュー(MQ)が提供されているから1つずつ覚えていきます!
メッセージキューってなに??
メールやSMSメッセージ通知をする時にメッセージ作成アプリ→配信アプリに橋渡しをするキュー
メッセージキューって名前だけどメッセージ配信以外のアプリ間データ連携に利用されている
直接アプリ同士で連携してもいいけど、大量データだとアプリサーバに負荷が掛かっちゃうのでMQはよく使われるらしい
キューなので渡されたデータから処理されていく(先入先出)
Amazon SNSとは
サービスアイコンは左側から入ったデータがフィルタされて複数に流れるような
Amazon Simple Notification Serviceって名前の通り通知(SMS・プッシュ通知)によく使われる
SNSでスマホにメッセージ送信
トピック(後述)のタイプをスタンダードにするとSMS・プッシュ通知などのメッセージ通知ができ
FIFOにするとSQSのみ選択できた(こちらはアプリ間データ連携に使う時に選択するっぽい)
トピックを作成しなくても左メニューSMSを選択して電話番号を登録
ワンタイムパスワードで認証後、テストSMSが送信できる
今度はスタンダードタイプのトピックから送ってみる
トピックを選択してSMS送信をサブスクリプションに設定すると、こんなメッセージが届いた(一番下)
トピックから送信するとメッセージの先頭に「トピック名>」って付くみたい
アプリからSMS通知するには
携帯電話に発行する - Amazon Simple Notification Service
公式ドキュメントにコードから電話番号を動的に渡してAmazon SNSからSMS通知できるみたい
あらかじめトピックを作っておかなくてもSMSが送れるように見える
Amazon SNS トピックを作成する - Amazon Simple Notification Service
トピックは配信先のグループなので「メッセージ配信+配信内容を分析するRedshiftにデータ登録」を実現したい時に
トピックのサブスクリプションにSMS通知、kinesisFirehorseを登録してあげればトピックでメッセージ発行をすると
SMS通知が届き、一方ではFirehorse経由でRedshiftにデータが登録されました〜となる