マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

Windows 10 IoT Coreの評価を実施中。

基本

Headモード、Headlessモード

Headモード

  • GUI有りモード

Headlessモード

  • GUI無しモード
  • リソース消費を抑えることが出来る。

切替方法

以下のコマンドで切り替え可能。

  • Headlessモードに変更
    setbootoption.exe headless
    shutdown /r /t 0
  • Headlessモードに変更
    setbootoption.exe head
    shutdown /r /t 0

ドライバの種類

Inboxドライバ

  • プラグ・アンド・プレイに対応した機器をパソコンに接続すると、
    Windowsに同梱されるドライバの中から自動的にドライバが選択され組み込まれる。
  • このため、すぐに周辺機器が使えるようになる。
  • この、Windowsに同梱されているドライバを、Inboxドライバと呼ぶ。

DMAPドライバ

  • DMAP : Direct Memory Mapped
  • InboxドライバよりもGPIOパフォーマンスの向上を実現する開発用ドライバ
  • 悪意のあるアプリはH/W、Securityの問題を引き起こす可能性がある。

準備

開発用PC

OS

Windows 10とする。

ネットワーク

企業内なら、開発用NWとインターネットへの接続が許可されているもの。

  • 開発用NW : Windows 10 IoT Coreはイントラのセキュリティ・ポリシーと異なるため。
  • インターネット・アクセス: NuGetやWebサービス、クラウドの利用にあたって必要になる。

なお、PC-IoT間は開発用NWを使用し、インターネット・アクセスにはAPを経由して出ると良い。

IoT機器

本体

Raspberry Pi 3 MODEL B

電源

micro USB(Androidと同じ)

周辺機器

ストレージ

  • microSDメモリーカード(Raspberry Pi 3に挿す)
  • microSD から メモリーカード への 変換アダプター(開発用PCに挿す)

ネットワーク

スイッチとして機能する機器(開発用PCとRaspberry Pi 3を接続する)

  • 有線LANの場合: L2スイッチとLANケーブル
  • 無線LANの場合: プライバシー・セパレータ機能を搭載したWi-Fiルーター

入出力

  • モニタとHDMI ケーブル。
  • USB マウス, USB キーボード

セットアップ

Windows 10 IoT Coreのインストール

Windows 10 IoT Core Dashboardのダウンロード

  • Get Windows 10 IoT Core Dashboardをクリック
  • setup.exeがダウンロードされるのでダブルクリックして実行
  • Windows 10 IoT Core Dashboardをインストールする。

microSDにWindows 10 IoT CoreのOSイメージを書き込む。

  • インストール後、そのままWindows 10 IoT Core Dashboardが起動する。
  • 「microSD から メモリーカード への 変換アダプター」を開発用PCに挿す。
  • [新しいデバイスのセットアップ]で以下の入力を行う。
  • [ダウンロードとインストール]をクリックしてmicroSDにOSイメージを書き込む。
セットアップ
  • はじめに、Windows 10 IoT Coreがダウンロードされる。
  • 次に、microSDにOSイメージを書き込まれる(フラッシング)。
    この際、コマンド・プロンプトで進捗表示がされる。
  • 書き込みが完了すると「SDカードは準備が完了しています」と表示される。
  • この画面で表示されている「3.デバイスを検索します」の「自分のデバイス」ボタンを押下し、
    「Dashboard」と「Raspberry Pi 3」との通信を許可しておく。
    Windows10IoTCoreDashboard?.exeのインバウンドが許可される。

Raspberry Pi 3へ機器を接続

  • 電源
    • micro USB(Androidと同じ)
  • 周辺機器
    • OSイメージを書き込んだ microSD を挿す。
    • 有線接続の場合、LANケーブルに接続する。
  • 入出力
    • USB マウス、USB キーボード
    • モニタ(HDMI ケーブル)

Windows 10 IoT Coreの初期設定をする。

起動時

  • 言語を選択する(日本語を選択)。
  • 無線LANの場合、
    • Wi-Fiを選択可能
    • IPアドレスはDHCPで自動配布される。
  • 有線LANの場合、
    • 起動前にLANケーブルを接続しておく。
    • IPアドレスはAPIPAのアドレスになっている。

その他、適宜

  • コマンド・プロンプト
    • コマンド・ラインを選択して、
    • Administratorのログイン・アカウント情報を入力する。
    • コマンド・プロンプトを使用できるようになる。

Windows 10 IoT Core Dashboardから接続・操作する。

  • 開発用PC側のIPアドレスの設定
  • 無線LANの場合、
    DHCPで自動配布されるアドレスで通信可能なので設定は不要。
  • 有線LANの場合、
    APIPAのアドレスを確認し、開発用PCのアドレスを設定・変更する。
    • IPアドレス : 169.254.x.x
    • サブネットマスク : 255.255.0.0
  • Windows 10 IoT Core Dashboardを起動する。
  • 「自分のデバイス」からRaspberry Pi 3を選択、

Device Portal

  • 接続
    • 右クリック、[Device Portalで開く]を選択する。
    • Administratorのログイン・アカウント情報を入力する。
    • ログイン後、Device Portalが表示される。
  • 操作
    • Device Portalから操作する。
    • HOME:タイムゾーンの変更
    • PROCESS: 電源(再起動など)
  • ,etc.

SMB

  • 接続
    • 右クリック、[ネットワーク共有を開く]を選択する。
      上手く行かない時は、「\\[Raspberry Pi 3のIPアドレス]\C$」を直打ち。
    • Administratorのログイン・アカウント情報を入力する。
    • 「\\[Raspberry Pi 3のIPアドレス]\C$」が開く。

PowerShell

  • 接続
    • 右クリック、[PowerShellを起動]を選択する。
    • Administratorのログイン・アカウント情報を入力する。
  • 操作
    • コマンドやコマンドレットを実行できる。
  • IPアドレスの設定(APIPAアドレスなら、必要に応じて変更すると良い)
    • 設定方法
      ipconfig /all
      netsh interface ip show config
      netsh interface ip set address "Ethernet" static [IPアドレス] [サブネットマスク] [デフォゲ]
    • 設定例
  • Administratorのパスワードを設定/変更する。
    net user Administrator [パスワード]
  • ローカルコンピュータの新しい NetBIOS 名を設定
    setcomputername [新しいマシン名]

開発用PC側のIPアドレスを設定/変更する。

IPアドレス、サブネットマスクなどを変更する。

  • Windows 10 IoT Core側の設定に合わせて、
    IPアドレス、サブネットマスクなどを変更する。
    netsh interface ip set address "Ethernet" static 192.168.1.1 255.255.255.0
  • 設定変更後、
    • PowerShellが切断される。
    • Dashboardの「自分のデバイス」のIPアドレスが更新される。

モバイルホットスポットでインターネット接続を共有する。

Windows 10 IoT Coreとモバイルホットスポット(Wi-Fi)で開発用PCのインターネット接続を共有する。

この設定を行えば、開発用PCと、Windows 10 IoT Coreが、
192.168.137.0/24のサブネットで接続できるようになり、インターネット接続も共有可能になる。

ただし、Dashboardから操作するために、有線LAN接続は引き続き必要になる。

開発環境

開発用PCの準備

Windows 10がインストールされた開発用PCを準備する。

開発環境のセットアップ

Visual Studio 2017をインストールする。

  • ターゲットがCreators Updade対象になっているようで、Visual Studio 2015ではなく2017が必要。
  • インストール時に、ユニバーサル Windowsアプリ開発ツールをインストールすること。

開発者モードを有効にする。

Windows SDKのインストール

Windows 10 用のWindows SDKをダウンロードしてインストールする。

  • Windows 10 用のWindows SDKをダウンロード
  • 以下から選択可能だが、ここでは1台だけの構築なのでEXEを選択する。
    • .EXE をダウンロードする
    • .ISO をダウンロードする
  • Windows 10 用のWindows SDKをインストール
    • winsdksetup.exeをダブルクリックしてインストーラを実行。
    • インストーラーが起動したら既定値でインストールする。
  • インストールが完了したら、OSを再起動する。

“Hello World”的にサンプルを実行する準備

サンプル・プログラムをGitHubからDownloadZIPする。

  • 解凍して、HelloWorld?HelloBlinky?を入手する。

HelloWorld?する。

  • HelloWorld?.slnをダブルクリックしてVS 2017を起動する。
  • [Debug]ボタンのドロップダウンから[リモート コンピューター]を選択。
  • 以下の入力を行う。
    • アドレス: IPアドレスを手打ち(自動検出できなかった場合)
    • 認証モード: ユニバーサル(暗号化されていないプロトコル)
    • [選択]ボタンを押下する。
  • [Debug]ボタンを押下する。
  • Hello Worldのメッセージが表示される。

HelloBlinky?する。

  • HelloWorld?.slnと同じ手順で、HelloBlinky?.slnをDebug実行する。
    • (2回目なので、)自動検出されているRaspberry Pi 3を選択する。
    • GPIO pinsの初期化が正しく行われた旨のメッセージが表示される。

サンプル・プログラムをデプロイして起動する。

デプロイ

  • [ソリューション構成]を「Release」に変更し、
  • [ビルド]から「xxの配置」を選択する。
  • [配置が完了しました]・・・の[完全パッケージ名]をメモしておく。

スタートアップアプリに指定

  • 以下のコマンドを実行する。
    iotstartup list
  • アプリが配置されていることを確認する。
  • 以下のコマンドを実行してスタートアップアプリに登録する。
    iotstartup add headed 完全パッケージ名の先頭部分
  • shutdown /r /t 0で再起動すれば、次回起動時から自作のIoTアプリが起動する。
  • 元のIoT Coreメイン画面に戻すには、以下でスタートアップアプリを切り替える。
    iotstartup add headed IoTCoreDefaultApp

いろいろな処理を実装する。

空のプロジェクトから実装を始める。

プロジェクトの新規作成

  • [新規作成]-[プロジェクト]
  • [テンプレート]-[Visual C#]
    • GUI有りのIoTアプリ
      [Windows ユニバーサル]-[空白のアプリ]を選択
    • GUI無しのIoTアプリ
      [Windows IoT Core]-[Background Application (IoT)]を選択

UWP バージョンを選択する

[ターゲットバージョン]と[最小バージョン]を選択する。

  • UWP バージョンの説明
    • ターゲットバージョン :一般ユーザー向けのコードを新しく開発する場合、常に最新ビルドの Windows (14393) を使う。
    • 最小バージョン :エンタープライズ アプリを開発する場合は、最小バージョンで古いバージョンをサポートすることを検討する。

Debug実行

  • この状態だと、選択したUWP バージョン次第で、ローカルでのDebug実行も可能。
    しかし、以降、H/Wに関する処理を実装していくとローカルでのDebug実行はできなくなる。
  • HelloWorld.slnHelloBlinky.slnと同じ手順でコレをDebug実行する。
    • [ターゲットCPU]を[x86]から[ARM]に変更してから、
    • [リモート コンピューター]でDebug実行する。
  • 空のウィンドウが表示されることを確認する。

Writing apps開発の設定を行う

  • 参照設定で[Universal Windows]-[拡張]-[Windows IoT Extension for the UWP]をチェックする。
  • NuGetから「Direct Memory Mapped Driver」の「Microsoft.IoT.Lightning」をインストールして参照設定を追加。
  • 以下の「Direct Memory Mapped Driver」の「Microsoft.IoT.Lightning」を利用するための設定を行う。
  • [Device Portal]からドライバを切替える。
    • [Devices]をクリックしてページを切り替える。
    • [Default Controller Driver]を[Direct Memory Mapped Driver]に設定する。
    • 「Warning: This option will reduce Windows security
      in exchange for performance using an in development driver.」と表示される。
    • [Update Driver]をクリックしてドライバ設定を更新する。
    • リブートするかどうかのメッセージが表示されるのでリブートする。
  • 以下のコードをマニフェストファイル(Package.appxmanifest)に追加。
  • Capabilities要素に以下を追加する。
    <Capabilities>
        <!-- アプリケーションがカスタムデバイスにアクセスできるようにする -->
        <iot:Capability Name="lowLevelDevices" />
        <!-- LightningインターフェースのデバイスGUID ID -->
        <DeviceCapability Name="109b86ad-f53d-4b76-aa5f-821e2ddf2141"/>
    </Capabilities>
  • package要素に上記のiot名前空間を追加する。
     xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
     xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
     IgnorableNamespaces="uap mp iot">

Lチカを実装する。

デバイス

Apple PiのLEDのGPIO numberについては、下記を参照のこと。

MainPage?.xaml.cs

using System.Threading.Tasks;
using Windows.Devices;
using Windows.Devices.Gpio;
using Microsoft.IoT.Lightning.Providers;

namespace App1
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        /// <summary>
        /// GpioPin #5は青色
        /// GpioPin #6は白色
        /// </summary>
        private readonly int LED_PIN = 6;

        /// <summary>GpioPin</summary>
        private GpioPin _gpioPin;

        /// <summary>Lチカを実装する。</summary>
        public MainPage()
        {
            this.InitializeComponent();

            // LightningProviderが利用可能かどうかチェックする。
            if (LightningProvider.IsLightningEnabled)
            {
                // LowLevelDevicesAggregateProviderを取得
                LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
            }

            // GpioControllerを取得
            GpioController gpioCtrl = GpioController.GetDefault();

            if (gpioCtrl == null)
            {
                return;
            }

            // GpioControllerでGpioを取得
            this._gpioPin = gpioCtrl.OpenPin(LED_PIN);
            // GpioPinでGpioPinをコントロール。
            this._gpioPin.SetDriveMode(GpioPinDriveMode.Output);
            this._gpioPin.Write(GpioPinValue.High);

            this.loop();
        }

        /// <summary>
        /// UIをハングさせないよう、asyncなloop内でawaitを使用する。
        /// System.Threading.Threadが無いので、こうなる。
        /// </summary>
        private async void loop()
        {
            while (true)
            {
                // GpioPinでGpioPinをコントロール。
                await Task.Delay(1000);
                this._gpioPin.Write(GpioPinValue.Low);
                await Task.Delay(1000);
                this._gpioPin.Write(GpioPinValue.High);
            }
        }
    }
}

LCDに文字を表示する。

デバイス

MainPage?.xaml.cs

using System.Text;
using System.Threading.Tasks;
using Windows.Devices;
using Windows.Devices.I2c;
using Microsoft.IoT.Lightning.Providers;

// 空白ページの項目テンプレートについては、https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x411 を参照してください

namespace App1
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        /// <summary>
        /// Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
        ///  (ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ)
        /// http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_gpio_enable_i2c/
        /// </summary>
        private readonly byte _Lcd_Addr = 0x3e;
 
        /// <summary>I2cDevice</summary>
        private I2cDevice _Lcd;
 
        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }
 
        /// <summary>Loaded</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            await this.InitLcd();
            await this.DisplayLcd();
        }
 
        /// <summary>
        /// LCDを初期化する。
        /// 電子工作 - .NET 開発基盤部会 Wiki > 周辺機器 > LCD(液晶ディスプレイ)> I2C LCD AQM0802
        /// https://dotnetdevelopmentinfrastructure.osscons.jp/index.php?%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C#b226d3e8
        /// </summary>
        private async Task InitLcd()
        {
            // LightningProviderが利用可能かどうかチェックする。
            if (LightningProvider.IsLightningEnabled)
            {
                // LowLevelDevicesAggregateProviderを取得
                LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
            }
 
            // I2cControllerを取得
            I2cController i2cCtrl = await I2cController.GetDefaultAsync();
 
            if (i2cCtrl == null)
            {
                return;
            }
 
            // I2cControllerでLCDを取得。
            this._Lcd = i2cCtrl.GetDevice(new I2cConnectionSettings(this._Lcd_Addr));
 
            // 初期化
            await WriteLcdCmd(0x38, 1); // 行数の設定
            await WriteLcdCmd(0x39, 1); // 拡張コマンドの設定開始
            await WriteLcdCmd(0x14, 1); // 内部OSC周波設定
            await WriteLcdCmd(0x70, 1); // コントラスト設定
            await WriteLcdCmd(0x56, 1); // パワー/アイコン コントラスト設定
            await WriteLcdCmd(0x6c, 250); // Follower設定
            await WriteLcdCmd(0x38, 1); // 拡張コマンドの設定終了
            await WriteLcdCmd(0x0c, 1); // ディスプレイ オン
            await WriteLcdCmd(0x01, 2); // ディスプレイ クリア
        }
 
        /// <summary>LCDに表示する</summary>
        /// <returns>Task</returns>
        private async Task DisplayLcd()
        {
            await WriteLcdCmd(0x01, 2); // ディスプレイ クリア
 
            // 一行目を指定して
            await WriteLcdCmd(0x80, 1); // Set DDRAM Address
            await WriteLcdDisplay("RzPi3"); // Write data to RAM
 
            // 二行目を指定して
            await WriteLcdCmd(0xc0, 2); // Set DDRAM Address
            await WriteLcdDisplay("ApplePi"); // Write data to RAM
        }
 
        /// <summary>LCDにコマンドを送る</summary>
        /// <param name="cmd">byte</param>
        /// <param name="waitTime_msec">int</param>
        /// <returns>Task</returns>
        private async Task WriteLcdCmd(byte cmd, int waitTime_msec)
        {
            // I2cDeviceでLCDをコントロール。
            // 10 bit 書くので2 byte で先頭は空なので 0.
            this._Lcd.Write(new byte[] { 0, cmd });
            await Task.Delay(waitTime_msec);
        }
 
        /// <summary>LCDに表示する</summary>
        /// <param name="msg">string</param>
        /// <returns>Task</returns>
        private async Task WriteLcdDisplay(string msg)
        {
            byte[] bytesMSG = Encoding.ASCII.GetBytes(msg);
 
            // I2cDeviceでLCDをコントロール。
            foreach (byte b in bytesMSG)
            {
                // 10 bit 書くので2 byte で先頭は・・・
                this._Lcd.Write(new byte[] { 0x40, b }); // 先頭0x40は?
            }
            await Task.Delay(1);
        }
    }
}

センサーからデータを取得する。

デバイス

MainPage?.xaml

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock x:Name="tbkTMP" Text="tbkTMP" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 140, 0, 0" TextWrapping="Wrap" FontSize="36" />
        <TextBlock x:Name="tbkHUM" Text="tbkHUM" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 210, 0, 0" TextWrapping="Wrap" FontSize="36" />
        <TextBlock x:Name="tbkPRE" Text="tbkPRE" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 280, 0, 0" TextWrapping="Wrap" FontSize="36" />
    </Grid>
</Page>

MainPage?.xaml.cs

のコードを一部、修正して動かした。

using System.Threading;
using System.Diagnostics;

// 空白ページの項目テンプレートについては、https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x411 を参照してください

namespace App1
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        /// <summary>ライブラリ</summary>
        private BME280 bme280;
        /// <summary>タイマー</summary>
        private Timer periodicTimer;

        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }

        /// <summary>Loaded</summary>
        /// <param name="sender">object</param>
        /// <param name="e">RoutedEventArgs</param>
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.bme280 = new BME280();
            this.initBme280();
        }

        /// <summary>初期化</summary>
        private async void initBme280()
        {
            await this.bme280.Initialize();
            this.periodicTimer = new Timer(this.TimerCallback, null, 0, 1000);
        }

        /// <summary>TimerCallback</summary>
        /// <param name="state">object</param>
        private void TimerCallback(object state)
        {
            // ココの処理はBackground Threadで動作する。

            var temp = bme280.ReadTemperature();
            var press = bme280.ReadPreasure() / 100;
            var humidity = bme280.ReadHumidity();
            var alt = bme280.ReadAltitude(1013);   // 1013hPa = pressure at 0m

            Debug.WriteLine(
                "Temp:{0:F2}℃ Humidity:{1:F2}% Press:{2:F2}hPa Alt:{3:F0}m",
                temp, humidity, press, alt);

            // 主スレッドで処理する(以下はUWPでのControl.Invokeの書き方らしい)
            var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                this.tbkTMP.Text = temp.ToString("F2") + "℃";
                this.tbkHUM.Text = humidity.ToString("F2") + "%";
                this.tbkPRE.Text = press.ToString("F2") + "hPa";
            });
        }
    }
}

BME280.cs

using System;
using System.Threading.Tasks;
using System.Diagnostics;

using Windows.Devices;
using Windows.Devices.I2c;
using Microsoft.IoT.Lightning.Providers;

namespace App1
{
    /// <summary>BME280キャリブレーション用</summary>
    public class BME280_CalibrationData
    {
        // BME280 Registers

        /// <summary></summary>
        public ushort dig_T1 { get; set; }
        /// <summary></summary>
        public short dig_T2 { get; set; }
        /// <summary></summary>
        public short dig_T3 { get; set; }

        /// <summary></summary>
        public ushort dig_P1 { get; set; }
        /// <summary></summary>
        public short dig_P2 { get; set; }
        /// <summary></summary>
        public short dig_P3 { get; set; }
        /// <summary></summary>
        public short dig_P4 { get; set; }
        /// <summary></summary>
        public short dig_P5 { get; set; }
        /// <summary></summary>
        public short dig_P6 { get; set; }
        /// <summary></summary>
        public short dig_P7 { get; set; }
        /// <summary></summary>
        public short dig_P8 { get; set; }
        /// <summary></summary>
        public short dig_P9 { get; set; }

        /// <summary></summary>
        public byte dig_H1 { get; set; }
        /// <summary></summary>
        public short dig_H2 { get; set; }
        /// <summary></summary>
        public byte dig_H3 { get; set; }
        /// <summary></summary>
        public short dig_H4 { get; set; }
        /// <summary></summary>
        public short dig_H5 { get; set; }
        /// <summary></summary>
        public sbyte dig_H6 { get; set; }
    }

    /// <summary>BME280 本体</summary>
    public class BME280
    {
        #region 各種列挙型

        /// <summary>キャリブレーションデータのレジスタアドレス</summary>
        enum eCalibrationDataRegistersAddress : byte
        {
            BME280_REGISTER_DIG_T1 = 0x88,
            BME280_REGISTER_DIG_T2 = 0x8A,
            BME280_REGISTER_DIG_T3 = 0x8C,

            BME280_REGISTER_DIG_P1 = 0x8E,
            BME280_REGISTER_DIG_P2 = 0x90,
            BME280_REGISTER_DIG_P3 = 0x92,
            BME280_REGISTER_DIG_P4 = 0x94,
            BME280_REGISTER_DIG_P5 = 0x96,
            BME280_REGISTER_DIG_P6 = 0x98,
            BME280_REGISTER_DIG_P7 = 0x9A,
            BME280_REGISTER_DIG_P8 = 0x9C,
            BME280_REGISTER_DIG_P9 = 0x9E,

            BME280_REGISTER_DIG_H1 = 0xA1,
            BME280_REGISTER_DIG_H2 = 0xE1,
            BME280_REGISTER_DIG_H3 = 0xE3,
            BME280_REGISTER_DIG_H4_L = 0xE4,
            BME280_REGISTER_DIG_H4_H = 0xE5,
            BME280_REGISTER_DIG_H5_L = 0xE5,
            BME280_REGISTER_DIG_H5_H = 0xE6,
            BME280_REGISTER_DIG_H6 = 0xE7,
        };

        /// <summary>測定データのレジスタアドレス</summary>
        enum eDataRegistersAddress : byte
        {
            BME280_REGISTER_PRESSUREDATA_MSB = 0xF7,
            BME280_REGISTER_PRESSUREDATA_LSB = 0xF8,
            BME280_REGISTER_PRESSUREDATA_XLSB = 0xF9, // bits <7:4>

            BME280_REGISTER_TEMPDATA_MSB = 0xFA,
            BME280_REGISTER_TEMPDATA_LSB = 0xFB,
            BME280_REGISTER_TEMPDATA_XLSB = 0xFC, // bits <7:4>

            BME280_REGISTER_HUMIDDATA_MSB = 0xFD,
            BME280_REGISTER_HUMIDDATA_LSB = 0xFE,
        };

        /// <summary>コマンド</summary>
        enum eCmd : byte
        {
            BME280_REGISTER_CHIPID = 0xD0,
            BME280_REGISTER_SOFTRESET = 0xE0,

            BME280_REGISTER_CONTROLHUMID = 0xF2,
            BME280_REGISTER_STATUS = 0xF3,
            BME280_REGISTER_CONTROL = 0xF4,
            BME280_REGISTER_CONFIG = 0xF5,
        };

        /// <summary>
        /// 
        /// Enables 2-wire I2C interface when set to ‘0’
        /// </summary>
        public enum interface_mode_e : byte
        {
            i2c = 0,
            spi = 1
        };

        /// <summary>
        /// スタンバイ時間のオプション
        /// t_sb standby options
        /// effectively the gap between automatic measurements when in "normal" mode
        /// </summary>
        public enum standbySettings_e : byte
        {
            tsb_0p5ms = 0,
            tsb_62p5ms = 1,
            tsb_125ms = 2,
            tsb_250ms = 3,
            tsb_500ms = 4,
            tsb_1000ms = 5,
            tsb_10ms = 6,
            tsb_20ms = 7
        };

        /// <summary>
        /// BME280のモード設定
        /// sensor modes,
        /// it starts off in sleep mode on power on forced is to take a single measurement now normal takes measurements reqularly automatically
        /// </summary>
        public enum mode_e : byte
        {
            smSleep = 0,
            smForced = 1,
            smNormal = 3
        };

        /// <summary>
        /// IIRフィルタの有効/無効
        /// Filter coefficients
        /// higher numbers slow down changes, such as slamming doors
        /// </summary>
        public enum filterCoefficient_e : byte
        {
            fc_off = 0, // OFF
            fc_2 = 1,
            fc_4 = 2,
            fc_8 = 3,
            fc_16 = 4
        };

        /// <summary>
        /// Oversampling options for humidity
        /// Oversampling reduces the noise from the sensor
        /// </summary>
        public enum oversampling_e : byte
        {
            osSkipped = 0,
            os1x = 1,
            os2x = 2,
            os4x = 3,
            os8x = 4,
            os16x = 5
        };

        #endregion

        #region メンバ変数

        /// <summary>
        /// Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
        ///  (ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ)
        /// http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_gpio_enable_i2c/
        /// </summary>
        const byte BME280_Address = 0x76;

        /// <summary>
        /// BME280 device signature
        /// </summary>
        const byte BME280_Signature = 0x60;

        /// <summary>
        /// String for the friendly name of the I2C bus 
        /// </summary>
        private const string I2CControllerName = "I2C1";

        /// <summary>
        /// Create an I2C device
        /// </summary>
        private I2cDevice bme280 = null;

        /// <summary>
        /// キャリブレーション
        /// Create new calibration data for the sensor
        /// </summary>
        private BME280_CalibrationData CalibrationData;
        
        /// <summary>インターフェイスモード</summary>
        private byte spi3w_en = (byte)interface_mode_e.i2c;

        /// <summary>スタンバイ時間のオプション</summary>
        private byte t_sb;
        /// <summary>BME280のモード設定</summary>
        private byte mode;
        /// <summary>IIRフィルタの有効/無効(サンプリング回数)</summary>
        private byte filter;
        
        /// <summary>温度測定の有効(オーバーサンプリング値)/無効</summary>
        private byte osrs_t;
        /// <summary>気圧測定の有効(オーバーサンプリング値)/無効</summary>
        private byte osrs_p;
        /// <summary>湿度測定の有効(オーバーサンプリング値)/無告</summary>
        private byte osrs_h;

        /// <summary>データ校正用変数</summary>
        private Int32 t_fine;

        #endregion

        /// <summary>Constructor</summary>
        /// <param name="t_sb">スタンバイ時間のオプション</param>
        /// <param name="mode">BME280のモード設定</param>
        /// <param name="filter">IIRフィルタの有効/無効(サンプリング回数)</param>
        /// <param name="osrs_t">温度測定の有効(オーバーサンプリング値)/無効</param>
        /// <param name="osrs_p">気圧測定の有効(オーバーサンプリング値)/無効</param>
        /// <param name="osrs_h">湿度測定の有効(オーバーサンプリング値)/無告</param>
        public BME280(standbySettings_e t_sb = standbySettings_e.tsb_0p5ms,    // 0.5msec
                      mode_e mode = mode_e.smNormal,                           // Normal
                      filterCoefficient_e filter = filterCoefficient_e.fc_16,  // サンプリング回数 * 16
                      oversampling_e osrs_t = oversampling_e.os2x,             // オーバーサンプリング * 2
                      oversampling_e osrs_p = oversampling_e.os16x,            // オーバーサンプリング * 16
                      oversampling_e osrs_h = oversampling_e.os1x)             // オーバーサンプリング * 1
        {
            this.t_sb = (byte)t_sb;
            this.mode = (byte)mode;
            this.filter = (byte)filter;
            this.osrs_t = (byte)osrs_t;
            this.osrs_p = (byte)osrs_p;
            this.osrs_h = (byte)osrs_h;
        }

        #region 初期化

        /// <summary>
        /// Method to initialize the BME280 sensor
        /// </summary>
        /// <returns></returns>
        public async Task Initialize()
        {
            Debug.WriteLine("BME280::Initialize");

            try
            {
                ////Instantiate the I2CConnectionSettings using the device address of the BME280
                //I2cConnectionSettings settings = new I2cConnectionSettings(BME280_Address);
                
                ////Set the I2C bus speed of connection to fast mode
                //settings.BusSpeed = I2cBusSpeed.FastMode;
                
                ////Use the I2CBus device selector to create an advanced query syntax string
                //string aqs = I2cDevice.GetDeviceSelector(I2CControllerName);
                
                ////Use the Windows.Devices.Enumeration.DeviceInformation class to create a collection using the advanced query syntax string
                //DeviceInformationCollection dis = await DeviceInformation.FindAllAsync(aqs);
                
                ////Instantiate the the BME280 I2C device using the device id of the I2CBus and the I2CConnectionSettings
                //bme280 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
                
                // LightningProviderが利用可能かどうかチェックする。
                if (LightningProvider.IsLightningEnabled)
                {
                    // LowLevelDevicesAggregateProviderを取得
                    LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
                }

                // I2cControllerを取得
                I2cController i2cCtrl = await I2cController.GetDefaultAsync();

                if (i2cCtrl == null)
                {
                    return;
                }

                // I2cControllerでbme280を取得。
                this.bme280 = i2cCtrl.GetDevice(new I2cConnectionSettings(BME280.BME280_Address));

                //Check if device was found
                if (this.bme280 == null)
                {
                    Debug.WriteLine("Device not found");
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine("Exception: " + e.Message + "\n" + e.StackTrace);
                throw;
            }

            byte[] readChipID = new byte[] { (byte)eCmd.BME280_REGISTER_CHIPID };
            byte[] ReadBuffer = new byte[] { 0xFF };

            // Read the device signature
            bme280.WriteRead(readChipID, ReadBuffer);
            Debug.WriteLine("BME280 Signature: " + ReadBuffer[0].ToString());

            // Verify the device signature
            if (ReadBuffer[0] != BME280.BME280_Signature)
            {
                Debug.WriteLine("BME280::Begin Signature Mismatch.");
                return;
            }

            // Read the coefficients table
            // キャリブレーション読み取り
            this.CalibrationData = this.ReadCoefficeints();

            #region レジスタの設定

            // Set configuration registers
            this.WriteConfigRegister();               // configレジスタ
            this.WriteControlMeasurementRegister();   // ctrl_measレジスタ
            this.WriteControlRegisterHumidity();      // ctrl_humレジスタ
            //Set configuration registers again to ensure configuration of humidity
            this.WriteConfigRegister();
            this.WriteControlMeasurementRegister();
            this.WriteControlRegisterHumidity();

            #endregion

            //Dummy read temp to setup t_fine
            this.ReadTemperature();
        }

        #region キャリブレーション読み取り

        /// <summary>
        /// BME280キャリブレーション読み取り
        /// Method to read the caliberation data from the registers
        /// </summary>
        /// <returns></returns>
        private BME280_CalibrationData ReadCoefficeints()
        {
            // 16 bit calibration data is stored as Little Endian, the helper method will do the byte swap.
            this.CalibrationData = new BME280_CalibrationData();

            // Read temperature calibration data
            this.CalibrationData.dig_T1 = this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T1);
            this.CalibrationData.dig_T2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T2);
            this.CalibrationData.dig_T3 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T3);

            // Read presure calibration data
            this.CalibrationData.dig_P1 = this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P1);
            this.CalibrationData.dig_P2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P2);
            this.CalibrationData.dig_P3 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P3);
            this.CalibrationData.dig_P4 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P4);
            this.CalibrationData.dig_P5 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P5);
            this.CalibrationData.dig_P6 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P6);
            this.CalibrationData.dig_P7 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P7);
            this.CalibrationData.dig_P8 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P8);
            this.CalibrationData.dig_P9 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P9);

            // Read humidity calibration data
            this.CalibrationData.dig_H1 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H1);
            this.CalibrationData.dig_H2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H2);
            this.CalibrationData.dig_H3 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H3);
            short e4                    = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H4_L);    // Read 0xE4
            short e5                    = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H4_H);    // Read 0xE5
            this.CalibrationData.dig_H4 = (short)((e4 << 4) + (e5 & 0x0F));
            short e6                    = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H5_H);    // Read 0xE6
            this.CalibrationData.dig_H5 = (short)((e5 >> 4) + (e6 << 4));
            this.CalibrationData.dig_H6 = (sbyte)this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H6);

            return CalibrationData;
        }

        #endregion

        #region レジスタの設定

        /// <summary>
        /// configレジスタの設定
        /// ・t_sb     : スタンバイ時間
        /// ・filter   : IIRフィルタの有効/無効
        /// ・spi3w_en : 3 wire SPIの有効/無効
        /// ----------
        /// Method to write the config register (default 16)
        /// 000  100  00
        /// ↑  ↑   ↑I2C mode
        /// ↑  ↑Filter coefficient = 16
        /// ↑t_sb = 0.5ms
        /// </summary>
        private void WriteConfigRegister()
        {
            byte value = (byte)((this.t_sb << 5) + (this.filter << 2) + this.spi3w_en);
            byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONFIG, value };
            bme280.Write(WriteBuffer);
            return;
        }

        /// <summary>
        /// ctrl_measレジスタの設定
        /// ・osrs_t : 温度測定の有効(オーバーサンプリング値)/無効
        /// ・osrs_p : 気圧測定の有効(オーバーサンプリング値)/無効
        /// ・mode   : BME280の測定モード設定
        /// ----------
        /// Method to write the control measurment register (default 87)
        /// 010  101  11 
        /// ↑  ↑   ↑ mode
        /// ↑  ↑ Pressure oversampling
        /// ↑ Temperature oversampling
        /// </summary>
        private void WriteControlMeasurementRegister()
        {
            byte value = (byte)((this.osrs_t << 5) + (this.osrs_p << 2) + this.mode);
            byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONTROL, value };
            bme280.Write(WriteBuffer);
            return;
        }

        /// <summary>
        /// ctrl_humレジスタの設定
        /// ・osrs_h : 湿度測定の有効(オーバーサンプリング値)/無告
        /// ----------
        /// Method to write the humidity control register (default 01)
        /// </summary>
        private void WriteControlRegisterHumidity()
        {
            byte value = this.osrs_h;
            byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONTROLHUMID, value };
            bme280.Write(WriteBuffer);
            return;
        }

        #endregion

        #endregion
        
        #region センサーを読む

        /// <summary>気温を読む</summary>
        /// <returns>float</returns>
        public float ReadTemperature()
        {
            //Read the MSB, LSB and bits 7:4 (XLSB) of the temperature from the BME280 registers
            byte tmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_MSB);
            byte tlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_LSB);
            byte txlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_XLSB); // bits 7:4

            //Combine the values into a 32-bit integer
            int t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4);

            //Convert the raw value to the temperature in degC
            double temp = this.BME280_compensate_T_double(t);

            //Return the temperature as a float value
            return (float)temp;
        }

        /// <summary>気圧を読む</summary>
        /// <returns>float</returns>
        public float ReadPreasure()
        {
            //Read the MSB, LSB and bits 7:4 (XLSB) of the pressure from the BME280 registers
            byte pmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_MSB);
            byte plsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_LSB);
            byte pxlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_XLSB); // bits 7:4

            //Combine the values into a 32-bit integer
            int p = (pmsb << 12) + (plsb << 4) + (pxlsb >> 4);

            //Convert the raw value to the pressure in Pa
            long pres = this.BME280_compensate_P_Int64(p);

            //Return the pressure as a float value
            return ((float)pres) / 256;
        }
        
        /// <summary>湿度を読む</summary>
        /// <returns></returns>
        public float ReadHumidity()
        {
            //Read the MSB and LSB of the humidity from the BME280 registers
            byte hmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_HUMIDDATA_MSB);
            byte hlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_HUMIDDATA_LSB);

            //Combine the values into a 32-bit integer
            int h = (hmsb << 8) + hlsb;

            //Convert the raw value to the humidity in %
            double humidity = this.BME280_compensate_H_double(h);

            //Return the humidity as a float value
            return (float)humidity;
        }

        #endregion

        #region 表示用文字列の作成

        /// <summary>
        /// ℃で温度を戻すメソッド
        /// 分解能は0.01℃。
        /// Method to return the temperature in DegC. Resolution is 0.01 DegC.
        /// Output value of “51.23” equals 51.23 DegC.
        /// </summary>
        /// <param name="adc_T"></param>
        /// <returns></returns>
        private double BME280_compensate_T_double(int adc_T)
        {
            double var1, var2, T;

            //The temperature is calculated using the compensation formula in the BME280 datasheet
            var1 = (adc_T / 16384.0 - CalibrationData.dig_T1 / 1024.0) * CalibrationData.dig_T2;
            var2 = ((adc_T / 131072.0 - CalibrationData.dig_T1 / 8192.0) *
                (adc_T / 131072.0 - CalibrationData.dig_T1 / 8192.0)) * CalibrationData.dig_T3;

            this.t_fine = (int)(var1 + var2);

            T = (var1 + var2) / 5120.0;
            return T;
        }

        /// <summary>
        /// Q24.8形式(24の整数ビットと8の小数ビット)のPaの圧力を返すメソッド。
        /// Method to returns the pressure in Pa, in Q24.8 format (24 integer bits and 8 fractional bits).
        /// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
        /// </summary>
        /// <param name="adc_P">int</param>
        /// <returns>long</returns>
        private long BME280_compensate_P_Int64(int adc_P)
        {
            long var1, var2, p;

            //The pressure is calculated using the compensation formula in the BME280 datasheet
            var1 = (long)this.t_fine - 128000;
            var2 = var1 * var1 * CalibrationData.dig_P6;
            var2 = var2 + ((var1 * CalibrationData.dig_P5) << 17);
            var2 = var2 + ((long)CalibrationData.dig_P4 << 35);
            var1 = ((var1 * var1 * CalibrationData.dig_P3) >> 8) + ((var1 * CalibrationData.dig_P2) << 12);
            var1 = (((long)1 << 47) + var1) * CalibrationData.dig_P1 >> 33;
            if (var1 == 0)
            {
                Debug.WriteLine("BME280_compensate_P_Int64 Jump out to avoid / 0");
                return 0; //Avoid exception caused by division by zero
            }

            //Perform calibration operations as per datasheet: 
            p = 1048576 - adc_P;
            p = (((p << 31) - var2) * 3125) / var1;
            var1 = ((long)CalibrationData.dig_P9 * (p >> 13) * (p >> 13)) >> 25;
            var2 = ((long)CalibrationData.dig_P8 * p) >> 19;
            p = ((p + var1 + var2) >> 8) + ((long)CalibrationData.dig_P7 << 4);
            return p;
        }

        /// <summary>
        /// %rHの湿度をdoubleとして返す。
        /// Returns humidity in %rH as as double. Output value of “46.332” represents 46.332 %rH
        /// </summary>
        /// <param name="adc_H"></param>
        /// <returns></returns>
        private double BME280_compensate_H_double(int adc_H)
        {
            double var_H;

            var_H = this.t_fine - 76800.0;
            var_H = (adc_H - (CalibrationData.dig_H4 * 64.0 + CalibrationData.dig_H5 / 16384.0 * var_H)) *
                CalibrationData.dig_H2 / 65536.0 * (1.0 + CalibrationData.dig_H6 / 67108864.0 * var_H *
                (1.0 + CalibrationData.dig_H3 / 67108864.0 * var_H));
            var_H = var_H * (1.0 - CalibrationData.dig_H1 * var_H / 524288.0);

            if (var_H > 100.0)
            {
                Debug.WriteLine("BME280_compensate_H_double Jump out to 100%");
                var_H = 100.0;
            }
            else if (var_H < 0.0)
            {
                Debug.WriteLine("BME280_compensate_H_double Jump under 0%");
                var_H = 0.0;
            }

            return var_H;
        }

        /// <summary>
        /// 気圧から高度を計算するメソッド
        /// Method to take the sea level pressure in Hectopascals(hPa) as a parameter and calculate the altitude using current pressure.
        /// </summary>
        /// <param name="seaLevel">float</param>
        /// <returns>float</returns>
        public float ReadAltitude(float seaLevel)
        {
            //Read the pressure first
            float pressure = this.ReadPreasure();
            //Convert the pressure to Hectopascals(hPa)
            pressure /= 100;

            //Calculate and return the altitude using the international barometric formula
            return 44330.0f * (1.0f - (float)Math.Pow((pressure / seaLevel), 0.1903f));
        }

        #endregion

        #region 読み取り

        /// <summary>
        /// Method to read an 8-bit value from a register
        /// </summary>
        /// <param name="register">byte</param>
        /// <returns>byte</returns>
        private byte ReadByte(byte register)
        {
            byte value = 0;
            byte[] writeBuffer = new byte[] { 0x00 };
            byte[] readBuffer = new byte[] { 0x00 };

            writeBuffer[0] = register;

            bme280.WriteRead(writeBuffer, readBuffer);
            value = readBuffer[0];
            return value;
        }

        /// <summary>
        /// Method to read a 16-bit value from a register and return it in little endian format
        /// </summary>
        /// <param name="register">byte</param>
        /// <returns>ushort</returns>
        private ushort ReadUInt16_LittleEndian(byte register)
        {
            ushort value = 0;
            byte[] writeBuffer = new byte[] { 0x00 };
            byte[] readBuffer = new byte[] { 0x00, 0x00 };

            writeBuffer[0] = register;

            bme280.WriteRead(writeBuffer, readBuffer);
            int h = readBuffer[1] << 8;
            int l = readBuffer[0];
            value = (ushort)(h + l);
            return value;
        }

        #endregion
    }
}

結果

SensorData

Twitterにセンサー情報をTweetする。

上記のセンサー情報をCoreTweet?というライブラリを使用してTwitterにTweetする。

CoreTweet?は、Twitter APIのクライアント・ライブラリなので、
非常に多機能っぽいが、ここではTweetするAPIを利用するだけ。

Twitterからエラーが返った場合、以下のエラー一覧が参考になる。

Twitter登録

  1. サインアップして、
  2. サインインする。
  3. Twitterの開発者サイトに移動し、
  4. My Appsのリンクをクリックする。
  5. そして、Create New Appボタンを押下する。
  6. [Create an application]画面で以下のように入力して、
    Twitter1
  7. [Create youre Twitter application]ボタンを押下する。
  8. アプリケーション登録後、登録したアプリケーションの画面に遷移するので、
  9. そこで、[Keys and Access Tokens Permissions]タブを押下する。
  10. 表示される[Consumer Key (API Key)], [Consumer Secret (API Secret)]をメモ。
    Twitter2
  11. 次に、当該画面の下部にある[Create my access token]ボタンを押下、
    [Access Token], [Access Token Secret]を入手してコレをメモする。
    Twitter3
  12. この4つのキー[Consumer Key], [Consumer Secret], [Access Token], [Access Token Secret]を使用してTweetを行う。

MainPage?.xaml.cs

  • はじめに以下を行う、
    • CoreTweet?をNugetから入手。
    • CoreTweet?をusingに追加する。
    • そして、UWPからTweet可能にするようにネットワーク・アクセスを許可する。
      • Windows10でVPN接続するとストアアプリが外に出られなくなる - tmytのらくがき
        http://blog.tmyt.jp/entry/2015/11/23/154702
      • 以下が、その設定画面(Package.appxmanifestを選択、機能タブに遷移)。
        ここでは、以下の2つのチェック・ボックスにチェックを入れ、機能をオンにしてみた。
        Twitter4
  • Tweet用のTimerとCallbackを追加する。
    • Timerと言っても色々あるので以下を参考に、DispatcherTimer?を選択。
      Tweet元の情報をUWPのUI場の情報から取得する必要があったので。
  • 以下、前述のコードからの差分。
    using System.Threading;
    using System.Diagnostics;
    using CoreTweet;
    ・・・
            /// <summary>ライブラリ</summary>
            private BME280 bme280;
            /// <summary>SensorのTimer</summary>
            private Timer periodicTimer;
            /// <summary>TwitterのTimer</summary>
            private DispatcherTimer twitterTimer;
            /// <summary>TwitterのToken</summary>
            private Tokens tokens;
    
            public MainPage()
            {
                this.InitializeComponent();
                this.Loaded += MainPage_Loaded;
            }
    
            /// <summary>Loaded</summary>
            /// <param name="sender">object</param>
            /// <param name="e">RoutedEventArgs</param>
            private void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                this.bme280 = new BME280();
                this.initBme280();
                this.initTwitter();
            }
    
            /// <summary>Twitterの初期化</summary>
            private void initTwitter()
            {
                // 実際の値を入力する。その際、{}は削除する。
                this.tokens = Tokens.Create(
                    "{API key}"
                    , "{API secret}"
                    , "{Access token}"
                    , "{Access token secret}");
    
                this.twitterTimer = new DispatcherTimer();
                this.twitterTimer.Interval = TimeSpan.FromSeconds(10); // Tweet間隔を調整
                this.twitterTimer.Tick += this.TimerCallback;
                this.twitterTimer.Start();
            }
    
            /// <summary>Bme280の初期化</summary>
            private async void initBme280()
            {
                await this.bme280.Initialize();
                this.periodicTimer = new Timer(this.TimerCallback, null, 0, 1000);
            }
    
            /// <summary>TwitterのTimerCallback</summary>
            /// <param name="state">object</param>
            private void TimerCallback(object sender, object e)
            {
                string text =
                    this.tbkTMP.Text +"\r\n"
                    + this.tbkHUM.Text + "\r\n"
                    + this.tbkPRE.Text;
    
                Debug.WriteLine("Tweet :" + text);
    
                this.tweet(text);
            }
    
            /// <summary>tweetする</summary>
            /// <param name="text">tweetのテキスト</param>
            private async void tweet(string text)
            {
                Status _status = await this.tokens.Statuses.UpdateAsync(status => text);
            }
    
            /// <summary>Bme280のTimerCallback</summary>
            /// <param name="state">object</param>
            private void TimerCallback(object state)
    ・・・

結果

SensorTweet

Wio Nodeを使用する。

Wio NodeのデバイスのデータをRESTで取得する。

Wio NodeのデバイスをRESTで操作する。

監視カメラを実装する。

  • カメラ・デバイスは、USBのInboxドライバ経由で操作する。
  • カメラ・デバイスの操作には、Windows.​Media.​Capture名前空間のAPIを使用する。
  • 顔の検出には、Windows.​Media.​Face​Analysis.Face​Detector名前空間のAPIを使用する。

OpenCVを利用する。

OpenCvSharp?が、.NET Core / Monoに対応しているようなので、
OpenCvSharp? + Windows10 IoT Coreができたら良さそ気。

参考

電子工作

ASCII.jp

Build Insider

Qiita

Microsoft

ms-iot/samples: Windows 10 IoT Core Samples

https://github.com/ms-iot/samples

Windows 10 IoTCore ハンズオントレーニング

電子工作(MAKE)


Tags: :インフラストラクチャ, :Windows, :IoT


添付ファイル: file1.png 169件 [詳細] fileSensorTweet.jpg 221件 [詳細] fileSensorData.jpg 244件 [詳細] fileTwitter4.png 232件 [詳細] fileTwitter3.png 220件 [詳細] fileTwitter2.png 229件 [詳細] fileTwitter1.png 216件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-08-23 (金) 09:58:52 (59d)