プログラム書いたり、もの作ったり。あと育児とか。

プログラム書いたり、もの作ったりすることについて書いていく予定です。あと育児とかも書くかもしれません。

TV録画サーバーを更新したい

前回からあっという間に3年経過してます。そして毎回ブログが更新できていないことを書いている気がする...。

たしか2年前くらいに録画サーバーを一新しました。理由はメインPCのupdateによって1台PCが組めるだけのパーツが揃ったためだったような。 その結果、下記のようなサーバが現在動いています。

  • PC: 自作 / i7-4790K / Memroy24GB / GTX660Ti
  • OS: Ubuntu18.04
  • Storage:
    • SSD 480GB
    • HDD: 2TB x 2, 6TB x 1, 8TB x 1をzfs on linuxRAID Z2にしている
  • TV tuner: PT3

ソフトウェアの構成 * Mirakurun / Chinachuで録画 * 録画ファイルをffmpegでH264でエンコードして保存 * エンコードにはNVENCを使用

他にもforked-daapdやminidlnaなども動いてますが、その辺はあんまり使えてないので割愛。 大体この録画をTVに繋いでいるAmazon Fire Cubeに入れたKodi経由で見るようなことをしてます。

ただ、最近録画に失敗したりエンコードに失敗したりしていて、最近だとMirakurun/EPGStationなど他の選択肢も出てきているし、TrueNASのLinux版(True NAS Scale)というものも出てきているようなので、いっそのこと全部入れ替えてみようかな、とか考えてたりします。

下記の構成ができないか考え中 * PCはそのまま * OS: True NAS Scale * その上でVMUbuntuを動かす * 録画はMirakurun/EPG Station * エンコードEPG Stationからnvenccでエンコード

あと最近Orange Pi 5買ってみたりもしたので、これもうまいこと使えないかなーとか考えてますがまだ妙案はない。

このGWでやりたかったが子供が風邪ひいたり自分が風邪ひいたりして結局時間がほとんどとれず進んでないんだよね...。 e-Paperもちょっと買ってみてて、表示までは割とすんなりできたけど、どう活用するかはこちらも特に妙案はなく。

ゆっくり考える時間が欲しい...。

TV録画サーバーの話

うちには数年前から動いているTV録画サーバがあります。 構成はこんなかんじ。

  • PC:HP ProLiant MicroServer (2万円くらいで買えるやつ)
  • OS:CentOS7(最初CentOS6で動かしてましたが、7に更新しました)
  • TVチューナー:PT3(販売終了 もうひとつくらい買っておけばよかった...)
  • ストレージ:
    • USB flash x1: centOSがインストールされている flashバイスにOS乗っけてるのはあまり良くないなーと思いながらずっとそのまま...
    • HDD 2TB x3 + zfs on linuxraid-z 音楽データとか、写真とか、TV録画データとか
    • HDD 2TB x1はバックアップ用
  • 録画管理ソフト:chinachu

基本的には問題ないのですが、いかんせんCPUが弱いのでエンコードが遅いし、エンコードと録画同時にちゃんと動くかとか不安だった(実際試してちゃんと動かなかったような...)ので自動エンコードさせてないところが不満点ですかね。 で。最近(といっても2年前くらい...)ivy bridgeを載せたPC一式が手に入りまして。こいつにTV録画+エンコードの機能を入れ、サーバーはデータ保存専用としようかな、と思っています。

まぁつまりは、記事を書くための事前準備記事でした。 そのうちやったら記事書きたいと思います。 今更感のある記事になるかと思いますが。書くことが大事。

他にもサーバにmt-daapを入れてiTunesサーバ化する、とかkodiいれてみる、とかやりたいなーと思いながら結構経ってます。。

ひさびさのブログ

やっぱりブログが続かない。

仕事と関係ある内容なら勉強にもなるし非定期でもかけるかなーとか思ってましたが全然かけない。 時間が取れないのが問題ですな。

独身のときの自由な時間が100だとすると  結婚後→40  子ども生まれた後→1~5  もうすぐ1歳→10くらい? って感じ。

書きたいことはあるつもりなんだけどなー・・・(遠い目)

ま、こんなのでも少しでもアップしていけばいいのかな。。

Bluetooth v5.0, Vol1, 1.2 Overview of Bluetooth Low Energy Operation

1.2 Overview of Bluetooth Low Energy Operation

  • BR/EDRと同様に2.4GHz帯を使用
  • 周波数ホッピングを採用している
  • 複雑さを避けるために2値周波数変調を採用
  • 必須(mandatory)シンボルレートは1Msym/s (LE 1M PHY)
    • 1sym=1bitでデータレートは1Mbit/s
      • オプションでエラー訂正
        • S=2; 2sym=1bit→500kbit/s
        • S=8; 8sym=1bit→125kbit/s
  • オプショナルシンボルレートは2Msym/s
    • 1sym=1bitでデータレートは2Mbit/s
      • エラー訂正オプションはない
  • Sec 3.2.2に詳細

多重化とチャネル

  • LEは2つの多元接続方式を採用
    • FDMA(Frequency Division Multiple Access; 周波数分割多元接続)
      • 2MHzで40の物理チャネルに分割
      • 3チャネルがprimary advertising channelsで残り37チャネルがsecondary advertising channelsでありData channels
    • TDMA(Time Division Multiple Access; 時間分割多元接続)
      • TDMAベースのポーリング
        • 送信側は予め決まったタイミングでパケットを送付し、受信側は予め決まったインターバルの後に返答する

イベント

  • 物理チャネルはイベントと呼ばれる時間単位に分割される
  • パケットはイベントに配置されて送信される
  • イベントは4種類
    1. Advertising
    2. Extended Advertising
    3. Periodic Advertising
    4. Connection Events

AdvertisersとScanners

  • Advertisers: advertising(以下、adv.)物理チャネルでadv.パケットを送信するデバイス
  • Scanners: adv.物理チャネルでadv.パケットを受信するデバイス
  • adv.物理チャネルにおける通信はadv.イベント内で行われる
    1. Advertiserはadv.イベントタイプに応じたadv.パケットを送る
    2. Scannerはadv.パケットタイプに応じて同じadv.物理チャネル上にリクエストを送付できる
    3. Advertiserはリクエストに続いて同チャネル上にレスポンスを返す
  • adv.物理チャネルは同じadv.イベント内でもAdvertiserが次のadv.パケットを送るときに変更される
  • Advertiserはイベント中いつでもadv.イベントを終了させることができる
  • 次のadv.イベントの始まりは最初に使用されたadv.物理チャネルが使用されます

f:id:shito6363:20190106160217p:plain
Advertising events (from Bluetooth Core v5.0)

Communication

  • LEデバイスはadvertising eventで2つ以上の機器間で単方向(unidirectional)通信もしくはブロードキャスト(broadcast)通信が可能
  • LEデバイスはadvertising eventを使用してペアを確立し、data channelを使用した双方向通信や、secondary advertising channelを使用して定期的にブロードキャストする事ができる

Connection event

  • Initiators: 他の機器と接続するためにconnectable advertising(以下、conn. adv.)パケットを監視(listen)している機器
  • 接続手順
    1. Advertiserがconn. adv.イベントを発信している場合、Initiatorはconnection requestを同物理チャネル上に送付できる
    2. Advertiserが接続を了承(accept)したら、adv.イベントは終了ののちconnectionイベントが開始される
  • 接続後はピコネット(piconet)内において、InitiatorはMasterデバイスに、AdvertiserデバイスはSlaveデバイスになる
  • Connection(以下、Conn.) eventはMaster-Slave間でデータパケットを送受信するために使用される
  • Connection eventについて
    • チャネルホッピングは各Conn. eventのはじめに行われる
    • Conn.イベント内では同じ物理チャネル内でMasterとSlaveは交互にデータパケットを送信し合う
    • MasterデバイスはConn. eventをいつでも開始できるし、いつでも終了させることができる

f:id:shito6363:20190106163606p:plain
Connection event (from Bluetooth Core v5.0)

Frequency Hopping

  • ピコネット内のデバイスは擬似ランダムパターンによって生成された特定の周波数ホッピングパターンを使用する
  • LEの場合は37の周波数帯をホッピングし、これによってISMバンド内におけるBluetoothの共存性能を向上させている

Link, Channel, Transport

  • 物理チャネルからL2CAPまでの構造(詳細はSec. 3.3 ~ 3.6)
L2CAP Channel
Logical Link
Logical Transport
Physical Link
Physical Channel
  • 同じ物理チャネル内で2つのデバイスがつながると物理リンクが形成される
  • アクティブな物理リンクはMaster-Slave間で双方向パケットトランスポートを提供する
  • LE物理チャネルは複数のSlaveデバイスを含むので、デバイスが物理リンクを形成するのには制限がある
  • SlaveはMasterデバイスへの物理リンクを1つ以上持つことができる
  • バイスはMasterとSlaveに同時になることができる
  • 同じpiconet内のSlave間で物理リンクを形成することはできない
  • 物理リンクは1つ以上の非同期通信論理リンクのトランスポートとして使用される
  • 論理リンク上の通信はリソースマネージャのスケジューリング機能によって物理リンク上に多重化される

  • 論理リンク上でLInk Layer(LL)プロトコルが実行される

  • ピコネット上でアクティブなデバイスはLLプロトコル信号を送るためにLE asynchronous connection logical transport (LE ACL)を持っている

  • BR/EDRのように、Link Layerの上にはL2CAPレイヤがチャンネルベースの抽象化をアプリケーションやサービスに提供している

  • L2CAPはアプリケーションデータを分解(fragmentation)/結合(de-fragmentation)を行い、また論理リンク上で複数チャネルの多重化(multiplexing)と非多重化(de-multiplexing)を行う
  • L2CAPはPrimary ACL論理トランスポート上で実行されるプロトコルコントロールチャネルをもつ

  • LEではL2CAPの上にさらに2つのプロトコルレイヤが存在する

    • Security Manager Protocol(SMP)
      • fixed L2CAP channelを用いてデバイス間のセキュリティ機能を受け持つ
    • Attribute Protocol (ATT)
      • fixed L2CAP channel上で小出しでコミュニケーションを取るメソッドを提供する

1.3 Overview of AMP Operation

こちらは省略…

Bluetooth Spec v5.0, Vol.1, 1.1 Overview of BR/EDR Operation

1.1 Overview of BR/EDR Operation

  • BR/EDRはISMバンド(2.4GHz帯)を使用
  • 周波数ホッピングを採用している
  • 複雑さを避けるために2値周波数変調を採用
  • シンボルレートは1Msym/s
  • ビットレートは1Mbit/sだが、EDRなら2Mbit/sか3Mbit/s
  • piconet間はクロックと周波数ホッピングパターンが同期される

周波数ホッピング

  • 擬似ランダムパターン
  • 1MHz分割で79チャネル

スロット

  • 各チャネルは時間方向にも「スロット」という単位で分かれている
  • Bluetoothバイス間のデータはパケットとしてスロットに配置されて通信する
  • Time-Division Duplex(TDD)によって全二重通信が可能

物理チャネル(physical channel)と物理リンク(physical link)

  • 物理チャネル内にはmaster-slave間で物理リンクが形成される
  • 物理リンクはmaster-slave間で双方向パケット通信を提供する
  • 物理チャネルには複数のslaveデバイスが含まれる可能性があるので、物理リンク形成には制限が生じる可能性がある
  • 物理リンクは各slaveとmasterの間に形成されるが、slave間には形成されない

    論理リンク(logical link)

  • 物理リンクはトランスポートとして1つ以上の論理リンクに使用される
  • 論理リンクはユニキャストなsynchronous, asynchronous, isochronous通信をサポートする
  • 論理リンクの通信路は物理リンク上で多重化され、リソースマネージャのスケジュール機能によって物理リンク上のスロットに配置される

Link Manager Protocol(LMP)

  • ピコネット上のデバイスはdefault asynchronous connection-oriented logical transport (ACL logical transport)でLMP protocol signalingを伝送する
  • ACL logical transportはデバイスがピコネットに参加するたびに作成される
  • 追加の論理トランスポートは要求されれば作成される

L2CAP

  • ベースバンド層の上でL2CAP層はチャネルベースの抽象化を提供
  • データの分割(segmentation)と再結合(reassembly)、共有論理リンク上におけるマルチチャネルの多重化(multiplexing)と分離(de-multiplexing)を実行

Bluetooth Spec v5.0 Vol1 1 General Description

1 General Description

  • Bluetoothは短距離における有線通信を無線化することを目的として策定された無線規格
  • 特徴:ロバスト性/低消費電力/低コスト
  • BluetoothにはBasic Rate(BR)とLow Energy(LE)の2つのシステム
  • BRはEnhanced Data Rate(EDR), Alternate Media Access Control (MAC)、Physical(PHY) layer extensionsをオプションとして持っている
  • BRには同期通信と非同期通信がある
  • データ通信速度
    • BR: 721.2kbit/s
    • EDR: 2.1Mbit/s
    • 802.11 AMP: 54Mbit/s
  • LE systemはBR/EDRよりさらに低消費電力、低複雑性、低コストな設計になっている
  • バイスは両方のシステムを実装して両方別々に通信することができる。
  • Bluetooth Core systemはHostと1つ以上のControllerで構成されている
  • HostはHost Controller Interface(HCI)から上の層
  • ControllerはHCIより下の層
  • ControllerにはPrimary ControllerとSecondary Controllerの2つが定義されている
    • Primary Controller
      • BR/EDRのみ
      • LEのみ
      • BR/EDRとLE両方
    • Secondary Controller
      • Alternate MAC/PHY (AMP) Controller

Memo

  • AMPは普段全然扱わないので、無視するかも…
  • EDRBluetooth v2.0から追加された仕様。今ではBR/EDRとBRとセットになってる
  • LEはBluetooth v4.0から追加された仕様。もともとBluetoothではないものを導入した経緯があるらしく、従来のBR/EDRとは互換性がない
  • にもかかわらずBR/EDRと同じ用語をいたるところで使うのでわけわからなくなる
  • BR/EDRiOSでMFiとらないと使えないのでアプリで独自実装してなにかするにはLEの方を使うしかない

Bluetooth Spec v5.0 Vol.1

では Vol.1 Architecture & Terminology OverviewArchitecture & Terminology Overview から見ていきましょうか。

前回Vol.0って書いた気がしますが、Vol.1です。

1. General Description
 1.1 Overview of BR/EDR Operation
 1.2 Overview of Bluetooth Low Energy Operation
 1.3 Overview of AMP Operation
 1.4 Nomenclature
2. Core System Architecture
3. Data Transport Architecture
  3.1 Core Traffic Bearers
  3.2 Transport Architecture Entities
  3.3 Physical Channels
  3.4 Physical Links
  3.5 Logical Links and Logical Transports
  3.6 L2CAP Channels
4. Communication Topology and Operation
 4.1 Piconet Topology
 4.2 Operational Procedures and Modes
5. Security Overview
 5.1 Security Architecture
 5.2 BR/EDR Secure Simple Pairing
 5.3 Secure Connections Only Mode
 5.4 LE Security
 5.5 AMP Security
 5.6 Key Generation Between BR/EDR and LE Physical Transports
6. Bluetooth Application Architecture
 6.1 Bluetooth Profiles
 6.2 Generic Access Profile
 6.3 Profile Hierarchy
 6.4 Generic Attribute Profile
 6.5 GATT-Based Profile Hierarcy
7 Coexistence and Collocation

目次書くだけで大変ですね…。

Bluetoothの仕様を把握する

結局前回の更新からずいぶん時間が空いてしまいました。

もう子供生まれてから1か月以上たつんですねぇ。。


突然ですが、Bluetooth core specを読んでいきたいと思います。

Bluetoothヘッドセットが流行り始めてから結構経ちますが、技術的なBluetoothの話ってあんまりネットで調べても出てこないので、勉強の意味も込めて書いていきたいと思います。

BLEだと個人でも結構いろいろできるので解説しているブログなどヒットしますが、いかんせん仕様がややこしくてですね。。

できるだけわかりやすく書くつもりですが、間違いありましたらご指摘いただけると嬉しいです。

Core Specは Bluetooth SIGの仕様→コア仕様 の中にあります。

ちなみに、実に2822ページあります。(絶望)

全体は大項目Vol 0~Vol7まで分けられており、それぞれに中項目Part A, B, ...、さらにその下に 小項目1, 2, ...と分けられています。

  • Vol.0: 全体の目次とか、Bluetooth認証の話とか。あまり見ない…
  • Vol.1: BR/EDR、BLEとはなにかとか、下層から上層まで全体のつながりとか、全体の話。Vol.2以降がそれぞれの層に分かれた詳細仕様になっている
  • Vol.2: BR/EDR物理層(RF), Baseband, LMP, HCIなど、下層まわりについて記されている。
  • Vol.3: L2CAP, SDP, GAP, ATT, GATTなどについて記されている。BR/EDRもBLEも記述されている。よくお世話になる。
  • Vol.4: 外部マイコンとやりとりするHCIのTransport Layerについて。UARTとか。
  • Vol5: AMP Controllerについて。使わないから読んだことない…
  • Vol6: BLEの下層の話。
  • Vol7: ほかの無線規格との共存の話。Mobile Wireless Standard(MWS)とのやりとりについて書かれているっぽい。どうやらv4.1から追加された模様。使わないので読んだことない…。

時間ができて気が向いたら更新されます。 最初はVol0からかなぁ…。

タイトル変えました。

やっぱり更新が滞ってしまう…。

原因を考えたところ、やはり意気込んで記事を持続して書き続けるのは性に合わないのだと言う結論に至りました。

なので、これからはたまに意気込んだ記事を書いて、それ以外はその日に思ったこととか、最近のニュースについてとかを誰に見られることも考えずに書いていきたいと思います。

あと最近子供生まれたので、育児についても書いていければと思います。

まずは書き続けることができるようになることが目標です。

では。

ポインタとメモリ その2

前回:ポインタとメモリ その1 - プログラム書いたり、もの作ったり。あと育児とか。

値渡しと参照渡し

C言語では、色んな所で実は同じように値のコピーが行われます。

ここに、ポインタの有用性が出てきます。

一番わかりやすいのは関数の引数における「値渡しと参照渡し」でしょう。

// 値渡し
void func_val(int fa, int fb)
{
    fb = fa;
    return;
}

// 参照渡し
void func_ref(int *pa, int *pb)
{
    *fb = *fa;
    return;
}

int a = 0x10;
int b = 0x20;

func_val(a, b);
printf("a=%d, b=%d", a, b);
// a=16, b=32となり、func_valではbの値は更新されない

func_ref(&a, &b);
printf("a=%d, b=%d", a, b);
// a=16, b=16となり、func_refではbの値は更新される

値渡しの場合は、関数の中でfb=faとやっても、もともとの変数には影響を与えません。これは関数が呼ばれるときに引数の値はスタック領域と呼ばれるメモリ上の別な場所にコピーされるため、関数の中の引数(faとかpa)と関数を呼ぶ前の引数(aとかb)の実体は別々のものになります。

つまり、アドレスが異なると思ってもらって良いです。

例:もとのaとbのアドレスが0x2000, 0x2001、関数引数のfaとfbのアドレスが0x2100と0x2101、などそんな感じ

アドレスが異なっていれば、そりゃあ関数の中で書き換えを行ってももとの変数には影響与えませんよね。

メモリのイメージで説明するとこんな感じです。


func_val()呼ぶ前

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | xx xx xx xx xx xx xx xx

func_val()に入った直後

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | 10 20 xx xx xx xx xx xx

b=aの直後

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | 10 10 xx xx xx xx xx xx

func_val()を抜けたあと

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | xx xx xx xx xx xx xx xx

じゃあ、参照渡しの場合はどうなるんでしょう。


func_ref()呼ぶ前

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | xx xx xx xx xx xx xx xx

func_ref()に入った直後

0x2000 | 10 20 xx xx xx xx xx xx 
...
0x2100 | 00 20 01 20 xx xx xx xx

pb=paの直後

0x2000 | 10 10 xx xx xx xx xx xx 
...
0x2100 | 00 20 01 20 xx xx xx xx

func_ref()を抜けたあと

0x2000 | 10 10 xx xx xx xx xx xx 
...
0x2100 | xx xx xx xx xx xx xx xx

func_refに入った直後、 0x2100 | 00 20 01 20 xx xx xx xx

こうなってますけど、まさにこれこそがポインタなのです。

(仮定として、16ビット系、リトルエンディアンとして書いてます。)

つまりpa(0x2100) = 0x2000, pb(0x2102) = 0x2001が代入されており、paがポインタなので*paと書くと、もともとの変数(0x2000の変数)に対して操作することができるわけです。

あくまで、関数がコールされるときにスタックに値がコピーされることは同じです。ですが、そのコピーされるものが値ではなくアドレスであり、さらにポインタという仕組みがあるため、そのアドレスの値にアクセスすることができるのです。

これによって関数の外側の変数を変更することができるというわけです。

ポインタの利点

これがわかると、ポインタがなぜ利用されるのかがわかってきます。

例えば、構造体。

構造体を関数の引数に渡すとき、そのまま渡したら構造体の中身がすべてスタックにコピーされる事になります。構造体の大きさがそこまで大きくなければ影響も少ないかもしれませんが、大きくなってくるとスタックにコピーされる量も大きくなり、メモリ的にも動作的にも無駄が大きくなってきます。

ところが、これをポインタで渡すようにすると、構造体の先頭アドレスをコピーするだけ済みます。

typedef struct sample_s
{
    int num1;  // 2byte
    int num2;  // 2byte
    char str[16];  // 16byte
} sample_t;

void proc_sample_val(sample_t sample)
{
    // コピーされたsampleにアクセスする
    // スタックへ20byte分すべてコピーされる
    // 元の変数sample1は変更されない
    sample.num2 = sample.num1;
    sprintf(sample.str, "val");
}

void proc_sample_ref(sample_t *sample)
{
    // sample1のアドレスにアクセスする
    // スタックはsampleのアドレスサイズ分(今回は2byte)だけ消費される
    // 元の変数sample1も変更される
    sample->num2 = sample->num1;
    sprintf(sample->str, "ref");
}

sample_t sample1;

sample1.num1 = 10;
sample1.num2 = 20;

proc_sample_val(sample1);
printf("val: %d, %d", sample1.num1, sample1.num2);
// val: 10, 20

proc_sample_ref(&sample1);
printf("ref: %d, %d", sample1.num1, sample1.num2);
// ref: 10, 10