2018年版、Rustで多次元配列を使うには
背景
の方法が最近のRustでは使えないことが判明。
2018年7月時点でのRustで多次元配列を扱う方法
ndarrayを使うのがお手軽な模様。
Cargo.tomlに以下を追加
[dependencies] ndarray = "0.11.2"
ndarrayでの多次元配列の使用例
以下の様なコードで、 1x2x3x4のサイズの4次元配列が扱える。
extern crate ndarray; use ndarray::ArrayD; use ndarray::IxDyn; fn main() { let mut b = ArrayD::<f32>::zeros(IxDyn(&[1,2, 3, 4])); println!("b = {}",b); }
関連記事
- Rustで多次元配列を扱うには
- Rustでコマンドラインアプリでキーが押されたかの判定しつつ、別の処理も進めるには
- RustでWebカメラの映像をコマンドプロンプトに出すコマンドを作った
- Surface Goのカメラ映像をRustでコマンドプロンプトに表示した
6年前の記事
5年前の記事
4年前の記事
2年前の記事
アレクサで「iPhoneを探す」をpuppeteerを使って出来るようにした
おはようございます。卒園式のDVDが完成し、その上映会を行い、久しぶりに長男の保育園の皆さんと再会し、寿退職された担任の先生、0歳児から担当してくれて、昨日はお泊り保育明けの先生も来てくださり、子供たちも再開を喜び、上映会も楽しめたようです。@kjunichiです。
既存方法の問題点
実は、このアレクサで「iPhoneを探す」は、IFTTT経由でiPhoneに電話をかけることで実現する方法がずいぶん前からあったのですが、 多分これは、日本ではできそうではないですし、電話代がかかる心配もあって見送っていました。
もう一つ
に紹介されている方法ですが、多分これも、2要素認証で運用していると面倒そうなことが、 利用しているiCloudライブラリpyicloudのGithubページを斜め読みする限りでは伺えました。
puppeteerで実現した
今回取った方法は、最近2要素認証でもブラウザ経由でiPhoneを探すのリンクに直接アクセスすると、自分の環境では、 2要素認証を回避してアクセスできるので、これで行けるかも?と思い試した。
なお、puppeteerの起動は、IFTTTでAlexaのトリガーを仕掛けて、Dropbox経由でローカルのPCにファイルを作成し、 PC側でこのファイルの作成を監視するとこで実現した。
いきなりAppleの嫌がらせにあうの巻
何故か、iframeで認証ページ、iPhoneを探すページとも組まれており、devtoolsで要素名を調べてもpageオブジェクト経由では アクセスできないようになっていました。
以下のページが大変参考になりました。
また、そもそも今回puppeteerを始めて使ったので、全般的なコードは公式ページの他、以下のページが参考になりました。
成果物
TARGET_ID、TARGET_PWD にiCloudのアカウントを入れて、TARGET_PHONE_NAME は対象のiPhoneに付けている名前を入れる。 そして、pathはDropboxのパスを入れることで、動くはず。
const fs=require('fs') const puppeteer = require('puppeteer'); const TARGET_ID = "test@mac.local"; const TARGET_PWD = "password"; const TARGET_PHONE_NAME = 'iphonename'; const path="D:/Dropbox/Amazon Alexa"; const findmyiphone = () => { (async () => { const browser = await puppeteer.launch({headless: false}); const page = await browser.newPage(); page.goto('https://www.icloud.com/#find'); await page.waitFor(12000); const dimensions = await page.evaluate(() => { return { text: document.body.innerHTML }; }); //console.log('Dimensions:', dimensions); //await page.type("input#account_name_text_field", "input"); //await page.screenshot({path: 'example.png'}); const frame = await page.frames().find(f => f.name() === 'auth-frame'); await frame.type("input#account_name_text_field", TARGET_ID); const tform = await frame.evaluate(() => { return { text: document.body.innerHTML }; }); await frame.click('i'); await frame.waitFor(1000); //await frame.waitFor('input#password_text_field',{timeout: 1000}); await frame.type("input#password_text_field", TARGET_PWD); await frame.click('i'); await page.waitFor(12000); const frame2 = await page.frames().find(f => f.name() === 'find'); await frame2.click('label[id="sc2348-label"]') await frame2.click(`div[title="${TARGET_PHONE_NAME}"]`) await frame2.click('div[title="このiPhoneでサウンドを再生"]') //console.log(tform); await browser.close(); })(); } fs.watch(path, (event, filename) => { if(filename&& event =="rename") { if(filename.startsWith("AmazonAlexa_findmyiphone")) { console.log("Find my iphone!") findmyiphone(); } } console.log(event,filename) });
あとがき
puppeteerでGUI非表示でやらせたかったものの、GUI表示しないと、エラーとなり、 まぁ、自分の用途では何が何でも非表示する必要もなかったので、これは放置してます。
また、Dropboxでのファイル作成もWindowsではIFTTTのデフォルトの日付入りだとファイルが作成されないので、 固定のファイル名にする必要があった。
参考資料
この記事を書いてからしばらくたちますが、以下のようにpuppeteerに関して日本語で書かれた書籍も最近は 出版されているようです。
関連記事
- 2018年春版Raspberry Pi 3の3.5mmジャックからAlexaを出した
- homebridge-camera-isightで外付けUSBカメラ(Microsoft® LifeCam HD-3000)を使うには
- puppeteerで動的にウインドウの大きさを変更するには
11年前の記事
6年前の記事
2年前の記事
1年前の記事
goroutineを使って高速にLAN内の*.localなホスト名の一覧を取得するツールを作った
こんばんは。次男が週末に初の保育園のお泊り会がある@kjunichiです。
- 作者: Katherine Cox-Buday,山口能迪
- 出版社/メーカー: オライリージャパン
- 発売日: 2018/10/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
背景
DHCPでLANに繋げる環境であれば、 raspberry piなどえはraspberrypi.localというホスト名でsshできたり、macOSなどでも ホスト名.localで手軽にアクセスできるため、/etc/hostsすら編集しなくても便利にリモートPC等に アクセスできる。
しかし、このホスト名が何か分からない場合、少なくともmacOSのdns-sdコマンドではDNSの逆引きに 相当することが出来ず、数年間途方に暮れていた。。avahiはこれが出来るのを知っていた。
SOで以下のページを発見するも、最近までdigコマンドに結構なスターがついている意味が まるで分らなかった。
最近になって、このdigコマンドが、21世紀のnslookupでmDNSにも対応しているので、 これでmacOSでもdigコマンドでホスト名.localをIPアドレスから逆引きできることが分かった。
IPアドレスから逆引きしてホスト名.localな名前を引くことが出来ることが分かったので、 LAN内のIPアドレスを片っ端から引数に指定して結果を表示すれば、やりたかった LAN内に現在どんなホスト名.localが存在しているのかコマンドができる。
コマンドラインで存在しないIPアドレスを指定して以下の様にdigコマンドを実行すると
dig +short -x 192.168.0.9 @224.0.0.251 -p 5353
かなり、待たされる。
ということで、Goでgoroutine使って、並行にコマンドを実行すれば良いのでは? ということを思いついた。
Goで外部プロセスの実行結果を取得する処理は「Raspberry Piの温度をgRPCを使ってElectronで作ったデスクトップマスコットに表示させた」の記事で習得済み。
学べたこと
同時に実行するコマンド数を絞りつつ、複数同時に実行する
さすがに、digコマンドに渡す引数のIPアドレスをクラスCで1から254まで指定してそれを同時に実行するのは ちょっとOSに優しくないだろうということで、同実行数を絞りつつ実行する方法を 探した。
今回のコードの大枠はこちらのコードをベースにさせてもらった。
for内でgoroutineを実行する際にやりがちなミスを学習
goroutineに渡しているループ変数は、ループされる度に作られる変数ではなく、 ループ全体で使われる変数
ただし、上の例だと文字列のアドレスを渡すことになるから この問題は発生しないのかも?と思いもしたが、Sleep消したら駄目だった。。。
ちなみに、この問題、VS Codeのおかげで早期に発見できた。
sprintf的なものがある
テンプレートの仕組みも見つけるも、ちょっと大げさだったので、 Cのsprintf的なものも見つけたので、今回はこちらを採用した。
成果物
こうして、今回も実際に自分の手を動かして取り組んだところ、多くの学びがあった。
今後の課題
- 192.168.0.0/24に決め打ちのIPアドレスを可変にする
あらたな使い道
iPhoneがWifi接続になっていると、dareka-no-iPhone.localなどと一覧に表示さるので、自宅に自分や奥さんがいるかをコマンドラインでチェック可能になった
参考資料
今回はavahiのないmacOSで逆引きする方法としてdigコマンドを用いて行ったが、Windowsでもdigコマンドを インストールすることが以下の記事によると出来るようなので、たぶんWindowsでも動くのでは。
関連記事
- Electronで自分のIPアドレスをLAN内のiPhoneに通知するには
- Go言語でコマンドプロンプトに画像を表示するコマンドを作って、Vimの:terminalで表示させた
- WindowsでmrubyからGoで作ったライブラリを呼び出して、Webカメラの画像をコマンドプロンプトに表示した
- GIMPのプラグインをGoで書く(その1)
- WindowsだけでAmazon DashボタンのMACアドレスを取得できるjsを書いた