Wi-Fiルータのプライバシーセパレータ機能

要約
  • モバイルルータを含むWi-Fiルータにはプライバシーセパレータ機能があります
  • プライバシーセパレータは、ルータにWi-Fiで接続する機器間での通信を禁止する機能です
  • 防犯カメラをモバイルルータに接続する設定がうまくいかない場合は、ルータの設定でプライバシーセパレータを確認しましょう

私の実家は農家をしていてその作業場は道路に近いところに建てられています。作業場には農機具等もあって盗難の可能性もあることから防犯カメラを設置することにしました。防犯カメラには、インターネットには接続するものの、動画データは防犯カメラ本体側に記録しておき、スマートフォンなどのアプリなど遠隔からリクエストに応じて動画データをアプリ側に送信するタイプを使用することにしました。また作業場から実家のWi-Fiルータは利用できないため、作業場にモバイルルータを設置し、防犯カメラはこのモバイルルータを経由してインターネットに接続することにしました。

購入した機器、契約したサービス

購入した機器、契約したサービスは以下の通りです。( 価格は購入時2025年1月のものです。 )
  • 防犯カメラ: Anker Eufy Indoor Cam C220 3368円
    • 動画データは本体側に記録する。遠隔のアプリのリクエストに応じて動画データを返す
  • microSD: KIOXIA(キオクシア) 旧東芝メモリ microSD 128GB UHS-I Class10 1116円
    • 防犯カメラに挿入し、動画保存用に使用する
  • モバイルルータ: 富士ソフト +F FS040W モバイル Wi-Fi ルーター 14300円
    • モバイルルータは、モバイルネットワーク契約時にセットで購入した
  • モバイルネットワーク: NURO モバイルのデータ通信専用 VSプラン 3GB 月額基本料金 627円
    • 初回のみ事務手数料 3300円、SIMカード準備料 440円が発生する

設定がうまくいかない

機器がそろった後、防犯カメラをモバイルルータを接続する設定を行ったのですが、何故かうまくいきませんでした。大まかな手順は次の通りです。
  1. モバイルルータの電源を入れ、利用可能な状態にする
  2. スマートフォンに専用のアプリをインストールする
  3. スマートフォンをモバイルルータにWi-Fiで接続する
  4. アプリを起動して、 防犯カメラが接続する Wi-Fiネットワークのパスワードを入力する
  5.  防犯カメラの同期ボタンを押した後、アプリが表示するQRコードを防犯カメラに読み込ませる
5 の手順のあと、防犯カメラがモバイルルータに接続できるはずなのですが、エラーになって接続できませんでした。
問題切り分けのため、自宅のWi-Fiルータで試すと防犯カメラのルータ接続は成功しました。

プライバシーセパレータ機能

何故防犯カメラがモバイルルータに接続できなかったのか当初見当がつきませんでした。モバイルルータの設定を見ていたところ、プライバシーセパレータという機能を見つけました。
プライバシーセパレータは、ルータにWi-Fiで接続する機器間での通信を禁止する機能です。モバイルルータでこの機能を無効にして上記の手順を実施したところ、防犯カメラのルータ接続が成功しました。
プライバシーセパレータ機能を無効にすることで防犯カメラのルータ接続が成功したことから、上記 5 の手順のあとでスマートフォンのアプリと防犯カメラ同士で通信する行程があることが想定されます。ちなみに、自宅のWi-Fiルータのプライバシーセパレータ機能は無効になっていました。

設置した防犯カメラは異変を検知するとプッシュ通知がスマートフォンに送信されます。
今の所確認できた侵入者はカラスや猫ぐらいで少しほっとしています。

Git for Windows + TortoiseGit で githubにsshで接続する

タイトルの内容を試してみました。参考になれば幸いです。

ポイント

・TortoisGitのsshクライアントには、デフォルトのsshかTortoiseGit付属のTortoisePlinkを指定することになるが、sshはGit for windows付属のもの他に、Windows10では標準のものなど、複数存在する。
・Git for windows付属のsshはGit bashでは使えているように見えるが、TortoiseGitからの使用は、(私が試した範囲では)その動作が確認できていない。
・Windows10標準のsshをTortoiseGitから使用することは可能だった。(参考: http://www.freia.jp/taka/blog/windows-native-ssh-client/index.html )

・ここでは、TortoiseGit付属のTortoisePlinkを使用する。マシン起動後にPagentを起動して、Pagentに鍵を登録する手間を省きたい場合は上記のWindows10標準のsshの使用をお勧めする。
・githubがputtygenで作成した公開鍵を受け付けてくれなかったので、Git for Windows付属のssh-keygenで公開鍵、秘密鍵を作成し、さらに秘密鍵をputtygenというツールでputty向けのppkファイルに変換する。

手順

1. 公開鍵の作成
・鍵を置くフォルダを作成する。
・作成したフォルダをエクスプローラで開き、右クリックして「Git bash here」をクリックする。Git bashのコンソール画面が開く。
・以下のコマンドを実行して公開鍵を生成する。鍵のファイル名をtest_keyとする。test_keyとtest_key.pubというファイルが作成される。

ssh-keygen -t ecdsa -f test_key

2. putty向けの秘密鍵を作成する。(TortoisGit付属のPuttygenを使用する)。出来上がったファイルをtest_key.ppkとする。

3. githubに公開鍵を登録する。

3. Pagentを起動し、putty向けの秘密鍵を読み込む。

4. TortoiseGitでsshクライアントにTortoisePlinkを使用するように設定する。

5. githubでssh用のリポジトリURLを取得して、クローンする。

プレゼンテーション(LibraOffice Impress)から動画を作成してみる

試しに動画を作成してみた、という話です。

動機

YouTubeで、Excelのハウツー動画などを見て、なんとなく、PCで動画を作成してみたいと思い、どうすればよいか考えてみました。

・CGアニメーションの作成は難しそうだけど、パワーポイント等のプレゼンテーションソフトの自動再生機能を使用して紙芝居的なものならできそう。
・テキスト読み上げソフトを使えば、テキストから音声ファイルを起こせる。この音声ファイルをプレゼンテーションのスライドにあわせて再生する。

作成してみる

肝心の動画の内容ですが、動画が作成できれば内容は何でもよかったので、掛け算九九の1の段、しかも1×1=1、1x2=2だけというものになっています。

プレゼンテーションソフトにLibraOffice Impressを使いました。

実際にやってみると以下のようなことがわかりました。

・Impress自体は動画の作成はできない。

そこで再生中のプレゼンテーションを録画ソフト(今回はロイロゲームレコーダ)で録画しました。

録画したファイルを再生したところ、動画の最初の部分と終わりの部分で不要な箇所(録画操作をしたり、プレゼンテーションの最後の黒い画面)があるので、別途動画編集するツールで必要な部分だけ抽出しました。

結果は以下のようになりました。

使用したツール

■テキストーク(テキスト読み上げソフト)
http://choppli.123net.jp/

■LibraOffice Impress(プレゼンテーションツール)

■ロイロゲームレコーダー(録画ソフト)
http://loilo.tv/jp/product/game_recorder

■AviUtl(録画ソフト)
http://spring-fragrance.mints.ne.jp/aviutl/

・動画の編集をするにはAviUtl本体と拡張編集Pluginが必要。
・mp4を出力するにはx624guiExというAviUtlプラグインが必要。
・mp4を出力する際に画面の縦横のピクセル数が奇数だと出力できないので、設定>サイズの変更で指定する。

詳細は下記を参照

AviUtlの易しい使い方
http://aviutl.info/

powershellを使う

Windows7以降では標準でpowershellが使えます、という話です。

バージョン管理システム(git)のログを整形したいことがありました。
ログの中身は複数のコミットの情報があり、1コミットには複数のファイルのリストが含まれています。これらをファイル毎にコミットの情報を付加して、出力としてはCSVファイルにしたいと思いました。(後はExcelで開いてゴニョゴニョ・・・みたいな。)
でも使用中のWindowsマシンで、LinuxやFreeBSDのような、テキスト処理をする環境もなく、かといってVirutalBoxを入れることもその時は考えていなかったので、powershellを使うことにしました。

結論から言うと、使えたのですが、bashやWindowsのコマンドプロンプトとはいろいろ違うところがあって、例えば、

・スクリプトファイルを書いて実行することができるけど、そのためには予め管理者権限でスクリプトの実行を許可しなければならない。
・パイプ処理ができるけど、受け取るのは文字列のストリームではなくてオブジェクト。パイプ処理に限らず、何かコマンドレット(powershellでいうところのコマンド)を実行すると結果はオブジェクトで帰ってくる。

で、色々やった結果が下記になります。
文字コードの扱いがうまくできなかったので、gitの出力をコマンドプロンプト(cmd)で取得して、テキストエディタ(さくらエディタ)で変換する、ということをして逃げています。

# cmdで以下を実行
#
# git log --numstat --date=iso > ..\log.txt
#
# log.txtのエンコーディングをテキストエディタでUTF8からSJISに変更
#
# powershellで、このスクリプトを実行
#
# .\read_git_log2.ps1 log.txt > log.csv
#
# Excelでlog.csvを開く
# 追加行の集計(シートlogがlog.csvの内容で、A1にファイル名とすると、)
# =SUMIFS(log!E:E,log!$D:$D,"=" & Sheet1!$A1)
# 削除行の集計(シートlogがlog.csvの内容で、A1にファイル名とすると、)
# =SUMIFS(log!F:F,log!$D:$D,"=" & Sheet1!$A1)
$commit = ""
$author = ""
$date = ""
$comment = ""
$file = ""
$chgnum = ""
$chgline = ""
$plusnum = ""
$minusnum = ""
if ($args.Count -eq 0) {
"read_git_log2.ps1 logfile"
return
}
cat $args[0]| % {
$line = $_
if ($line -match '^commit.*$') {
$commit = $line -replace '^commit +', ''
$author = ""
$date = ""
$comment = ""
$file = ""
$plusnum = ""
$minusnum = ""
#$commit
} elseif ($line -match '^Author:.*$') {
$author = $line
$author = $author -replace '^Author: +',''
$author = $author -replace '<.+>',''
$author = $author.ToString().Trim()
#$author
} elseif ($line -match '^Date:.*$') {
$date = $line
$date = $date -replace '^Date: +',''
$date = $date -replace '\+0900', ''
#$date
} elseif ($line -match '^ .+$') {
$txt = $line -replace '\W',' '
$comment = "{0}{1}" -f $comment, $txt
#"comment {0}" -f $comment
} elseif ($line -match '^[0-9-]+\W+[0-9-]+\W+.*$') {
$file = $line -replace '^[0-9-]+\W+[0-9-]+\W+(.*)$','$1'
$plusnum = $line -replace '^([0-9-]+)\W+[0-9-]+\W+.*$','$1'
$minusnum = $line -replace '^[0-9-]+\W+([0-9-]+)\W+(.*)$','$1'
"{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $commit, $author, $date, $file, $plusnum, $minusnum, $comment
}
}

powershellはクセがあって使いづらいこともありますが、標準で入っていることもあり、使えると便利だと思います。

mp3ファイルのタグ編集 eyeD3

ポッドキャストをスマートフォンにダウンロードして聞いています。あるフォルダ以下のmp3ファイルをまとめて聞きたいので、全mp3ファイルのアルバム名をフォルダ名に変更できないか試してみました。

mp3ファイルのタグ名を変更するツールとしてeyeD3を使いました。eyeD3はpythonのライブラリですが、コマンドで呼び出すこともできました。

インストールはFreeBSDの場合、portsを使いました。

cd /usr/ports/audio/py-eyed3/
sudo make
sudo make install

Ubuntuでは、easy_install、pipを入れてからeyeD3を入れました。
* easy_install http://pypi.python.org/pypi/setuptools

sudo /home/hiroki/Downloads/setuptools-0.6c11-py2.7.egg

* pip

sudo easy_install pip

* eyeD3 http://eyed3.nicfit.net/installation.html

sudo pip install eyeD3</pre>

mp3ファイルのアルバム名は以下のようにしました。ID3タグのv2.2だと書き込みがうまくいかなかったので、v2.3への書き換えも指定しました。eyeD3のバージョン0.7.1-finalでは-Qオプション(標準出力を減らす)が使えます。以下は0.6.18で確認しました。

eyeD3 --to-v2.3 -A タイトル mp3ファイル

参考:

mp3 ファイルの id3 タグをいじる(python で日本語で id3v2)

moshを使う

mosh(mobile shell)はモバイル環境での使用を想定したsshに似たコマンドです。特徴としては、リモートマシンへの接続がスリープやハイバネートによる、マシンの中断から再開した後も保持される、ネットワークのローミングに対応している、などです。(似たコマンドにtmuxというコマンドもあるようです。)

使用の際は、クライアント側・サーバ側の両方で、文字コードをUTF-8にする
必要があります。

サーバ側(FreeBSD)では、~/.login_confを以下のように作成して、接続を確認しました。

me:\
   :charset=utf-8:\
   :lang=ja_JP.UTF-8:

参考:

http://mosh.mit.edu/

http://www.sssg.org/blogs/naoya/archives/2267

http://d.hatena.ne.jp/mutsune/20120416/1334590736

AWS上でFreeBSDインスタンスを起動する

http://gihyo.jp/admin/clip/01/fdt/201204/12
で紹介されていた、AWSでのFreeBSDインスタンスを試してみました。

AMIは、http://www.daemonology.net/freebsd-on-ec2/の中の、

ami-6c1dac6d 118940168514/FreeBSD/EC2 8.3-RELEASE amd64/HVM

を選びました。これをマイクロインスタンスで起動します。
インスタンス起動後は、sshでログインします。

$ ssh -l root -i EC2で作成した鍵.pem ec2-XXX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com

FreeBSDのインスタンスは、Windowsのインスタンスとして扱われるため、EC2のメニューにはリモートデスクトップ接続等の項目がありますが、使えないようです。

xenの仮想化方式には、hvmとparavirtualがあり、hvmの場合若干オーバヘッドが高いそうです。Windowsインスタンスの価格がlinux/unixより高いのはそういった理由があるのかもしれません。

参考:虎塚 メモ: AMIの仮想化方式 hvm、paravirtualについて

githubを使う

ポッドキャストをダウンロードするスクリプトをgithubにおいてみました。

https://github.com/hrktir/download_podcast_mp3

–sinceの指定がうまくいってなかったのを修正しています。

githubの接続に、Windows用のgitを試してみましたがうまく行かなかったのでCygwin用でリトライしてみました。sshの公開鍵をgithubに登録する必要があって、それをしていなたったため、コケていたようです。(Windows用のgitクライアントでは気づきませんでした。)

mp3ファイルの音量を調整する

「ポッドキャストをダウンロードする」で、用意したmp3ファイルを聞くとファイルによって音量が違っていることに気づきました。

mp3ファイルの音量を調整するツールにmp3gainがあるようなので、これを使ってみました。

インストールはpkg_addで行いました。

# pkg_add -r mp3gain

音量の調整は、-rオプション(指定したファイルの音量を同じ大きさにする)で行いました。ファイルのタイムスタンプを変えないように、-pもつけます。

$ mp3gain -r -p *.mp3

すべてのmp3ファイルを対象にすると、処理に時間がかかるので、音量が小さいファイルのみを指定すると良いようです。

ポッドキャストをダウンロードする

ポッドキャストを聞く場合、PCを使っている時はiTunesを使うのですが、車中で聞く場合は、USBメモリをチューナーに差して聞いています。

このUSBメモリにPC上のmp3のファイルを手作業でコピーするのが少々面倒なので、スクリプトでやってみることにしました。

やることは、ポッドキャストのデータから過去n時間以内に公開されたのmp3ファイルをダウンロードする、です。幾つかのファイルが揃ったらそれをDropbox側に移動させます。(Dropbox側へのファイルコピーはdropbox-apiを使ってみるを使うことにします。)

ポッドキャストのデータからmp3ファイルをダウンロードする方法ですが、スクリプトを書いてみました(download_podcast_mp3.py)。ネットで似たようなスクリプトを見つけたのですが、公開時期でファイルを選択させる機能がほしかったので書いた次第です。

import urllib2
from xml.dom.minidom import parse
from time import strptime
from datetime import datetime
from datetime import timedelta
import time
import re
import os
import sys


# The following url is feed format and can not be accepted. 
# url = "http://www.bbc.co.uk/worldservice/learningenglish/general/sixminute/index.xml"
# The following url is rss format and can be accepted.
# url = "http://downloads.bbc.co.uk/podcasts/worldservice/how2/rss.xml"

def getPodcastXmlDom(url):
    response = urllib2.urlopen(url)
    #msg = response.read()
    dom1 = parse(response)
    return dom1

def getItemList(dom):
    items = dom.getElementsByTagName('item')
    if len(items) > 0:
        return parseItemsAsRSS(items)
    else:
        raise Exception("no item element found")

def parseItemsAsRSS(items):
    results = []
    for item in items:
        idict = dict()

        enc = item.getElementsByTagName('enclosure')
        if len(enc) == 1:
            idict["url"] = enc[0].getAttribute("url")

        idate = item.getElementsByTagName('pubDate')
        if len(idate) == 1:
            idict["date"] = getGMTDatetime(idate[0].firstChild.wholeText)

        ititle = item.getElementsByTagName('title')
        if len(ititle) == 1:
            idict["title"] = ititle[0].firstChild.wholeText

        if idict["url"] is not None and idict["date"] is not None and idict["title"] is not None:
            results.append(idict)
    return results

def getGMTDatetime(idateStr):
    tlag = 0
    if re.search("[\+\-][0-9]{4}",idateStr):
        tlag = int( re.findall("[\+\-][0-9]{4}", idateStr)[0] ) / 100     
        idateStr = re.sub("[\+\-][0-9]{4}", "GMT", idateStr)
    for s, v in {
       "ADT":-3,
       "AST":-4,
       "EDT":-4,
       "EST":-5,
       "PDT":-7,
       "PST":-8,
       "JST":9
    }.iteritems():
        if re.search(s, idateStr):
            tlag = v
            idateStr = re.sub(s, "GMT", idateStr)
    idateValue = strptime(idateStr, "%a, %d %b %Y %H:%M:%S %Z")
    idate = datetime(idateValue.tm_year,idateValue.tm_mon, idateValue.tm_mday, idateValue.tm_hour, idateValue.tm_min, idateValue.tm_sec)
    idate = idate - timedelta(hours = tlag)
    return idate
 
def getFilename4mp3(idict):
    ret = re.sub("[ :]", "_", idict["title"])
    ret = ret + "_"
    ret = ret + idict["date"].strftime("%Y_%m_%d_%H_%M")
    ret = ret + ".mp3"
    return ret

def downloadFile(url, filename):
    print "download " + url + " as " + filename
    response = urllib2.urlopen(url)
    tofile = open(filename,"w")
    tofile.write(response.read())        
    response.close()
    tofile.close()

def changeAccessTime(filename, pubdate):
    t = int(time.mktime(pubdate.timetuple()))
    os.utime(filename, (t,t))

def getLatestItem(items, nhoursago):
    tdy = datetime.today()
# make t as GMT 
    t = datetime(tdy.year, tdy.month, tdy.day, tdy.hour, tdy.minute)
# assume this environment is in JST (+0900)
    t = t - timedelta(seconds = 9 * 3600)

    ndaysago = nhoursago % 24
    nsecsago = (nhoursago - 24 * ndaysago) * 3600
    
    results = filter(lambda i:i["date"] > t - timedelta(days = ndaysago, seconds = nsecsago) ,items)
    return results

def main():
    if len(sys.argv) < 2:
        print "Usage:" + sys.argv[0] + " url_of_podcast_rss [options]"
        print """Options:
    --since n      : gets mp3s newer than n hours ago. 
                     default is 148 (24hours * 7days) 
    --title TITLE  : uses TITLE as filename
"""
        sys.exit()
    url = sys.argv[1]
    nhoursago = 7 * 24
    alttitle = None
    for i in range(2, len(sys.argv)):
        if sys.argv[i] == "--since" and i + 1 < len(sys.argv):
            nhoursago = int(sys.argv[i + 1])
        if sys.argv[i] == "--title" and i + 1 < len(sys.argv):
            alttitle = sys.argv[i + 1]

#    items = getItemList(getPodcastXmlDom(url))
    items = getLatestItem(getItemList(getPodcastXmlDom(url)),nhoursago)
    for item in items:
        if alttitle:
            item["title"] = alttitle
        downloadFile(item["url"], getFilename4mp3(item))
        changeAccessTime(getFilename4mp3(item), item["date"])

def testGetGMTDatetime():
    print getGMTDatetime("Sun, 22 Jan 2012 13:00:01 +0000")
    print getGMTDatetime("Thu, 27 Jan 2012 22:48:45 PDT")
    print getGMTDatetime("Thu, 26 Jan 2012 08:44:15 -0800")
    print getGMTDatetime("Fri, 27 Jan 2012 03:30:33 EST")

if __name__ == '__main__':
#    testGetGMTDatetime()
    main()

以下使い方です。


$ python download_podcast_mp3.py ポッドキャストのURL [--since n] [--title TITLE]

対象となるmp3ファイルがあれば、カレントディレクトリにそのファイルが保存されます。ファイル名は「title_2012_01_27_01_23_45.mp3」のようにポッドキャストXML内のtitle要素 + pubDate要素を使います。

「–since n」は今からn時間前以降に公開されたファイルを対象とすることを指定します。デフォルトは148(一週間前)になります。
「–title TITLE」はファイル名にtitle要素以外の文字列を指定する場合に使用します。これはtitleに日本語が含まれる場合にうまく保存できないのを避けるための用意しています。

タイムゾーンの扱いは、きっちりやっていません。PDT、EDT、JST以外のタイムゾーンを扱う場合は、該当するタイムゾーン文字列とGMTとの時間差をdictで書いている部分がありますので、そこを変更してみてください。

追記:20120328
タイムゾーンを追加しました。