GoPro をライブカメラにしてターミナルから操作する

👉 【無料】使わなくなったスマホをライブカメラにしておじいちゃんを監視したい 

GoProはパソコンとWiFi接続で接続できますよね。

このとき、
10.5.5.9 をルータとしたローカルネットワークとなり、
パソコン側は、10.5.5.10? のアドレスが割り振られます。

非SSL通信です。

録画を開始・停止する

今、このページを見ているパソコンをGoProにWiFi接続すると

以下のただのリンクをタップして操作できます。

まず、ストリーミングを(再)起動して、

[→ (再)起動]


http://10.5.5.9/gp/gpControl/execute?p1=gpStream&a1=proto_v2&c1=restart

録画開始して、

[→ 録画開始]


http://10.5.5.9/gp/gpControl/command/shutter?p=1

そして、録画停止。

[→ 録画停止]


http://10.5.5.9/gp/gpControl/command/shutter?p=0

これだけで、録画開始・停止はできるのですが、ライブ画像を見たいところです。

ライブ画像を見る

ffplay (ffmpeg) で見ることができます。


ffplay -loglevel panic -an -fflags nobuffer -f:v mpegts -probesize 8192 udp://:8554

実際には、ストリーミング接続を保持させる処理が必要となります。


#!/usr/bin/env python3

import sys
import socket
from urllib.request import urlopen
import subprocess
from time import sleep
import datetime
import signal
import http
import multiprocessing

# GPH 6/0.160
GOPRO_IP = "10.5.5.9"
UDP_PORT = 8554
KEEP_ALIVE = 2.5
MESSAGE = "_GPHD_:0:0:2:0.000000"

URL_PREFIX       = f"http://{GOPRO_IP}/gp/gpControl"
URL_STREAM       = f"{URL_PREFIX}/execute?p1=gpStream&a1=proto_v2&c1=restart"
URL_RECORD_START = f"{URL_PREFIX}/command/shutter?p=1"
URL_RECORD_STOP  = f"{URL_PREFIX}/command/shutter?p=0"

CMD_VIEW = f"ffplay -loglevel panic -fflags nobuffer -f:v mpegts -probesize 8192 udp://:{UDP_PORT}"

def live():

    urlopen(URL_STREAM).read()
    subprocess.Popen(CMD_VIEW, shell=True)
    multiprocessing.Process(target=keep_alive).start()

    print("Press Ctl+C to quit.")
    print("Press ENTER to start/stop recording.")

    on = False
    while True:
        input()
        on = not on
        record(on)

def keep_alive():

    while True:
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.sendto(bytes(MESSAGE, "utf-8"), (GOPRO_IP, UDP_PORT))
        sleep(KEEP_ALIVE)

def record(on):

    urlopen(URL_RECORD_START if on else URL_RECORD_STOP).read()
    print(f"Record {str(on)} {datetime.datetime.today()}")


def quit_gopro(signal, frame):

    sys.exit(0)

if __name__ == '__main__':

    signal.signal(signal.SIGINT, quit_gopro)
    live()

パソコン・スマホ共にアプリが公式に公開はされていますが、サクッと見たいですよね。

いろんな使い方ができそうです。

👉 【無料】使わなくなったスマホをライブカメラにしておじいちゃんを監視したい 
Live Hero5 Session with WiFi - GOPRO SUPPORT HUB


すばやく理解する「Room x RxJava 」

いい記事があったので。

Room 🔗 RxJava – Google Developers – Medium

まずは、Room で Dao.


@Query(“SELECT * FROM Users WHERE id = :userId”)
User getUserById(String userId);

ここまでで問題なのは、

1. 同期呼び出しでブロッキング。
2. データ変更時に再度呼び出す必要がある。

ということで、RxJava を使いたくなります。

Room は RxJava2.x に対応しています。

Adding Components to your Project | Android Developers

どのように使うのか?

Maybe


@Query(“SELECT * FROM Users WHERE id = :userId”)
Maybe<User> getUserById(String userId);

1. 該当ユーザがなければ、何も返さずに complete。
2. 該当ユーザがあれば、onSuccess となり complete。
3. Maybe が complete されたあとにユーザー情報が更新されても何もしない。

Single


@Query(“SELECT * FROM Users WHERE id = :userId”)
Single<User> getUserById(String userId);

1. 該当ユーザがなければ、何も返さず onError(EmptyResultException)。
2. 該当ユーザがあれば、onSuccess。
3. Single が complete されたあとにユーザー情報が更新されても何もしない。

Flowable


@Query(“SELECT * FROM Users WHERE id = :userId”)
Flowable<User> getUserById(String userId);

1. 該当ユーザはなければ、何も返さず emit もされない。当然、onNext も onError も呼ばれない。
2. ユーザが存在すれば、onNext。
3. ユーザ情報が更新されるたびに、自動で emit されるので、UI上を最新データに更新させることが可能になる。

 

まとめ

これだけ数行でデータベース、非同期処理を簡潔明快に説明できる Room x RxJava の組み合わせ。

おまけに Observable から細分化された RxJava2.x の主役たちの使い方も理解することができます。

素晴らしいですよね。


docomo spモードが 実効速度 100Mbps をかるく越えてる件

ふと計測してみたのですが...

Speedtest.net - Google Play の Android アプリ

ドコモ spモード で.

針の振り切り方が激しすぎる!

自宅の フレッツ光 + OCN でも計測した結果.

ホントかよ...?

ドコモのサイトに なんか凄い数字書いてるけど...

サービスエリアマップ | エリア | NTTドコモ

これって, あくまで, 理論値だよな...

しかし...

2017年 3大キャリアの実行速度公開 :ドコモ圧勝。SB下りが最下位。KDDI上りの遅さも目立つ【docomo/KDDI/SoftBank】 – め組のライフスタイル マガジン

実効速度計測結果 | エリア | NTTドコモ

じっこう
【実効】
実際の効力。実際のききめ。

ホントなんだわ 100Mbps...

まさかの

自宅の回線契約とか不要な時代が来ましたでしょうか?

(つづく)

Android USB テザリング 経由で 100Mbps を超える


「ThreeTenABP」で捨てれないのか android.text.format.DateUtils

Androidで日付表記をお手軽に国際化する « LINE Engineers' Blog

読んでみると, なんかいろいろややこしそう.

イギリス式: Fri, 18 Nov 2016
アメリカ式: Fri, Nov 18, 2016

イギリス英語: Fri, 18 Nov 2016
アメリカ英語: Fri, Nov 18, 2016
日本語: 2016年11月18日(金)

イギリス英語: 18/11/2016
アメリカ英語: 11/18/2016
日本語: 2016/11/18

Android 6.0: 2016年11月18日(金)
Android 4.1: 2016/11/18 (金)

Android 6.0: 2016年11月18日金曜日
Android 4.1: 2016年11月18日 (金)

日本語: 3 日前
英語: 3 days ago
フランス語: Il y a 3 jours

日本語: 11月18日
英語: on Nov 18
フランス語: le 18 nov.

挙動にぶれがあります(エミュレータにて動作確認)。小さいTextViewに表示する際にはOS versionによって見切れてしまっていないかなどの検証をしましょう。

OS version間での挙動差分や、ビジネス上アプリで必要な言語をAPIが対応してくれるかの検証は必要

Android 7.0でのICU4Jの導入と共に下記クラスがICU4JでのDateUtilsに対応するクラスとして案内されています。

うーむ...「日付表示」て, 書いときゃ世界のどこでもまあまあいけるやつはねえのかなあ, と.

ThreeTenABP で DateTimeFormatter を使う

「ThreeTenABP」て何なのかは, 作者であるぼくらの Jake Wharton神 の書いていることを読めば分かります.

JakeWharton/ThreeTenABP: An adaptation of the JSR-310 backport for Android.

なぜ JSR-310 なのか?

JSR-310 は, java.time.* パッケージとして Java8 に含まれています. これは, Java と Android の両方で Date/Calendar API群をすべて置き換えるものです.
Java6 の開発者であるStepahen Colebourne によって調整され, それにバックポートされました.

なぜ ThreeTenBP を使わないのか?

Android 上で Joda-Time を使う問題のように ThreeTenBP はタイムゾーン情報の読込みにjar リソースを利用しています. これが Android 上では非常に非効率です.
このライブラリでは, タイムゾーン情報を Android標準で使えるようして, 効率的にパースできるローダーを提供しています.

なぜ Joda-Time を使わないのか?

Joda-Time は非常に大きいバイナリサイズと多くのメソッド数をもつ非常に大きいAPIです. また, JSR-310 と Joda-Time の作者は「壊れてはいないが, 設計に欠陥がある」と言っています.
すでに Joda-Time を使っているなら, サイズとメソッド数を除けば, 置き換える理由はほとんどありません. 新しいプロジェクトのために, このライブラリはバイナリサイズとメソッド数だけでなくAPIの数をかなり削減したJava8の標準APIの形 で提供しています.

Joda Time's Memory Issue in Android

Date/Calendar API + JodaTime の機能をJava8 で合成した java.time.* (JSR-310) を 現Android開発向けに適正化し利用できるようにしたものが「TheeTenABP」ということになります.

コードの記述は Java8 の記述と同じなので Java8 Date and Time APIドキュメントや記事が参考にできます.

続・今日から始めるJava8 - JSR-310 Date and Time API - Taste of Tech Topics

13 章 : Date and Time API · Java Study

Java 8 の DateTimeFormatter の曜日等のフォーマットについて - tokuhirom's blog

Javaで日時を扱う(Java8) - Qiita

同梱されている国際化可能そうな日時フォーマットを試してみる.

...
DateTimeFormatter formatter =
    DateTimeFormatter
        .ofLocalizedDateTime(formatStyle, formatStyle)
        .withLocale(Locale.getDefault());
Timber.d(zonedDateTime.format(formatter) + " : " + formatStyle.name());
...

日付と時刻, それぞれ FormatStyle.SHORTからFULLまでの4種類ある.


2016年12月14日水曜日 10時13分36秒 日本標準時 : FULL
2016年12月14日 10:13:36 JST : LONG
2016/12/14 10:13:36 : MEDIUM
2016/12/14 10:13 : SHORT

Wednesday, 14 December 2016 01:13:36 Greenwich Mean Time : FULL
14 December 2016 01:13:36 GMT+00:00 : LONG
14 Dec 2016 01:13:36 : MEDIUM
14/12/2016 01:13 : SHORT

Tuesday, December 13, 2016 8:13:36 PM Eastern Standard Time : FULL
December 13, 2016 8:13:36 PM EST : LONG
Dec 13, 2016 20:13:36 : MEDIUM
12/13/16 20:13 : SHORT

2016年12月14日星期三 香港標準時間上午9時13分36秒 : FULL
2016年12月14日 GMT+08:00上午9時13分36秒 : LONG
2016年12月14日 09:13:36 : MEDIUM
2016/12/14 09:13 : SHORT

2016년 12월 14일 수요일 오전 10시 13분 36초 대한민국 표준시 : FULL
2016년 12월 14일 오전 10시 13분 36초 GMT+09:00 : LONG
2016. 12. 14. 10시 13분 36초 : MEDIUM
16. 12. 14. 10:13 : SHORT

なんか微妙...

FormatStyle.MEDIUM くらいが良さげだが, 曜日が含まれてないし.

別個, 曜日の文字列としては別に


localDateTime.getDayOfWeek()
    .getDisplayName(TextStyle.FULL, Locale.getDefault());

のようにして文字列として取れるっちゃあとれるが並び順やセパレータの件がある.

カスタムで言語別にフォーマットつくるのもなあ.

まとめ

android.text.format.DateUtils で.


DateUtils.formatDateTime(
       context,
       timestamp, 
       FORMAT_SHOW_YEAR | FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_ABBREV_ALL);


2016年12月14日(水) 10:13
Wed, 14 Dec 2016 00:13
Tue, Dec 13, 2016, 20:13
2016年12月14日週三 09:13
2016년 12월 14일 (수) 10:13

結局, これが簡単で自然,

表示言語やタイムゾーンの設定は context から取得してくれるし.

モバイル画面上の表示としてその他海外で自然かどうかは実際知らんけども.

日時を多言語化するというのは思ったより複雑.

モバイル端末というのは, いろいろな制限の中で動いているのだなあと実感.

Date/Calendar のことはもう忘れていいのだよな?

(つづく)


通知が表示されない とかどうせブロックの設定だろ! → 原因「フィルター」

「通知をONにしているのに表示されないんだけど...」

ありますよね!

実際, 設定が多すぎて分かりづらいです.

ネット上の情報も, OSバージョンや機種の違いなどでさらに混乱します.

とりあえず, すべての設定項目を列挙してみます.

そのアプリ内での「設定」

そのアプリの中の「設定」をONにします.

LINEの場合は以下のような画面ですね.

20161125-152024

OSの設定「アプリ」から

OSの「設定」アイコンから「アプリ」を選択.

そして対象アプリを選択後,「通知を表示」のチェックボックスをONにします.

20161125-153800

ネット上にこの設定の話がたくさんありますが, Android 6.x (Marshmallow) では, このチェックボックはなかったりします.

OSの設定「通知」から

OSの「設定」アイコンから「通知」を選択.

「ヘッドアップ」「端末がロック」とよくわからない言葉が表示されていますが, とりあえず上から2つをONにしていきます.

20161125-154834

続いてその下の「アプリの通知」をタップして対象のアプリを選択して

「ブロック」はOFFに, ロック画面に表示」をONにします.

20161125-155321

この画面は, Android 6.0 では, こんな画面なので, 1つOFF, 2つONにします.

20161125-160017

続いて, 私がはまっていた「フィルタリング」の設定です.

通知バーが表示されたときに, 長押しからなんとなくこの「フィルタリング」を押してしまっている人が多いのではないかと思います.

20161125-161030

簡単に非表示にできるわりには, 再度表示させるときの設定がわかりずらいです.

先ほどの「通知」の画面で「通知のフィルタリング」をタップします.

20161125-161447

「フィルタリング(無視して表示しない)」している通知が一覧で表示されます.

20161125-161727

この中から復活表示したい通知をタップすると, 無視された回数などが表示されますので, ここで「削除」を押すとフィルターから除外されて表示されるようになります!

20161125-162824

まとめ

「通知する」をONにしたあと, 「ブロック」と「フィルター」をOFFにする.

OS設定は「設定-通知」と「設定-アプリ」の2つの中のどこかにある.

設定多すぎ.

👉 【Android10/11】通知が来ない、遅れるときに見直すべき「電池(バッテリー)の最適化」 

👉【Android Pie】「通知」設定のシンプルな考え方