2015年3月1日日曜日

OWIN (Open Web Interface for .NET) Hello world


OWINとは?
  簡単なアプリケーションもすべてインターネットを通してやりとりを行う時のインターフェイス規格です。この技術を使えばハッピーになれるターゲット層は、Internet of things(物とインターネット)をやっている人です。
例えば部屋においてある電化製品でインターネットに繋がっていないモノ{冷蔵庫、オーブンレンジ、トースター、IHコンロ、エアコン、オーディオ、、、etc}それぞれが独自の通信方式を持っているより1つのインターフェイスで出来ちゃえばJavascriptでも制御できてしまう、そんな抽象的なインターフェイス規格です。


OWINの無い世界
  1つ1つの家電は専用サーバーに集約されているが、各社メーカー毎に存在しているので、端末から見るとアクセス先毎に通信方法を変えないと行けない。


メリット
 各社専用サーバーを設けて独自のコンテンツ・サービスの提供が可能。
デメリット
 ・ユーザー視点だと、様々なメーカーを利用しているので同じメーカーで統一しないとメリットの魅力が伝えられない。



PlantUML diagram



OWINのある世界
 家に必ずあるインタネットモデムがサーバーになった場合、アクセス先は家になる。
 さらに家電はOWIN通信規格で統一されているので、新しく買った製品でもすぐつなげる事ができて、コンテンツは各家電が提供することで画面レイアウト以外は共通になる。

メリット
 家の中に1台サーバーがいればスマホ1つですべての家電にアクセスが可能。

デメリット
 コンテンツ・サービスは家電の中に閉じ込めてしまっているので、表示される画面に統一感が無い。


PlantUML diagram



抽象的って素晴らしいなって思うこの頃。(なんでも包括出来てしまう(的が広い)から外れにくい)
今回はイメージ(抽象的)ではなくリアル(現実的)に、ということで今回は具体例を挙げてみました。


hello world


[ツール]⇢[NuGet パッケージマネージャー]⇢[パッケージマネージャーコンソール]を開いて、必要なパッケージをインストールする。


install-package Microsoft.Owin.Hosting -IncludePreRelease
install-package Microsoft.Owin.Host.HttpListener –IncludePreRelease
install-package Microsoft.Owin.Diagnostics –IncludePreRelease
install-Package Owin.Extensions -IncludePrerelease


プロジェクトでコンソールアプリケーションを選択して、

using Microsoft.Owin.Hosting;
using Owin;
static void Main(string[] args)
{
    string uri = "http://localhost:8080/";
    using (WebApp.Start(uri))
    {
        Console.WriteLine("Started");
        Console.ReadKey();
        Console.WriteLine("Stopping");
    }
}
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseWelcomePage();
    }
}

こんなコースコードを書いて実行。
ブラウザ上で「http://localhost:8000」にアクセスすると、下の画面が出てきたら成功。
ちなみに「http://127.0.0.1:8000」だとエラー画面が出るので注意。





独自のコンテンツを展開する場合は、
public class Startup
{
    public void Configuration(IAppBuilder app)
    {        
        app.UseHandlerAsync((req, res) =>
        {
            res.ContentType = "text/plain";
            return res.WriteAsync("Hello, World!");
        });
    }
}
スタートアップクラスを書き換える。


参考URL

http://odetocode.com/blogs/scott/archive/2013/07/09/getting-started-with-owin-katana-and-vs2013.aspx



FTDIドライバをLinux/Window cross-platform 対応にする

LoadLibrary周りがWindowsAPI直接利用しているので、この部分をLinuxに対応させなくては行けない。

ということで参考サイトをみると、その部分はインターフェイスに分離してWin/Linux切り替えできるように実装する方法が乗っていたのでやり方を書いていく。

まずはインターフェイス
interface DllLoadUtils {
        IntPtr LoadLibrary(string fileName);
        void FreeLibrary(IntPtr handle);
        IntPtr GetProcAddress(IntPtr dllHandle, string name);
}

次に

Windows実装部
    public class DllLoadUtilsWindows : DllLoadUtils {
        void DllLoadUtils.FreeLibrary(IntPtr handle) {
            FreeLibrary(handle);
        }

        IntPtr DllLoadUtils.GetProcAddress(IntPtr dllHandle, string name) {
            return GetProcAddress(dllHandle, name);
        }

        IntPtr DllLoadUtils.LoadLibrary(string fileName) {
            return LoadLibrary(fileName);
        }

        [DllImport(" extern="" filename="" freelibrary="" getprocaddress="" handle="" int="" intptr="" kernel32.dll="" kernel32="" llimport="" loadlibrary="" ntptr="" pre="" private="" procedurename="" static="" string="">
Linux実装部
    internal class DllLoadUtilsLinux : DllLoadUtils {
        public IntPtr LoadLibrary(string fileName) {
            return dlopen(fileName, RTLD_NOW);
        }

        public void FreeLibrary(IntPtr handle) {
            dlclose(handle);
        }

        public IntPtr GetProcAddress(IntPtr dllHandle, string name) {
            // clear previous errors if any
            dlerror();
            var res = dlsym(dllHandle, name);
            var errPtr = dlerror();
            if (errPtr != IntPtr.Zero) {
                throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr));
            }
            return res;
        }

        const int RTLD_NOW = 2;

        [DllImport("libdl.so")]
        private static extern IntPtr dlopen(String fileName, int flags);
        
        [DllImport("libdl.so")]
        private static extern IntPtr dlsym(IntPtr handle, String symbol);

        [DllImport("libdl.so")]
        private static extern int dlclose(IntPtr handle);

        [DllImport("libdl.so")]
        private static extern IntPtr dlerror();
    }
こうすることでLinuxとWindowsで処理を分離できるようになったわけだがすでに呼び出ししてる箇所の置き換えは大変なので、関数でかぶせる感じにする。
  #region LOAD_LIBRARIES
  /// 
  /// Built-in Windows API functions to allow us to dynamically load our own DLL.
  /// Will allow us to use old versions of the DLL that do not have all of these functions available.
  /// 
  //[DllImport("kernel32.dll")]
  //private static extern IntPtr LoadLibrary(string dllToLoad);
  //[DllImport("kernel32.dll")]
  //private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
  //[DllImport("kernel32.dll")]
  //private static extern bool FreeLibrary(IntPtr hModule);
  private DllLoadUtils dllLoadUtils;
  private IntPtr LoadLibrary(string dllToLoad)
  {
   return this.dllLoadUtils.LoadLibrary(dllToLoad);
  }
  private IntPtr GetProcAddress(IntPtr hModule, string procedureName)
  {
   return this.dllLoadUtils.GetProcAddress(hModule, procedureName);
  }
  private bool FreeLibrary(IntPtr hModule)
  {
   this.dllLoadUtils.FreeLibrary(hModule);
  }
  private bool IsLinux() {
   var p = (int) Environment.OSVersion.Platform;
   return (p == 4) || (p == 6) || (p == 128);
  }
  #endregion
  public FTDI()
  {
   // If FTD2XX.DLL is NOT loaded already, load it
   if (hFTD2XXDLL == IntPtr.Zero)
   {
    // Load our FTD2XX.DLL library
    if (IsLinux())
    {
     this.dllLoadUtils = new DllLoadUtilsLinux() 
     hFTD2XXDLL = LoadLibrary(@"libftd2xx.so");
    }
    else
    {
     this.dllLoadUtils = new DllLoadUtilsWindows();
     hFTD2XXDLL = LoadLibrary(@"FTD2XX.DLL");
    }
                 ...
あとはMessageBox。System.Windows.Formsを利用しているのでLinuxでは利用できない。
なのでstaticクラスなスタブ関数を用意する。
    internal static class MessageBox
    {
        public static void Show(string message)
        {
            Console.WriteLine(message);
        }
    }

試しに.netアプリを使ってみるとDLLで対応していない?APIがあって
 Rescan
 Reload
 GetComPortNumber
この3つがエラーになった。
とりあえずコメントアウトしておくこと。

この後Linux側でオープンできないとかが発生した場合は
共有ライブラリ周りがおかしいので、詳細はこっちへ
http://ivis-mynikki.blogspot.jp/2015/02/raspberry-piftdi.html


参考サイト

http://dimitry-i.blogspot.jp/2013/01/mononet-how-to-dynamically-load-native.html

2015年2月28日土曜日

Cordova(Phone Gap) for Visual Studio 2013 環境構築編

これからスマートフォンアプリ開発を始めようと思うと
Android, iOS, Windows, WP8,,, 様々な環境に合わせて開発環境を構築する必要がある。
XamarinだとC#を覚えればすべての端末向けのアプリが作れるようになるが、無料版だと制限が厳しい。


Cordovaとは?
 クロスプラットフォームで1つ書けば複数のOS上で動作するライブラリである。
開発環境はWEB上で開発できるPhoneGapBuilderやMonacaなども存在する。
仕組みはブラウザ上で動くHTML+Javascriptなアプリであって、ネイティブアプリではない。
でもアプリを起動するにはネイティブアプリである必要があるので、その部分は開発者が書く必要がなくて、はじめからブラウザだけを表示するアプリが用意されている。
vc

インストールが簡単。
プラグイン管理。
統合されたデバッグ機能。
1 回の記述であらゆる場所に配置。


そこでオープンソースで使えそうなものを探してみたらHTML5の技術を使ったCordova(PhoneGap)を見つけたので、早速開発環境を構築してみた。
構築する方法は、拡張機能をインストールするだけだが9GB以上の空き容量がないとインストールできないのでその点だけ注意しておくこと。 インストール完了後、試しにプロジェクトを作ってF5で実行するとChromeブラウザ上のエミュレータが立ち上がってすんなりいけた。 デバッグを優先して考えたとき、ローカルな統合環境で行ったほうが楽なので
開発環境はVisualStudioをオススメしておく。


Step1.


参考:

https://msdn.microsoft.com/ja-jp/library/dn771545.aspx


Raspberry PiでFTDIデバイスドライバをインストールする

RPiでFTDIドライバを使おうと思ったときのメモ。

1.まずはドライバダウンロード

ドライバのページをみたらRPi用に用意されていた。





2.インストール
ドライバインストール手順はReadMeに記載してあるので注意点を追加しておく。


Installing the D2XX shared library and static library.
------------------------------------------------------

1.  tar xfvz libftd2xx1.1.12.tar.gz

 ここで気をつけないと行けないのは所有権です。


もし共有フォルダ経由でコピペしてきた場合はchownコマンドで変更します。

This unpacks the archive, creating the following directory structure:

    build
        arm926
        i386
        x86_64
    examples
    libusb
    ftd2xx.h
    WinTypes.h

2.  cd build/arm926
3.  sudo -s   or, if sudo is not available on your system:
    su

Promotes you to super-user, with installation privileges.  If you're
already root, then step 3 (and step 7) is not necessary.

4.  cp lib* /usr/local/lib
Copies the libraries to a central location.

5.  chmod 0755 /usr/local/lib/libftd2xx.so.1.1.12
Allows non-root access to the shared object.

6.  ln -sf /usr/local/lib/libftd2xx.so.1.1.12 /usr/local/lib/libftd2xx.so
Creates a symbolic link to the 1.1.12 version of the shared object.

7.  exit
Ends your super-user session.

インストール完了。
次は正しくビルドできるかexampleでテスト。

Building the shared-object examples.
------------------------------------

1.  cd examples
2.  make -B




 Multithread項目において、ビルドエラーがでるので、一部修正します。


$ vim MultiThread/Makefile

---

TOPDIR  := $(shell cd ..; pwd)
include $(TOPDIR)/Rules.make

APP = multi

all: $(APP)

$(APP): main.c
        $(CC) main.c -lpthread -o $(APP) $(CFLAGS)

clean:
        rm -f *.o ; rm $(APP)

---
-lpthread を追加する



This builds all the shared-object examples in subdirectories.

With an FTDI device connected to a USB port, try one of the
examples, e.g. reading EEPROM.

3.  cd EEPROM/read
4.  sudo ./read
If the message "FT_Open failed" appears:
    Perhaps the kernel automatically loaded another driver for the
    FTDI USB device.

    sudo lsmod

    If "ftdi_sio" is listed:
        Unload it (and its helper module, usbserial), as follows.

        sudo rmmod ftdi_sio
        sudo rmmod usbserial

    Otherwise, it's possible that libftd2xx does not recognise your
    device's Vendor and Product Identifiers.  Call FT_SetVIDPID before
    calling FT_Open/FT_OpenEx/FT_ListDevices.


ここでDeviceOpenが出来ないなんていう自体が発生する
そういう時は
$ ldd read

コマンドを売ってみると
 libftd2xx -> not found 

というメッセージが出ていると思う。

じゃあ
$sudo vim /etc/ld.so.conf.d/libc.conf
 /usr/local/lib

を追加してから、

$ sudo ldconfig

を実行して共有ライブラリのDBを更新する。

$ ldconfig -p

 libftd2xx.so => /usr/local/lib/libftd2xx.s
こんな行があれば共有ライブラリは見つかるようになっている。

再度、

$ldd read

をやってみてまだnot found が出てる場合、

libftd2xx.so (libc6,hard-float) => /usr/local/lib/libftd2xx.so

 他のライブラリはhard-float ってついてるのにコピーしてきたlibftd2xx.soはついてない!

という場合はhard-floatでコンパイルされたlibftd2xx.soを使用する必要がある。

このファイルはネット上の
 https://s3.amazonaws.com/hayk-public/arm926-hf.zip

ここにあったので利用させてもらってます。
もし不安なら自前でビルドするしか無いでしょう。

 入れ替えてから
$ sudo ldconfig
$ ldconfig -p
やってみて hard-float になった事を確認して
$ ldd read 
でリンクが通ったか見てみると

ibftd2xx.so => /usr/local/lib/libftd2xx.so (0x76f14000)

ようやく共有ライブラリのリンクが見つかったのがわかる。

これは気づかないと分からないので、
ARMの世界には 32bit 64bit みたいに hard-float と soft-floatの2種類が混在しているということを覚えておくと迷わなくなる。



参考URL

http://www.ftdichip.com/Drivers/D2XX.htm
http://stackoverflow.com/questions/24096807/dso-missing-from-command-line

http://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_132_Adding_FTDI_Devices_VCP_Driver_Support_to_Android.pdf

2015年2月20日金曜日

RaspberryPi + KTV-FSUSB2 を 2台 で 同時2番組録画 + 裏で1番組視聴に成功

recfsusb2nのソースコードを見てみたら、USBデバイスを総当りに検索して、オープンしたら排他ロックするような仕組みとなっていて、複数デバイスに対応しているようだったので試してみた。

ハードウェア構成は、
RaspberryPi [Turbo設定]
 USB経由で
  2TBハードディスク(3.5インチ)
  KTV-FSUSB2 x 2台
  セルフパワーUSBハブ(※アダプターなしで同時録画すると電力不足でフリーズする)

動作確認するため、続けて下記コマンドを実行する。

$ recfsusb2n --b25 --sid hd --wait 10 25 30 /mnt/hdd2tb/testesA.ts &
$ recfsusb2n --b25 --sid hd --wait 10 25 30 /mnt/hdd2tb/testesB.ts &

-----1つ目のデバイス-----
recfsusb2n ver. 0.9.2
ISDB-T DTV Tuner FSUSB2N
device: "/dev/bus/usb/001/012" ←デバイスオープンpid = 3263
B25Decoder initialized.

-----2つ目のデバイス-----
recfsusb2n ver. 0.9.2
ISDB-T DTV Tuner FSUSB2N
share violation ←1つ目のデバイスは使用中
device: "/dev/bus/usb/001/011" ←別のデバイスをオープンpid = 3265
B25Decoder initialized.
Available sid = 1040 1041 1424
Chosen sid    = 1040

さらに2番組同時録画しながら裏で1番組視聴。

こんな使い方しても視聴番組はスムーズに再生できていて
フレーム落ちなどせず2番組とも録画が出来ていた。


後は、Mpeg2TS→Mpeg4へトランスコードすれば容量削減+Chromebookで番組視聴ができる予定。

Androider