自作IoTデバイスをつくろう--.NET Micro Frameworkと.NET Gadgeterを使いこなす技術者ルポ

builder by ZDNet Japan Ad Special
2014-03-05 11:00:00
  • このエントリーをはてなブックマークに追加

いよいよ完成

 最後に、加速度センサでの振動検知とメールを送る機能を組み合わせて完成だ。

Program.cs

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;
using Gadgeteer.Modules.Seeed;

// 参照に「System」を追加する 
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ZiddyWashing
{
        public partial class Program 
        {
                private static int START_THRESHOLD = 30; // 1分間に30秒以上の揺れになったら起動 
                private static int END_THRESHOLD = 10; // 1分間に10秒以下の揺れになったら停止 

                private Accelerometer.Acceleration _prev_acc;
                private bool[] _count = new bool[60];
                private bool _is_washing = false;   // 洗濯中か 

                 // This method is run whenthe mainboard is powered up or reset.   
                void ProgramStarted()
                {
                        // Use Debug.Print to showmessages in Visual Studio's "Output" window during debugging. 
                        Debug.Print("Program Started");

                        // ネットワーク初期化 
                        InitNetwork();

                        // Ziddyちゃんを描画 
                        DrawZiddy();

                        // メッセージ表示 
                        Msg("Hello, I'm Ziddy!\nIhave to do the laundry... ");

                        accelerometer.MeasurementComplete+= accelerometer_MeasurementComplete;

                         // 1秒に1回イベント呼び出し 
                        accelerometer.ContinuousMeasurementInterval= new TimeSpan(0, 0, 1);

                        // 計測開始 
                        accelerometer.StartContinuousMeasurements();
                }
                void accelerometer_MeasurementComplete(Accelerometer sender, Accelerometer.Acceleration acceleration)
                {
                double th = 0.2; // 閾値。環境によって変えること 

                 Array.Copy(_count, 1, _count, 0,_count.Length - 1);
                        if (_prev_acc == null)
                        {
                                _prev_acc = acceleration;
                        }

                bool result = false;
                if ((System.Math.Abs(_prev_acc.X -acceleration.X) > th)
                        || (System.Math.Abs(_prev_acc.Y -acceleration.Y) > th)
                        || (System.Math.Abs(_prev_acc.Z -acceleration.Z) > th)
                        )
                {
                        result = true;
                }
                _count[_count.Length - 1] = result;

                _prev_acc = acceleration;

                int count = 0;
                bool is_finished = false;
                for (int i = 0; i < _count.Length;i++)
                {
                count += (_count[i] ? 1 : 0);
                }

                string msg = "";
                if (_is_washing == false && count >=START_THRESHOLD)
                {
                _is_washing = true;
                msg = "Start Washing.";
                }
                else if (_is_washing == true && count <=END_THRESHOLD)
                {
                        _is_washing = false;
                        msg = "Finished! Sending aMail... ";
                        is_finished = true;
                }
                else if (_is_washing)
                {
                        msg = "WASHING NOW.";
                }
                else
                {
                        msg = "Waiting.";
                }

                Msg(msg + "\n" + count.ToString() + " " + (count == 1 ? "shake" : "shakes"));
                 if (is_finished)
                {
                        SendMail();
                }
        }

 // Ziddyちゃんを描画 
void DrawZiddy()
{
        const int x = 35;
        const int y = 138;

         // 耳 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x - 25, y - 25, 10,10);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x + 28, y - 20, 10,10);

         // 輪郭 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x, y, 30, 27);

         // 口 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x - 6, y + 4, 5, 3);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x + 5, y + 5, 5, 4);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.Black, x - 7, y + 3, 5, 3);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.Black, x + 6, y + 3, 5, 4);

        // 鼻 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x, y, 2, 2);

        // 目 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x - 10, y - 8, 1, 1);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, x + 11, y - 7, 1, 1);

        // リボン 
        display_N18.SimpleGraphics.DisplayText("ZD",
        Resources.GetFont(Resources.FontResources.NinaB),
        GT.Color.Red, x - 29, y - 27);

        // 吹き出し 
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, 85, 140, 5, 5);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, 100, 120, 7, 7);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, 90, 90, 10, 10);
        display_N18.SimpleGraphics.DisplayEllipse(GT.Color.White, 70, 0, 130, 70);
}

// メッセージ表示 
private void Msg(string msg)
{
        Debug.Print(msg);
        display_N18.SimpleGraphics.DisplayRectangle(GT.Color.Black, 0, GT.Color.Black, 0, 0, 128, 50);
        display_N18.SimpleGraphics.DisplayTextInRectangle(msg, 0, 0, 128, 50,GT.Color.White, Resources.GetFont(Resources.FontResources.NinaB), GTM.Module.DisplayModule.SimpleGraphicsInterface.TextAlign.Left, GTM.Module.DisplayModule.SimpleGraphicsInterface.WordWrap.Wrap, GTM.Module.DisplayModule.SimpleGraphicsInterface.Trimming.WordEllipsis, GTM.Module.DisplayModule.SimpleGraphicsInterface.ScaleText.None);
}

        // ネットワーク初期化 
        private void InitNetwork()
        {
                DebugInfo("InitializingNetwork");
                Microsoft.SPOT.Net.NetworkInformation.NetworkInterface netif
                =Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0];

        /* Static IPを使うときはこちらのコードを使う */ 
        /* 
        netif.EnableStaticIP( 
        "192.168.1.100",  // IPアドレス 
        "255.255.255.0",  // サブネットマスク 
        "192.168.1.1"     // デフォルトゲートウェイ 
        ); 
        netif.EnableStaticDns(new[] {"192.168.1.1" }); // DNS 
        */ 

        /* DHCPからIPを取得 */ 

        // DHCPがオフになっていればオンにする 
        if (netif.IsDhcpEnabled == false)
        {
                netif.EnableDhcp();
        }

        // DHCPからIPを取得(最大30秒待つ) 
        for (int i = 0; i < 30; i++)
        {
                DebugInfo("Waiting DHCP .." + (i +1).ToString());
                netif =Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0];
                if (netif.IPAddress != "0.0.0.0")
                {
                break;
                }
                Thread.Sleep(1000);
        }
if (netif.IPAddress == "0.0.0.0")
{
        // DHCPからIPを取得失敗 
        throw new SystemException();
}

DebugInfo(
                "Networkready.\n" 
                + "IP Address is " + netif.IPAddress,
                1500
        );
}

private void SendMail()
{
        const string server = "smtp.sendgrid.net";           // SMTPサーバーのホスト 
        const int port = 2525;                          // SMTPサーバーのポート 
        const string username = "this_account_is_temporary";   // SMTPサーバーのユーザー名を設定する 
        const string password = "this_password_is_temporary"// SMTPサーバーのパスワードを設定する 
        const string mail_from = "example@example.com";
        const string mail_to = "example@example.com";

        try
        {
                using (Socket socket = SmtpConnect(server,port))
                {
                SmtpReadLine(socket);
                SmtpSendCommand(socket, "EHLO Ziddy");
                SmtpSendCommand(socket, "AUTH LOGIN");
                SmtpSendCommand(socket, Convert.ToBase64String(Encoding.UTF8.GetBytes(username)));
                SmtpSendCommand(socket, Convert.ToBase64String(Encoding.UTF8.GetBytes(password)));
                SmtpSendCommand(socket, "MAIL FROM: <" + mail_from + ">");
                SmtpSendCommand(socket, "RCPT TO: <" + mail_to + ">");

                 string msg = "From: " + mail_from + "\r\n" 
                        + "To: " + mail_to + "\r\n" 
                        + "Subject: Hello from your washing machine\r\n" 
                        + "\r\n" 
                        + "Finished thelaundry!\r\n" 
                        + ".";

                SmtpSendCommand(socket, "DATA");
                SmtpSendCommand(socket,msg);
                SmtpSendCommand(socket, "QUIT");
        }
}
catch (Exception ex)
{
        DebugInfo("err : " + ex.Message);
}
finally 
{
}
}

// SMTPサーバーに接続 
private Socket SmtpConnect(string server, int port)
{
        try 
        {
                DebugInfo("Connecting SMTPserver");
                IPHostEntry hostEntry = Dns.GetHostEntry(server);

                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Connect(new IPEndPoint(hostEntry.AddressList[0],port));

                DebugInfo("Connected SMTPserver");

                return socket;
}
        catch (Exception ex)
        {
        DebugInfo("err : " + ex.Message);
        }
        finally 
        {
        }
        return null;
}

// SMTPサーバーからデータ受信 
private string SmtpReadLine(Socket socket)
{
        Byte[] buffer = new Byte[1024];

        string result = "";
        while (socket.Poll(30 * 1000000, SelectMode.SelectRead))
        {
                Array.Clear(buffer, 0,buffer.Length);
                Int32 bytesRead =socket.Receive(buffer);
                if (bytesRead == 0) break;
                string rec = new string(UTF8Encoding.UTF8.GetChars(buffer));
result = result + rec;


                if (result.LastIndexOf("\r\n") > 0)
                {
                        DebugInfo(result, 1500);
                        return result;
                }
                }
                return "";
        }

 // SMTPサーバーにコマンド送信 
private string SmtpSendCommand(Socket socket, string command)
{
        string request = command + "\r\n";
        DebugInfo(request, 1500);

        Byte[] bytesToSend = Encoding.UTF8.GetBytes(request);
        socket.Send(bytesToSend,bytesToSend.Length, 0);
        Byte[] buffer = new Byte[1024];

        string result =SmtpReadLine(socket);
        DebugInfo(result, 1500);

        return result;
}

// デバッグメッセージ 
private void DebugInfo(string msg, int sleep = 0)
{
        Debug.Print(msg);
        /* 
        display_N18.SimpleGraphics.Clear(); 
        display_N18.SimpleGraphics.DisplayTextInRectangle(msg, 0, 0, 128, 50,GT.Color.White, Resources.GetFont(Resources.FontResources.NinaB),GTM.Module.DisplayModule.SimpleGraphicsInterface.TextAlign.Left,GTM.Module.DisplayModule.SimpleGraphicsInterface.WordWrap.Wrap,GTM.Module.DisplayModule.SimpleGraphicsInterface.Trimming.WordEllipsis,GTM.Module.DisplayModule.SimpleGraphicsInterface.ScaleText.None); 
        if (sleep > 0) 
        { 
                Thread.Sleep(sleep); 
        } 
        */ 
        }
    }
}

実際に洗濯機で試してみた

洗濯が終了すると、指定したアドレスへメールを送信してくれる

アイデア次第で広がる自前IoT

 このように1万円程度のキットでも、ネットワーク機能を含め、色々なことができる。他にもGHI Electrics社からは次のようなモジュールなどが発売されている。

 これらのモジュールとVisual Studioを活用すれば、使い慣れたC#やVisual Basic.NETを使って、手軽に組み込みシステムやIoTの世界にチャレンジすることができる。Windows Azureなどのクラウド環境と組み合わせて、センサクラウド的なガジェットを作ってみても面白いだろう。

 是非、.NET Micro Frameworkと.NET Gadgeteerで、あなたのアイデアを試して欲しい。

※記事中の価格は、記事掲載時の価格です。

  • コメント(1件)
#1 ZDちゃんファン   2014-07-07 22:05:05
Ziddyちゃんは楕円描画でできてるとは!
このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]