.NET Gadgeteer の無線 LAN 接続と時刻同期 (NETMF 4.3 版)

.NET Micro Framework 4.3 対応の .NET Gadgeteer で、無線 LAN 接続をする方法および NTP サーバーを利用した時刻同期の方法を紹介します。

この記事の内容は NETMF 4.2 で一度書いていますが、4.3 で API が大きく変わり、コードの互換性がなくなりました。(そんな・・・)
そこで改めて書いてみます。なお使用したのは10月末にリリースされた NETMF and Gadgeteer Package 2014 R5 です。

動作の確認のために LCD を接続してデジタル時計を作りましたが、時計表示は今回の投稿ではオマケです。

WP_20140915_010

メインボードと接続するモジュールは以下の通り。

2014-11-16 21-24-34

 


無線 LAN 接続の方法

Spider と RS21 Module を利用すると無線 LAN 接続は簡単です。

RS21 をオープンして DHCP を有効にして、Join メソッドを呼ぶだけです。

NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;

if (!wifiRS21.NetworkInterface.Opened)
    wifiRS21.NetworkInterface.Open();
if (!wifiRS21.NetworkInterface.IsDhcpEnabled)
    wifiRS21.NetworkInterface.EnableDhcp();

wifiRS21.NetworkInterface.Join(Ssid, WifiKey);

Join に成功して IP アドレスを取得できると NetworkAddressChanged イベントが発行されます。
今回はこのあと NTP サーバーに接続して時刻を取得しますが、無線 LAN に接続するのは上記のコードで OK です。定石となるコードですのでこのまま利用していいと思います。

他のメインボードの場合は RS21 モジュールが使えませんが、 XBee + Wifi モジュールで無線 LAN 接続を実現できるようです。(私がモジュールを持っていないので確認できていません。)

 


時刻同期の方法

時刻同期も定型的な記述です。

TimeService.SystemTimeChanged += TimeService_SystemTimeChanged;
TimeService.TimeSyncFailed += TimeService_TimeSyncFailed;

var ntpAddresses = Dns.GetHostEntry(NtpServer).AddressList;
if (ntpAddresses == null || ntpAddresses.Length == 0)
    return;

Thread.Sleep(1000);

var settings = new TimeServiceSettings
{
    PrimaryServer = ntpAddresses[0].GetAddressBytes()
};

TimeService.Settings = settings;
TimeService.SetTimeZoneOffset(540);
TimeService.Start();
  1. DNS クラスの GetHostEntry メソッド、さらに AddressList プロパティで NTP サーバーの IP アドレスを取得
  2. TimeService の PrimaryServer プロパティに NTP サーバーの IP アドレスを設定。ただし PrimaryServer は byte 配列型なので GetAddressBytes メソッドが必要
  3. SetTimeZoneOffset メソッドでタイムゾーンの指定 (540 = 9時間 * 60分)
  4. TimeService の Start メソッド呼び出し
  5. 時刻同期に成功すると SystemTimeChanged イベントハンドラーが呼び出される

NTP サーバーはネットワーク的に近いところを指定するのがよいようです。例えば “time.windows.com” を指定するとかなりの確率でエラーになります。タイムアウトしてしまうようです。私が試したところでは “ntp.nict.jp” はほぼ確実に時刻が取得できます。

NETMF 4.2 の時代には 時刻同期で使用する TimeService クラスが Premium ライブラリーにしか含まれていなかったのですが、 NETMF 4.3 では Microsoft.SPOT.Time.TimeService が利用できます。
Spider 以外のメインボードなどでも利用できるか、動作するかは改めて検証したいと思います。

 


デジタル時計の全ソースコードは以下の通り。 WiFi 接続できて時刻が同期できれば、実はあとはネットワークは不要です。

using System;
using System.Net;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Net.NetworkInformation;
using Microsoft.SPOT.Time;
using GT = Gadgeteer;

namespace GadgeteerWatch43
{
  public partial class Program
  {
    private const string Ssid = "<ここにSSID>";
    private const string WifiKey = "<ここにKey>";
    private const string NtpServer = "ntp.nict.jp";

    // This method is run when the mainboard is powered up or reset.
    void ProgramStarted()
    {
      characterDisplay.BacklightEnabled = true;
      PrintMessage("Initializing ...");

      var startSystemTimer = new GT.Timer(3000, GT.Timer.BehaviorType.RunOnce);
      startSystemTimer.Tick += startSystemTimer_Tick;
      startSystemTimer.Start();

      // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
      Debug.Print("Program Started");
    }

    void clockTimer_Tick(GT.Timer timer)
    {
      var curDt = DateTime.Now;
      var curTime = curDt.ToString(" HH:mm:ss ");
      var curDate = curDt.ToString("yyyy/MM/dd (ddd)");

      PrintMessageToLine(curTime, 0, false);
      PrintMessageToLine(curDate, 1, false);
    }

    void startSystemTimer_Tick(GT.Timer timer)
    {
      NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;

      if (!wifiRS21.NetworkInterface.Opened)
        wifiRS21.NetworkInterface.Open();
      if (!wifiRS21.NetworkInterface.IsDhcpEnabled)
        wifiRS21.NetworkInterface.EnableDhcp();

      wifiRS21.NetworkInterface.Join(Ssid, WifiKey);
    }

    void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
    {
      if (wifiRS21.NetworkInterface.IPAddress == "0.0.0.0" ||
        wifiRS21.NetworkInterface.IPAddress == string.Empty)
      {
        PrintMessage("Can't join to NW");
      }
      else
      {
        PrintMessageToLine("Joined to NW", 0, true);
        PrintMessageToLine(wifiRS21.NetworkInterface.IPAddress, 1, false);

        SetupLocalTime();
      }
    }

    void SetupLocalTime()
    {
      TimeService.SystemTimeChanged += TimeService_SystemTimeChanged;
      TimeService.TimeSyncFailed += TimeService_TimeSyncFailed;

      var ntpAddresses = Dns.GetHostEntry(NtpServer).AddressList;
      if (ntpAddresses == null || ntpAddresses.Length == 0)
        return;

      Thread.Sleep(1000);
      PrintMessage("Sync Clock Start");

      var settings = new TimeServiceSettings
      {
        PrimaryServer = ntpAddresses[0].GetAddressBytes()
      };

      TimeService.Settings = settings;
      TimeService.SetTimeZoneOffset(540);
      TimeService.Start();
    }

    void TimeService_SystemTimeChanged(object sender, SystemTimeChangedEventArgs e)
    {
      TimeService.Stop();

      var clockTimer = new GT.Timer(1000);
      clockTimer.Tick += clockTimer_Tick;
      clockTimer.Start();
    }

    void TimeService_TimeSyncFailed(object sender, TimeSyncFailedEventArgs e)
    {
      TimeService.Stop();
    }

    private void PrintMessage(string msg)
    {
      PrintMessageToLine(msg, 0, true);
    }

    private void PrintMessageToLine(string msg, int row, bool clearDisplay)
    {
      if (clearDisplay)
        characterDisplay.Clear();
      else
        characterDisplay.SetCursorPosition(row, 0);

      characterDisplay.Print(msg);
    }
  }
}
広告
カテゴリー: .NET Micro Framework, IoT タグ: , , パーマリンク

.NET Gadgeteer の無線 LAN 接続と時刻同期 (NETMF 4.3 版) への2件のフィードバック

  1. ピンバック: .NET Gadgeteer の無線 LAN 接続と時刻同期 | 技術との戯れ

  2. simosimo72 より:

    時刻同期の方法を探していて拝見しました。ありがとうございます。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中