Androidのメモとか

ポキオの日記です。今日も遅延してない。

技術書典に向けてGoogle Drive上のファイル監視をGASからやってみる(前編)

久々のGAS案件。

ポキオ GoogleAppsScript GAS 技術書典

もうすぐ技術書典ですね(震)

執筆を加速させていきたいところですが、やっぱり締切駆動開発になりがちになってしまって、進歩しないなぁと思う今日このごろです。

ここで、この状況を打破すべく、他の人の進捗を監視して自分を戒めるシステムを構築してみようと思います!そんなシステム構築してる暇があったら、さっさと書けよ!

ポキオ GoogleAppsScript GAS 技術書典

某弊チームの技術書典向け原稿はGoogle Drive上で管理しているので、もしかしたらGoogle Apps Script(GAS)が使えるかもしれない!と思い、いろいろやってみたことをメモしていきます。

developers.google.com

GASで色々な情報をgetしてみる

まずはGoogle Drive上のファイルへのアクセスはDriveAppクラスが使えるはず。

developers.google.com

監視したいファイルやフォルダのIDが分かれば、そのIDから色々の情報が取得できます。

ポキオ GoogleAppsScript GAS 技術書典

たとえば、あるファイルの最終更新日を取得するには、こんな感じでコーディングしていきます。

function myFunction() {
  var id = 'xxxxx'
  var file = DriveApp.getFileById(id)
  Logger.log(file.getLastUpdated())
 }

これを実行すると、権限付与を求められますが、一度付与して実行すると・・・。

ポキオ GoogleAppsScript GAS 技術書典

こんな感じで最終更新日を取得することができます。一方で、技術書典を複数人で執筆していて、その進捗共有用のSpreadsheetの場合、最終更新日とともに誰が更新したのか気になるんですが、その情報はDriveAppクラスでは取得できないのです・・・

ポキオ GoogleAppsScript GAS 技術書典

実はDriveAppクラスとは別に、[リソース] > [Googleの拡張サービス]からDrive APIを有効にするとDriveクラスがGASから叩けるようになります。

developers.google.com

これは、いわゆるGoogle Drive APIで、APIでできることがGASから叩けるようになります。たとえば、先程の最終更新をしたのが誰かを取得するには、このDriveクラスを使っていきます。

function myFunction() {
  var id = 'xxxxx' 
  var file = Drive.Files.get(id)
  Logger.log(file.lastModifyingUserName)
 }

こんな感じ。で、実行すると・・・

ポキオ GoogleAppsScript GAS 技術書典

ちゃんと取得できましたー。(個人名なので伏せてますが・・・)

というわけで

なんとなくGoogle Drive上のファイルの情報を引き出せそうな気がしてきました。今後は、定期的にファイルをポーリングして監視したり、それを何かしらの形で通知する方法を考えていきたいところです。はやく執筆しろ。

enebular+IFTTTで夜になったらSonosスピーカーの音量を下げるようにしてみた

夜は静かに。

ポキオ Sonos IFTTT

ついつい音量上げたくなるやつ

Sonosのスピーカー「One」を使い始めて数週間。時間を見つけてはSonosで音楽を聞いてますが、ついつい調子に乗って音量上げがち。 でも、流石に夜は近所迷惑だったり、寝てる家族に申し訳ないので、ここはなんとか自動化で音量コントロールできないかと考えたわけです。

ポキオ Sonos IFTTT

幸運なことに、IFTTTでSonosの音量設定(Set Volume)ができるので、これをつかって音量コントロールをしてみたいと思います。

ちょっぱやで作るよー!

このSonosのActionを毎度おなじみのWebhooksのTriggerから発火するように設定し、enebular(Node-RED)から毎晩23時にそのWebhooksURLを叩くようにするシンプルな仕組みです。

ポキオ Sonos IFTTT

毎晩23時に発火させるには、Injectionノードの設定をちょっといじるだけ。

ポキオ Sonos IFTTT

これだけで、毎晩発火するようになりました。実際にWebhooksの設定は、次のFunctionノードで行っています。

msg = {};
msg.method = 'POST';
msg.headers = 'Content-Type: application/json';
msg.url = 'http://maker.ifttt.com/trigger/xxxxx/with/key/xxxxx'
msg.payload = {'value1' : '10'};
return msg;

value1に10を設定し、Webhooks側ではここで指定された数値の音量を設定するようにしています。ここで、数値は0-100まで指定可能です。まぁ、10%くらいに音量を絞っておけば文句は言われないでしょう。

これで音量設定を自動化できました!

毎晩23時になると、急に音量が10%になるようになりました。

IFTTTのSonos Actionsには、まだまだいろんなコントロールが可能なので、自分のライフスタイルにあった自動化ができそうですね!

[asin:B07HSBKTFH:detail]

今回のフローはこんな感じですー。

[
    {
        "id": "c5495b36.8b97c8",
        "type": "tab",
        "label": "Sonos Flow",
        "disabled": false,
        "info": ""
    },
    {
        "id": "7451e07.f12dc2",
        "type": "inject",
        "z": "c5495b36.8b97c8",
        "name": "毎日23時に実行",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "00 23 * * *",
        "once": false,
        "onceDelay": 0.1,
        "x": 140,
        "y": 60,
        "wires": [
            [
                "44f2a101.c42ae"
            ]
        ]
    },
    {
        "id": "b7541cbb.283a4",
        "type": "http request",
        "z": "c5495b36.8b97c8",
        "name": "IFTTTにHTTP-POST",
        "method": "use",
        "ret": "txt",
        "url": "",
        "tls": "",
        "x": 560,
        "y": 60,
        "wires": [
            [
                "68b920c2.b7034"
            ]
        ]
    },
    {
        "id": "44f2a101.c42ae",
        "type": "function",
        "z": "c5495b36.8b97c8",
        "name": "IFTTT Webhooks設定",
        "func": "msg = {};\nmsg.method = 'POST';\nmsg.headers = 'Content-Type: application/json';\nmsg.url = 'http://maker.ifttt.com/trigger/xxxxx/with/key/xxxxx'\nmsg.payload = {'value1' : '10'};\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 340,
        "y": 60,
        "wires": [
            [
                "b7541cbb.283a4"
            ]
        ]
    },
    {
        "id": "68b920c2.b7034",
        "type": "debug",
        "z": "c5495b36.8b97c8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "x": 730,
        "y": 60,
        "wires": []
    }
]

SonosをIFTTT経由でコントロールしてみる(後編)

SonoSwitchをつくるお!

ポキオ Sonos IFTTT

前回までのあらすじ

SonosはIFTTTから制御できそうというところまでわかりました。

relativelayout.hatenablog.com

今回は、IFTTTのSonos Actionsを使うべく、WebhooksをTriggerとして、M5StackからIFTTT経由でSonosのスピーカーの制御をしてみようと思います。

M5Stackって?

詳しい説明は省きますが、ディスプレイやWi-Fi/BTなどがもろもろついた小さなマイコンボードです。

m5stack.com

プログラミング方法も色々ありますが、ブラウザ上でノンコーディングでプログラミングできるUI Flowを使って実装してみようと思います。

やりたいことは以下の通り。

  • Sonosのスピーカーを制御(Prev/Next/Pause)できるSonoSwitch
  • おしゃれなUIを表示
  • ボタンを押すと制御(Prev/Next/Pause)が行えるようにする
  • 裏ではIFTTTのWebhooksへHTTP-GETを行う

ポキオ Sonos IFTTT

IFTTT側の設定

先述の通り、TriggerをWebhooks、ActionをSonosとなるようにレシピを設定します。

ポキオ Sonos IFTTT

レシピは別々のWebhooksイベントで3つ作成します。今回は、それぞれのイベント名をこのようにしました。

  • sonoswitch1:Skip to previous
  • sonoswitch2:Pause
  • sonoswitch3:Skip to next
To trigger an Event
Make a POST or GET web request to:

https://maker.ifttt.com/trigger/{event}/with/key/{key}

それぞれのイベントごとにURLが決まり、ここにHTTP-GETをするとSonosのActionが発火するようになりました。今度は、M5StackからこれらのURLをHTTP-GETできるようにしていきます。

つぎにM5Stack側の実装

とはいえ、まずは(本質的ではないですが)UIを作ってみます。

ポキオ Sonos IFTTT

macOSKeynoteでこんな感じのUIを作ってJPGで保存し、UI Flow経由でM5Stackに流し込みます。SonosのロゴのフォントはGIll Sansが一番近かったです(笑)

UI Flowでは、こんな感じに実装していきます。

ポキオ Sonos IFTTT

MicroPythonのコードは、この記事の後ろの方で晒します。やっていることはざっくりこんな感じで、

  • 起動時にWi-Fi接続
  • ボタン押下時にそれぞれのレシピへのWebhooksへHTTP-GETを送るようにする
  • HTTP-GET成功/失敗時に効果音を出す

これをUI Flowで組んでいきます。

つかってみますー

これが、ふつーに使えます(笑)

ポキオ Sonos IFTTT

Sonosのスピーカーに直接コマンドを送っているわけではないので、1〜2秒のタイムラグはあるものの、Sonosのスピーカーの制御がちゃんとできています!

逆に言えば、インターネット回線さえあれば、理論上は地球の裏側からもSonosのスピーカーを制御できるということですねー。すごいー。

[asin:B07HSBKTFH:detail]

コードはこんな感じです

from m5stack import *
from m5ui import *
from uiflow import *
import wifiCfg
import urequests

setScreenColor(0x222222)




image0 = M5Img(0, 0, "res/SonoSwitch.jpg", True)

statusCode = None


def buttonB_wasReleased():
  global statusCode
  if not (wifiCfg.wlan_sta.isconnected()):
    wifiCfg.reconnect()
    while not (wifiCfg.wlan_sta.isconnected()):
      pass
  try:
    req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch2/with/key/xxxxxxx', headers={})
  except:
    pass
  statusCode = req.status_code
  pass
btnB.wasReleased(buttonB_wasReleased)

def buttonA_wasReleased():
  global statusCode
  if not (wifiCfg.wlan_sta.isconnected()):
    wifiCfg.reconnect()
    while not (wifiCfg.wlan_sta.isconnected()):
      pass
  try:
    req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch1/with/key/xxxxxxx', headers={})
  except:
    pass
  statusCode = req.status_code
  pass
btnA.wasReleased(buttonA_wasReleased)

def buttonC_wasReleased():
  global statusCode
  if not (wifiCfg.wlan_sta.isconnected()):
    wifiCfg.reconnect()
    while not (wifiCfg.wlan_sta.isconnected()):
      pass
  try:
    req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch3/with/key/xxxxxxx', headers={})
  except:
    pass
  statusCode = req.status_code
  pass
btnC.wasReleased(buttonC_wasReleased)


statusCode = -1
wifiCfg.autoConnect(lcdShow = False)
while not (wifiCfg.wlan_sta.isconnected()):
  pass
speaker.tone(1800, 100)
while True:
  if statusCode > 0:
    if statusCode == 200:
      speaker.tone(1800, 100)
      speaker.tone(2400, 100)
    else:
      speaker.tone(1800, 300)
    statusCode = -1
  wait_ms(2)

SonosをIFTTT経由でコントロールしてみる(前編)

みんな大好きIFTTT!

ポキオ Sonos IFTTT

IFTTTって?

知っている人も多いハズのこのサービス。

ポキオ Sonos IFTTT

いろいろなサービス同士を結びつけてオートメーション化するサービス。実はSonosのスピーカーはIFTTTに対応しているんです。今回は、IFTTTで何ができるのか?というところを軽く探ってみようと思います。

連携はかんたん

ExploreからSonosと検索すると、かんたんにみつかりました。

ポキオ Sonos IFTTT

このページのConnectを押してやると、Sonosアカウントと紐付けができます。

ポキオ Sonos IFTTT

このあたりがGrantされるPermissionたち。See what...とありますが、執筆時時点ではそれを利用した機能はなさそうです。(詳しくは後述)

使い方

レシピのアクションにSonosを指定するだけ。

ポキオ Sonos IFTTT

…そう、SonosはIFTTTに対応しているものの、Triggerとしては使えないようです。なので、先程のSee what...のように「いま聞いている楽曲情報をTweetする」みたいなSonosがTriggerとなるレシピは作成することができません。必ず、他のサービスがTriggerとなりSonosが動き出すといった形になります。

では、IFTTTのアクションでは何ができるのかというと・・・

ポキオ Sonos IFTTT

  • Play Favorite
  • Play Stream
  • Skip to Next/Previous Track
  • Pause/Resume
  • Volume Up/Down
  • Set Volume
  • Mute/Unmute

このような、一通りの操作が可能です。Triggerにはなれないものの、これだけ幅広い制御がActionとして可能なので、夢が広がりそうですね。

ポキオ Sonos IFTTT

ちなみに、Actionは実行するGroupやスピーカーを設定できます。家のSonosスピーカーの制御がIFTTT経由でできるってちょっとすごいですよね・・・。Triggerは同じネットワーク上にいなくて良いわけですから・・・。次回は、このActionを使った例を紹介します!続く!

[asin:B07HSBKTFH:detail]

GeekservoでLEGOを自走させてみた

うごくぞー!

ポキオ Geekservo LEGO サーボモーター

LEGO、いいよLEGO

先日、LEGO互換のサーボモーターと手に入れてニヤニヤしていました(笑)

relativelayout.hatenablog.com

せっかくなので、これをLEGOで作ったクルマに取り付けてみて、走らせてみます。

車体はこんな感じ

もう購入から20年近く経っているLEGOをかき集めて、こんな感じの車体を作りました。

ポキオ Geekservo LEGO サーボモーター

サーボモーターに中くらいのタイヤを直付けしています。このタイヤはLEGO TECHNIC用のやつなので、シャフトが刺さるようになってます。

ポキオ Geekservo LEGO サーボモーター

フロントのタイヤは小さめのタイヤに、自由に回転するパーツを組み合わせることで、小回りが効くようになっています。ステアリング自体をサーボモーターで制御するのではなく、リアにある2つの独立したサーボモーターを制御することで左右に曲がれるようにしています。

マイコンを載せて、走り初め!

この車体に、Arduino UNOと、モバイルバッテリーを積んで、サーボモーターと接続してみます。

[asin:B0044X2E5S:detail]

この投稿をInstagramで見る

#LEGO を #Arduino で走らせてみた。なんかかわいい。

pokio(@pokiiiiio)がシェアした投稿 -

後述のコードをArduino UNOに焼くと、こんな感じで走ります。今回は、動き方自体をハードコードさせているので、ラジコンのように意のままに動かすことはできませんが、通信部材がついているような別のマイコンで動かせれば、ラジコン的な使い方も可能です。

というわけで、

とりあえず、チョッパやで作ってみました。

  • サーボモーターに個体差があり、回転速度が異なる
  • マイコンとモバイルバッテリーをオシャレに取り付けたい
  • USBケーブルが長くてダサい

など、いろいろ改善の余地はありますが、まずは動いたのでOKとさせてください(笑)

コードはこんな感じ

A0A1につないでますが、多分どのピンでも大丈夫なはずです。

#include <Servo.h>

Servo servo1;
Servo servo2;

void setup() {
  servo1.attach(A0);
  servo2.attach(A1);
}

void loop() {
  servo1.write(0);
  servo2.write(180);
  delay(2000);

  servo1.write(90);
  servo2.write(180);
  delay(2000);
  
  servo1.write(180);
  servo2.write(0);
  delay(2000);

  servo1.write(180);
  servo2.write(90);
  delay(2000);
}

レゴ(LEGO) テクニック ランドローバー・ディフェンダー 42110

レゴ(LEGO) テクニック ランドローバー・ディフェンダー 42110

  • 発売日: 2019/10/04
  • メディア: おもちゃ&ホビー

リングフィットアドベンチャー課金と新年

やせたい。

ポキオ リングフィットアドベンチャー 課金

あけましておめでとうございます

今年もよろしくおねがいします。

今年は腹筋割りたい、そう思って年末にリングフィットアドベンチャーを買ってしまいました。

この投稿をInstagramで見る

サンタ、さっき来た。 #ringfitadventure

pokio(@pokiiiiio)がシェアした投稿 -

リングフィット アドベンチャー -Switch

リングフィット アドベンチャー -Switch

  • 発売日: 2019/10/18
  • メディア: Video Game

毎晩のように子供を寝かしつけてから、夫婦揃ってやってるわけですが・・・。

思った以上にツライ

どうせSwitchだしヌルゲーなんでしょ?って思ってたんですが、これが相当つらい。

ポキオ リングフィットアドベンチャー 課金

下半身だけじゃなくて、上半身も使った運動をしないと、ゲームをクリアできないようになってるんだけど、上半身の筋肉がなさすぎて、本当にツライ。 やり始めてから、何日かすると腹筋が悲鳴を上げ、ニートゥーチェストとプランクっていう2大巨頭が本当に嫌になりました(笑)

ついつい課金

いままで筋トレなんて絶対にしないと思っていたわけですが、だんだんなれてくると楽しくなってきてしまって(笑) ただ、楽しくなってくると、いろいろ装備を見直したくなるわけです。

ポキオ リングフィットアドベンチャー 課金

まずは、夜中に足踏みして大きな音を立てなくなかったので、ヨガマットを買いました。ヨガマットなんてリングフィットアドベンチャーに出会ってなければ買ってなかったと思います(笑)

全然ヨガマットはどこのメーカーが良いとか全く知らないんですが、たまたま見つけたこのヨガマット。あのPC周辺機器で有名なエレコムが作ってるヨガマットらしくて・・・。その意外性と、厚み8mmなのに割と安かったので購入してしまいました。

一軒家なので、そこまで物音立てても怒られることはないですが、ヨガマットのおかげでプレイ中の音がいい感じに弱まったのと、クッション性があるので筋トレにぴったりです。

明治 ザバス ウェイトダウン ヨーグルト風味【16食分】 336g

明治 ザバス ウェイトダウン ヨーグルト風味【16食分】 336g

  • 発売日: 2016/05/31
  • メディア: ヘルスケア&ケア用品

そして、せっかく運動するのでプロテインも買ってみました。プロテインも人生で初めて買ったので、何が良いかよくわからなかったんですが、ウェイトダウンという文字にやられて買ってしまいました。効果の程はまだわかりませんが、思いの外飲みやすいですねぇ。粉っぽさは否めませんが、これでウェイトダウンできるなら全然よいです。

というわけで

これからもシックスパック目指してがんばります。お正月に嫁の実家に行くときも、Switch一式持って参戦しようかと思います(笑)

今年もありがとうございました!来年もよろしくおねがいします!

お世話になりました・・・!

ポキオ 2019年 ありがとう 2020年 よろしく

今年もありがとうございました!

一年を振り返ると、いろいろあったなーと。そしてなにより、たくさんの機会を作っていただけた皆様、本当にありがとうございました。

今年は(も)、ツールの進化に驚かされました。というのも、ハードを作るにもソフトを作るにも便利なツールが沢山登場してきていて、ものづくりのハードルが本当に下がってきていると実感しています。もちろん、Qiitaなどのナレッジ共有も豊富なので、検索すればすぐに情報が手に入る状況。だからこそ、何が作れるかということより、どういうアイディアで何を作るかにシフトしてきているような気がしています。要はアイディア勝負。来年こそはちゃんとアイディアを量産していきたいところ・・・。

イベントにも参加しましたー

今年もデブサミで登壇させていただきました。 relativelayout.hatenablog.com

また、メイカーフェアにも参加。 relativelayout.hatenablog.com

ご協力頂いた方々、ご覧になった方々、ありがとうございました。

新たなチャレンジも

一時期、レーザーカッターにどハマリしてました・・・。おかげさまでCADソフトのノウハウが溜まった気がする。 relativelayout.hatenablog.com

また、新居購入に伴って、日曜大工にもどハマリ。無駄に工具を揃えました。工具は沼ですが、DIYの可能性は無限大です。 relativelayout.hatenablog.com

あと、Node-RED。今年も大変お世話になりました。今年はノード職人になってみました。 relativelayout.hatenablog.com

そして、ここに来てYoutuberデビュー(笑)まだまだヒヨッコですが、ご視聴のほどよろしくお願いします。 relativelayout.hatenablog.com

最後にSonos。新しいガジェットを手に入れたので、これからいじり倒そうと思います。 relativelayout.hatenablog.com

というわけで、

来年も何卒よろしくおねがいします!!!

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。