Project tutorial
Remote Facility Command and Sensing System

Remote Facility Command and Sensing System © MIT

Legacy facilities lack of remote access possible by Internet. This proof of concept presents a typical remote command and sensing system.

  • 302 views
  • 0 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

This is a project created during a post-graduate class of Embedded Systems in ITA during first semester of 2018.

It uses Netduino Plus 2 with multiple sensors and services (Webserver, SNTP, SMTP) to provide connectivity for a typical industrial facility.

Implement a remote command and monitoring system over the internet exercising concepts such as: GPIO Management, Interruption, Threads, Pulse Width Modulation, Serial Communication, Webserver, SNTP, SMTP, SD Card.

System is comprised of:

  • Stepper Motor
  • 4 LEDs
  • Buzzer
  • 2 DC Motors
  • Slide Switch
  • Serial Communication (Terminal emulated on Laptop)

The following functional requirements are accomplished:

Also a HTML page is available to support monitoring and control of the system remotely:

The project starts by Program.cs as follows:

using System;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using NeonMika.Webserver;
using NeonMika.Webserver.Responses;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Toolbox.NETMF;
using Toolbox.NETMF.NET;
namespace NeonMikaWebserverExecuteable
{
   public class Program
   {
       static int TimeZone_Offset = -3;                // Brazil Timezone
       static string SNTP_Server = "pool.ntp.org";     // SNTP Server
       static FileStream config;
       static string s_ip, s_porta, s_email, s_ntp;
       //MOST OF THE FOLLOWING INFORMATION ARE RETRIEVED FROM config.txt
       public static string Receiver_email = "";           //DEFINE RECEIVER E-MAIL
       public static string Receiver_name = "";            //DEFINE RECEIVER NAME
       public static string Sender_email = "";             //DEFINE SENDER E-MAIL
       public static string Sender_name = "";              //DEFINE SENDER NAME
       public static string SMTP_Server = "";              //DEFINE SMTP SERVER
       public static void Main()
       {
           // Thread for SNTP Client
           Thread thread1 = new Thread(Cliente_SNTP);
           thread1.Start();
           try
           {
               //OPEN config.txt FROM SD CARD
               config = new FileStream(@"\SD\config.txt", FileMode.Open);
               StreamReader reader = new StreamReader(config);
               String message = reader.ReadToEnd();
               //USES REGEX TO RETRIEVE WEBSERVER_IP, WEBSERVER_PORT, RECEIVER_EMAIL, SNTP_SERVER
               Match ip = Regex.Match(message, "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
               Match porta = Regex.Match(message, "=\\s([0-9]{2,4})\\r");
               Match email = Regex.Match(message, "=\\s(\\w+@\\w+\\.\\w{3}.*)");
               Match ntp = Regex.Match(message, "=\\s(\\w+\\.\\w+\\.\\w+)$");
               s_ip = ip.Groups[1].Value.ToString();
               s_porta = porta.Groups[1].Value.ToString();
               s_email = email.Groups[1].Value.ToString();
               s_ntp = ntp.Groups[1].Value.ToString();
               SNTP_Server = s_ntp;
               Receiver_email = s_email;
               
               // OUTPUTS READ INFORMATION
               Debug.Print("****** config.txt ******");
               Debug.Print(">> IP: " + s_ip);
               Debug.Print(">> PORTA: "+ s_porta);
               Debug.Print(">> EMAIL: "+ s_email);
               Debug.Print(">> NTP: "+ s_ntp);
               Debug.Print("************************");
               Thread.Sleep(1000);
               reader.Close();
           }
           catch
           {
               Debug.Print("Error to open config.txt");
           }
           // if not available on SD Card, creates an "alarm" file to record all buzzer events
           if (!File.Exists(@"SD\alarmes.log"))
           {
               File.Create(@"SD\alarmes.log");
               Thread.Sleep(10000);
           }
           
           // WEBSERVER START
           Server WebServer = new Server(PinManagement.OnboardLED, Int32.Parse(s_porta), false, s_ip, "255.255.255.0", "192.168.0.1", "NETDUINO_PLUS_2");
           WebServer.AddResponse(new XMLResponse("wave", new XMLResponseMethod(WebserverXMLMethods.Wave)));
       }
       static void Cliente_SNTP()
       {
           string DateStr;
           DateStr = "Initial Netduino P2 date & time: " + DateTime.Now;
           Debug.Print(DateStr);
           while (true)
           {
               try
               {
                   Serial_Port.Serial("Tentando configurar relogio (SNTP) ...");
                   Debug.Print("Tentando configurar relogio (SNTP) ... " + DateTime.Now.ToString());
                   // Initializes the time client and displays UTC date & time
                   SNTP_Client TimeClient = new SNTP_Client(new IntegratedSocket(SNTP_Server, 123));
                   DateStr = "UTC date & time: " + TimeClient.UTCDate.ToString();
                   Debug.Print(DateStr);
                   //Synchronizes the internal clock using the local date & time and the TimeZone Offset
                   Utility.SetLocalTime(TimeClient.UTCDate.AddHours(TimeZone_Offset));
                   Serial_Port.Serial("Configurado com sucesso (SNTP) - " + DateTime.Now.ToString());
                   Debug.Print("Configurado com sucesso (SNTP) - " + DateTime.Now.ToString());
               }
               catch
               {
                   Serial_Port.Serial("Erro ao configurar SNTP - " + DateTime.Now.ToString());
                   Debug.Print("Erro ao configurar SNTP");
               }
               // R
               Thread.Sleep(15 * 60 * 1000);
           }
       }
   }
} 

Other important source code of the projects and attached to the project are:

- PinManagement.cs - GPIO management

- XMLResponse.cs - Update HTML output page

- Server.cs - Server configuration and GET method handling

- Serial_Port.cs - Start of serial communication

This project can be up and running by deploying NeonMika webserver and replacing the attached files.

* For reference, it is attached "SD_Content.zip"

Code

Program.csC#
Main Program (Visual Studio Project)
** Refer to commented version on Story Page **
using System;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using NeonMika.Webserver;
using NeonMika.Webserver.Responses;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Toolbox.NETMF;
using Toolbox.NETMF.NET;


namespace NeonMikaWebserverExecuteable
{
    public class Program
    {

        static int TimeZone_Offset = -3;
        static string SNTP_Server = "pool.ntp.org";
        static FileStream config;
        static string s_ip, s_porta, s_email, s_ntp;
        public static string Receiver_email = "";
        public static string Receiver_name = "";
        public static string Sender_email = "";
        public static string Sender_name = "";
        public static string SMTP_Server = "";

        public static void Main()
        {
            

            // Criao da thread para o Cliente SNTP
            Thread thread1 = new Thread(Cliente_SNTP);
           

            try
            {
                config = new FileStream(@"\SD\config.txt", FileMode.Open);
                StreamReader reader = new StreamReader(config);
                String message = reader.ReadToEnd();
                Match ip = Regex.Match(message, "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
                Match porta = Regex.Match(message, "=\\s([0-9]{2,4})\\r");
                Match email = Regex.Match(message, "=\\s(\\w+@\\w+\\.\\w{3}.*)");
                Match ntp = Regex.Match(message, "=\\s(\\w+\\.\\w+\\.\\w+)$");
                s_ip = ip.Groups[1].Value.ToString();
                s_porta = porta.Groups[1].Value.ToString();
                s_email = email.Groups[1].Value.ToString();
                s_ntp = ntp.Groups[1].Value.ToString();
                SNTP_Server = s_ntp;
                Receiver_email = s_email;
                Debug.Print("****** config.txt ******");
                Debug.Print(">> IP: " + s_ip);
                Debug.Print(">> PORTA: "+ s_porta);
                Debug.Print(">> EMAIL: "+ s_email);
                Debug.Print(">> NTP: "+ s_ntp);
                Debug.Print("************************");
                Thread.Sleep(1000);
                reader.Close();
            }
            catch
            {
                Debug.Print("Erro ao abrir config.txt");
            }

            thread1.Start();
            
            if (!File.Exists(@"SD\alarmes.log"))
            {
                File.Create(@"SD\alarmes.log");
                Thread.Sleep(10000);
            }

            

            Server WebServer = new Server(PinManagement.OnboardLED, Int32.Parse(s_porta), false, s_ip, "255.255.255.0", "192.168.15.1", "NETDUINO_PLUS_2");
            
            WebServer.AddResponse(new XMLResponse("wave", new XMLResponseMethod(WebserverXMLMethods.Wave)));

        }

        static void Cliente_SNTP()
        {
            string DateStr;

            DateStr = "Initial Netduino P2 date & time: " + DateTime.Now;
            Debug.Print(DateStr);
            
            while (true)
            {
                try
                {
                    Serial_Port.Serial("Tentando configurar relogio (SNTP) ...");
                    Debug.Print("Tentando configurar relogio (SNTP) ... " + DateTime.Now.ToString());
                    // Initializes the time client and displays UTC date & time
                    SNTP_Client TimeClient = new SNTP_Client(new IntegratedSocket(SNTP_Server, 123));
                    DateStr = "UTC date & time: " + TimeClient.UTCDate.ToString();
                    Debug.Print(DateStr);
                    //Synchronizes the internal clock using the local date & time and the TimeZone Offset
                    Utility.SetLocalTime(TimeClient.UTCDate.AddHours(TimeZone_Offset));
                    Serial_Port.Serial("Configurado com sucesso (SNTP) - " + DateTime.Now.ToString());
                    Debug.Print("Configurado com sucesso (SNTP) - " + DateTime.Now.ToString());
                }
                catch
                {
                    Serial_Port.Serial("Erro ao configurar SNTP - " + DateTime.Now.ToString());
                    Debug.Print("Erro ao configurar SNTP");
                }
                // Acessar o servidor SNTP a cada 15 minutos
                Thread.Sleep(15 * 60 * 1000);
            }
        }

    }
}
SD ContentHTML
- Simple HTML Webpage
- config.txt example
- alarmes.log - Alarms Log
No preview (download only).
Serial PortC#
Set up Serial Port communication
using System;
using System.Collections;
using System.Threading;
using NeonMika.Webserver;
using Microsoft.SPOT;
using System.IO.Ports; // Included library to enable the serial port class 
using System.Text; // Included library to convert strings to bytes and vice-versa. 

namespace NeonMika.Webserver
{
    public class Serial_Port
    {
        static byte[] msg1 = Encoding.UTF8.GetBytes(" --> ");
        static byte[] msg2 = Encoding.UTF8.GetBytes("\r\n");
        static SerialPort serial = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);

        public static void Serial(string URL)
        {

            if (serial.IsOpen == false)
            {
                serial.Open();
                Debug.Print("Open serial communication <COM3 - (Pin7-RX) and (Pin8-TX)>\n");
            }
            Thread SerialThread = new Thread(new ThreadStart(() =>
            {
                byte[] command = Encoding.UTF8.GetBytes(URL);



                serial.Write(msg1, 0, msg1.Length);
                serial.Write(command, 0, command.Length);
                serial.Write(msg2, 0, msg2.Length);


            }));
            SerialThread.Start();
        }
    }
}
ServerC#
This is the modified NeonMika Webserver file responsible to manage all GET request to Netduino from Webpage
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using FastloadMedia.NETMF.Http;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net.NetworkInformation;
using NeonMika.Webserver.Responses;
using NeonMika.XML;
using NeonMika.Util;
using NeonMika.Webserver.Responses.ComplexResponses;
using NeonMika.Webserver.POST;
using System.IO;






namespace NeonMika.Webserver
{
    /// <summary>
    /// XML Expansion methods have to be in this form
    /// </summary>
    /// <param name="e">Access to GET or POST arguments,...</param>
    /// <param name="results">This hashtable gets converted into xml on response</param>       
    public delegate void XMLResponseMethod(Request e, Hashtable results);


    /// <summary>
    /// JSON Expansion methods have to be in this form
    /// </summary>
    /// <param name="e">Access to GET or POST arguments,...</param>
    /// <param name="results">This JsonArray gets converted into JSON on response</param>
    /// <returns>True if URL refers to this method, otherwise false (false = SendRequest should not be executed) </returns>        
    public delegate void JSONResponseMethod(Request e, JsonArray results);

    /// <summary>
    /// Main class of NeonMika.Webserver
    /// </summary>
    public class Server
    {
        public int Port { get; private set; }

        private Socket listeningSocket = null;
        private Hashtable responses = new Hashtable();
        private OutputPort led;

        public static string funcao;

        public static bool ok = true;
        public static bool okpwm;

        public static bool sentido;//sentido de rotação do motor

        public static bool sentido2;//sentido de rotação do motor

        public static bool state;
        public static bool state2;


        //Monitora a chave 
        private void chave()
        {


            //chama a função apenas para iniciar a interupção do botão
            PinManagement.Main();



            while (true)
            {


                //caso a chave esteja ativa
                if (!PinManagement.Digital2.Read() && ok)
                {
                    ok = false;

                    //muda a imagem no arquivo XMLResponse
                    XMLResponse.chave = "chave_on.gif";

                    Serial_Port.Serial("Alateração da chave - Estado: Ligada - " + DateTime.Now);

                }



                else if (PinManagement.Digital2.Read())
                {




                    ok = true;

                    //muda a imagem no arquivo XMLResponse
                    XMLResponse.chave = "chave_off.gif";


                }


            }



        }



        //aciona o Buzzer

        private void buzzer()
        {


            while (true)
            {

                if (okpwm)
                {
                    //aciona o buzzer por 10s
                    XMLResponse.buzzer = "buzzer_on.gif";
                    Thread.Sleep(10000);

                    //desliga o buzzer
                    PinManagement.SetPWM(9, 0, 0);

                    XMLResponse.buzzer = "buzzer_off.gif";

                    if (okpwm)
                        okpwm = false;

                }

            }




        }














        /// <summary>
        /// Creates an NeonMika.Webserver instance running in a seperate thread
        /// </summary>
        /// <param name="portNumber">The port to listen for incoming requests</param>
        public Server(OutputPort ledPort, int port = 80, bool DhcpEnable = true, string ipAddress = "", string subnetMask = "", string gatewayAddress = "", string networkName = "NETDUINOPLUS")
        {
            Debug.Print("\n\n---------------------------");
            Debug.Print("THANKS FOR USING NeonMika.Webserver");
            Debug.Print("Version: " + Settings.SERVER_VERSION);
            Debug.Print("---------------------------");

            this.Port = port;
            //wifi
            //NetworkSetup(DhcpEnable, ipAddress, subnetMask, gatewayAddress, networkName);
            StartLedThread(ledPort);
            ResponseListInitialize();
            SocketSetup();

            var webserverThread = new Thread(WaitingForRequest);
            webserverThread.Start();

            var webserverThread2 = new Thread(chave);
            webserverThread2.Start();

            var webserverThread3 = new Thread(buzzer);
            webserverThread3.Start();


            Debug.Print("\n\n---------------------------");
            Debug.Print("Webserver is now up and running");


            System.DateTime dt = new System.DateTime(2018, 7, 4, 21, 41, 0);
            Microsoft.SPOT.Hardware.Utility.SetLocalTime(dt);
            Serial_Port.Serial("Webserver Iniciado! - " + DateTime.Now);




        }




        /// <summary>
        /// Creates the socket that will listen for incoming requests
        /// </summary>
        private void SocketSetup()
        {
            listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listeningSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
            listeningSocket.Listen(5);
        }








        /// <summary>
        /// Starts a loop that lets the selected led blink all 2 seconds
        /// </summary>
        /// <param name="ledPort"></param>
        private void StartLedThread(OutputPort ledPort)
        {
            led = ledPort;

            Thread t = new Thread(
                new ThreadStart(
                    delegate()
                    {
                        while (true)
                        {
                            ledPort.Write(true);
                            Thread.Sleep(30);
                            ledPort.Write(false);
                            Thread.Sleep(2000);
                        }
                    }
                    ));
            t.Start();
        }

        /// <summary>
        /// Sets the ip adress and the networkname
        /// </summary>
        /// <param name="DhcpEnable">If true, ip will be received from router via DHCP</param>
        /// <param name="ipAddress"></param>
        /// <param name="subnetMask"></param>
        /// <param name="gatewayAddress"></param>
        /// <param name="networkName">Instead of using the ip, this name can be used in the browser to connect to the device</param>
        private void NetworkSetup(bool DhcpEnable, string ipAddress, string subnetMask, string gatewayAddress, string networkName)
        {
            var interf = NetworkInterface.GetAllNetworkInterfaces()[0];

            if (DhcpEnable)
            {
                //Dynamic IP
                interf.EnableDhcp();
                interf.RenewDhcpLease();
            }
            else
            {
                //Static IP
                interf.EnableStaticIP(ipAddress, subnetMask, gatewayAddress);
            }

            NameService nameService = new NameService();
            nameService.AddName(networkName, NameService.NameType.Unique, NameService.MsSuffix.Default);

            Debug.Print("\n\n---------------------------");
            Debug.Print("Network is set up!\nIP: " + interf.IPAddress + " (DHCP: " + interf.IsDhcpEnabled + ")");
            Debug.Print("You can also reach your Netduino with the following network name: " + networkName);
            Debug.Print("---------------------------");
        }

        /// <summary>
        /// Waiting for client to connect.
        /// When bytes were read they get wrapped to a "Reqeust"
        /// </summary>
        private void WaitingForRequest()
        {


            while (true)
            {
                try
                {
                    using (Socket clientSocket = listeningSocket.Accept())
                    {
                        //Wait to get the bytes in the sockets "available buffer"
                        int availableBytes = AwaitAvailableBytes(clientSocket);

                        if (availableBytes > 0)
                        {
                            byte[] buffer = new byte[availableBytes > Settings.MAX_REQUESTSIZE ? Settings.MAX_REQUESTSIZE : availableBytes];
                            byte[] header = FilterHeader(clientSocket, buffer);

                            //reqeust created, checking the response possibilities
                            using (Request tempRequest = new Request(Encoding.UTF8.GetChars(header), clientSocket))
                            {
                                Debug.Print("\n\nClient connected\nURL: " + tempRequest.URL + "\nFinal byte count: " + availableBytes + "\n");

                                if (tempRequest.Method == "POST")
                                {
                                    //POST was incoming, it will be saved to SD card at Settings.POST_TEMP_PATH
                                    // This file can later be handled in a normal response method by using PostFileReader
                                    PostToSdWriter post = new PostToSdWriter(tempRequest);
                                    post.ReceiveAndSaveData();
                                }

                                //Let's check if we have to take some action or if it is a file-response 


                                SendResponse(tempRequest);
                            }

                            try
                            {
                                //Close client, otherwise the browser / client won't work properly
                                clientSocket.Close();
                            }
                            catch (Exception ex)
                            {
                                Debug.Print(ex.ToString());
                            }

                            Debug.Print("Request finished");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.Print(ex.Message);
                }
            }








        }

        /// <summary>
        /// Reads in the data from the socket and seperates the header from the rest of the request.
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <param name="buffer">Will get filled with the incoming data</param>
        /// <returns>The header</returns>
        private byte[] FilterHeader(Socket clientSocket, byte[] buffer)
        {
            byte[] header = new byte[0];
            int readByteCount = clientSocket.Receive(buffer, buffer.Length, SocketFlags.None);

            for (int headerend = 0; headerend < buffer.Length - 3; headerend++)
            {
                if (buffer[headerend] == '\r' && buffer[headerend + 1] == '\n' && buffer[headerend + 2] == '\r' && buffer[headerend + 3] == '\n')
                {
                    header = new byte[headerend + 4];
                    Array.Copy(buffer, 0, header, 0, headerend + 4);
                    break;
                }
            }

            return header;
        }

        /// <summary>
        /// Returns the number of available bytes.
        /// Waits till all bytes from one request are received.
        /// </summary>
        /// <param name="clientSocket"></param>
        /// <returns></returns>
        private int AwaitAvailableBytes(Socket clientSocket)
        {
            int availableBytes = 0;
            int newAvBytes;

            do
            {
                //Wait if bytes come in
                Thread.Sleep(15);
                newAvBytes = clientSocket.Available - availableBytes;

                // breaks the "always true loop" if no new bytes got available
                if (newAvBytes == 0)
                    break;

                availableBytes += newAvBytes;
                newAvBytes = 0;
            } while (true); //repeat as long as new bytes were received

            return availableBytes;
        }

        /// <summary>
        /// Checks what Response has to be executed.
        /// It compares the requested page URL with the URL set for the coded responses 
        /// </summary>
        /// <param name="e"></param>
        private void SendResponse(Request e)
        {
            Response response = null;


            if (responses.Contains(e.URL))
                response = (Response)responses[e.URL];
            else
                response = (Response)responses["FileResponse"];


            if (response != null)
            {
                using (response)
                {
                    if (response.ConditionsCheckAndDataFill(e))
                    {
                        if (!response.SendResponse(e))
                            Debug.Print("Sending response failed");
                    }
                    else
                    {
                        response.Send404_NotFound(e.Client);
                    }
                }
            }
        }

        //-------------------------------------------------------------
        //-------------------------------------------------------------
        //---------------Webserver expansion---------------------------
        //-------------------------------------------------------------
        //-------------------------------------------------------------
        //-------------------Basic methods-----------------------------

        /// <summary>
        /// Adds a Response
        /// </summary>
        /// <param name="response">XMLResponse that has to be added</param>
        public void AddResponse(Response response)
        {
            if (!responses.Contains(response.URL))
            {
                responses.Add(response.URL, response);
            }
        }

        /// <summary>
        /// Removes a Response
        /// </summary>
        /// <param name="ResponseName">XMLResponse that has to be deleted</param>
        public void RemoveResponse(String ResponseName)
        {
            if (responses.Contains(ResponseName))
            {
                responses.Remove(ResponseName);
            }
        }

        //-------------------------------------------------------------
        //-------------------------------------------------------------
        //-----------------------EXPAND this methods-------------------

        /// <summary>
        /// Initialize the basic functionalities of the webserver
        /// </summary>
        private void ResponseListInitialize()
        {
            AddResponse(new IndexResponse(""));
            AddResponse(new FileResponse());
            AddResponse(new XMLResponse("echo", new XMLResponseMethod(Echo)));
            AddResponse(new XMLResponse("switchDigitalPin", new XMLResponseMethod(SwitchDigitalPin)));
            AddResponse(new XMLResponse("setDigitalPin", new XMLResponseMethod(SetDigitalPin)));
            AddResponse(new XMLResponse("xmlResponseList", new XMLResponseMethod(ResponseListXML)));
            AddResponse(new JSONResponse("jsonResponseList", new JSONResponseMethod(ResponseListJSON)));
            AddResponse(new XMLResponse("pwm", new XMLResponseMethod(SetPWM)));
            AddResponse(new XMLResponse("getAnalogPinValue", new XMLResponseMethod(GetAnalogPinValue)));
            AddResponse(new XMLResponse("getDigitalPinState", new XMLResponseMethod(GetDigitalPinState)));
            AddResponse(new XMLResponse("multixml", new XMLResponseMethod(MultipleXML)));
            AddResponse(new XMLResponse("upload", new XMLResponseMethod(Upload)));
            AddResponse(new XMLResponse("getAllDigitalPinStates", new XMLResponseMethod(GetAllDigitalPinStates)));
            AddResponse(new XMLResponse("getAllAnalogPinValues", new XMLResponseMethod(GetAllAnalogPinValues)));
            AddResponse(new XMLResponse("getAllPWMValues", new XMLResponseMethod(GetAllPWMValues)));
            AddResponse(new XMLResponse("getPWM", new XMLResponseMethod(GetPWM)));
            AddResponse(new XMLResponse("setAllDigitalPinStates", new XMLResponseMethod(SetAllDigitalPinStates)));
            AddResponse(new XMLResponse("display", new XMLResponseMethod(Display)));
            AddResponse(new XMLResponse("motores", new XMLResponseMethod(Motores)));
            AddResponse(new XMLResponse("servo", new XMLResponseMethod(ServoPos)));
        }

        //-------------------------------------------------------------
        //---------------------Expansion Methods-----------------------
        //-------------------------------------------------------------
        //----------Look at the echo method for xml example------------

        /// <summary>
        /// Example for webserver expand method
        /// Call via http://servername/echo?value='echovalue'
        /// Submit a 'value' GET parameter
        /// </summary>
        /// <param name="e"></param>
        /// <param name="results"></param>
        /// <returns></returns>
        private void Echo(Request e, Hashtable results)
        {
            if (e.GetArguments.Contains("value") == true)
                results.Add("echo", e.GetArguments["value"]);
            else
                results.Add("ERROR", "No 'value'-parameter transmitted to server");
        }

        /// <summary>
        /// Submit a 'pin' GET parameter to switch an OutputPorts state (on/off)
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        private static void SwitchDigitalPin(Request e, Hashtable h)
        {
            if (e.GetArguments.Contains("pin"))
                try
                {
                    int pin = Int32.Parse(e.GetArguments["pin"].ToString());
                    if (pin >= 0 && pin <= 13)
                    {
                        PinManagement.SwitchDigitalPinState(pin);
                        h.Add("pin" + pin, PinManagement.GetDigitalPinState(pin) ? "1" : "0");
                    }
                }
                catch
                {
                    h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterConvertError);
                }
            else
                h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterMissing);
        }



        public static void ServoPos(Request e, Hashtable h)
        {
            Thread ServoThread = new Thread(new ThreadStart(() =>
            {
                double angulo = 0.0;
                uint duracao;
                if (e.GetArguments.Contains("angulo"))
                {
                    try
                    {

                        angulo = double.Parse(e.GetArguments["angulo"].ToString());
                        XMLResponse.angulo = angulo.ToString();
                    }
                    catch
                    {
                        angulo = 0.0;
                        Debug.Print("Angulo Invalido");
                        XMLResponse.angulo = angulo.ToString();
                    }
                }
                if (angulo > 180)
                {
                    angulo = 180;
                    XMLResponse.angulo = angulo.ToString();
                }
                else if (angulo < 0)
                {
                    angulo = 0;
                    XMLResponse.angulo = angulo.ToString();
                }
                duracao = (uint)(2000 * angulo / 180.0 + 500);
                Debug.Print("Posicionando servo");

                PinManagement.SetPWM(10, 20000, duracao);

                Serial_Port.Serial("Angulo do servo motor alterado - " + angulo.ToString() + " - " + DateTime.Now);
            }));
            ServoThread.Start();
        }




        /// <summary>
        /// Submit a 'pin' (0-13) and a 'state' (true/false) GET parameter to turn on/off OutputPort
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        /// 


        //envia uma mensagem para o display
        private static void Display(Request e, Hashtable h)
        {
            string display = (e.GetArguments["texto"].ToString());

            display = display.Replace('+', ' ');

            XMLResponse.display = display;
            display = "Mensagem recebida: " + display + "-" + DateTime.Now;

            Serial_Port.Serial(display);



        }



        private static void Motores(Request e, Hashtable h)
        {

            int pin = Int32.Parse(e.GetArguments["pin"].ToString());//pino do motor
            sentido = (e.GetArguments["dir"].ToString() == "true") ? true : false;
            state = (e.GetArguments["state"].ToString() == "true") ? true : false;


            if (pin == 0)//motor 1
            {


                PinManagement.Digital0.Write(state);//liga/desliga o motor
                PinManagement.Digital1.Write(sentido);//muda o sentido de rotação

                if (state)
                {
                    if (sentido)
                    {
                        XMLResponse.motor = "motor_h.gif";
                        Serial_Port.Serial("Motor 1 ligado - sentido Horario - " + DateTime.Now);

                    }
                    else
                    {
                        XMLResponse.motor = "motor_ah.gif";
                        Serial_Port.Serial("Motor 1 ligado - sentido Anti-horario - " + DateTime.Now);
                    }
                }

                else
                {
                    Serial_Port.Serial("Motor 1 Desligado - " + DateTime.Now);
                    XMLResponse.motor = "motor_off.gif";
                }

            }


            if (pin == 11)//motor 2
            {


                PinManagement.Digital11.Write(state);//liga/desliga o motor
                PinManagement.Digital12.Write(sentido);//muda o sentido de rotação


                if (state)
                {
                    if (sentido)
                    {
                        XMLResponse.motor2 = "motor_h.gif";
                        Serial_Port.Serial("Motor 2 ligado - sentido Horario - " + DateTime.Now);

                    }
                    else
                    {
                        XMLResponse.motor2 = "motor_ah.gif";
                        Serial_Port.Serial("Motor 2 ligado - sentido Anti-horario - " + DateTime.Now);
                    }
                }

                else
                {
                    Serial_Port.Serial("Motor 2 Desligado - " + DateTime.Now);
                    XMLResponse.motor2 = "motor_off.gif";
                }
            }




        }



        private static void SetDigitalPin(Request e, Hashtable h)
        {




            if (e.GetArguments.Contains("pin"))
                if (e.GetArguments.Contains("state"))
                    try
                    {
                        int pin = Int32.Parse(e.GetArguments["pin"].ToString());
                        if (pin >= 0 && pin <= 13)
                        {
                            try
                            {
                                bool state = (e.GetArguments["state"].ToString() == "true") ? true : false;

                                state = PinManagement.GetDigitalPinState(pin);
                                state = !state;

                                PinManagement.SetDigitalPinState(pin, state);
                                h.Add("pin" + pin, PinManagement.GetDigitalPinState(pin) ? "1" : "0");

                                Serial_Port.Serial("Alteracao no led: " + (pin - 2).ToString() + " - Estado: " + state.ToString() + " - " + DateTime.Now);
                            }
                            catch
                            {
                                h = XMLResponse.GenerateErrorHashtable("state", ResponseErrorType.ParameterRangeException);
                            }
                        }
                        else
                            h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterRangeException);
                    }
                    catch
                    {
                        h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterConvertError);
                    }
                else
                    h = XMLResponse.GenerateErrorHashtable("state", ResponseErrorType.ParameterMissing);
            else
                h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterMissing);



        }

        /// <summary>
        /// Returns the responses added to the webserver
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        private void ResponseListXML(Request e, Hashtable h)
        {


            int i = -1;
            foreach (Object k in responses.Keys)
            {
                i++;
                if (responses[k] as XMLResponse != null)
                {
                    h.Add("methodURL" + i, k.ToString());
                }
            }

        }

        /// <summary>
        /// Returns the responses added to the webserver
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        private void ResponseListJSON(Request e, JsonArray j)
        {
            JsonObject o;
            foreach (Object k in responses.Keys)
            {
                if (responses[k] as JSONResponse != null)
                {
                    o = new JsonObject();
                    o.Add("methodURL", k);
                    o.Add("methodInternalName", ((Response)responses[k]).URL);
                    j.Add(o);
                }
            }
        }

        /// <summary>
        /// Submit a 'pin' (5,6,9,10), a period and a duration (0 for off, period-value for 100% on) GET parameter to control PWM
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        private void SetPWM(Request e, Hashtable h)
        {

            funcao = "PWM";



            int pino = Int32.Parse(e.GetArguments["pin"].ToString());
            uint periodo = UInt32.Parse(e.GetArguments["period"].ToString());

            if (!okpwm)
                PinManagement.SetPWM(9, 0, 0);

            if (pino == 9)
            {
                okpwm = !okpwm;

                if (okpwm)
                {

                    PinManagement.SetPWM(9, 200, 100);
                    XMLResponse.buzzer = "buzzer_on.gif";

                    Serial_Port.Serial("Alteração no buzzer - Estado: ON - " + DateTime.Now);


                }
                else
                {
                    PinManagement.SetPWM(9, 0, 0);
                    XMLResponse.buzzer = "buzzer_off.gif";

                    Serial_Port.Serial("Alteração no buzzer - Estado: OFF - " + DateTime.Now);

                }


            }






            else if (e.GetArguments.Contains("pin"))
            {
                if (e.GetArguments.Contains("period"))
                {
                    if (e.GetArguments.Contains("duration"))
                    {
                        try
                        {
                            int pin = Int32.Parse(e.GetArguments["pin"].ToString());
                            try
                            {
                                uint duration = UInt32.Parse(e.GetArguments["duration"].ToString());
                                try
                                {
                                    uint period = UInt32.Parse(e.GetArguments["period"].ToString());
                                    if (PinManagement.SetPWM(pin, period, duration))
                                        h.Add("success", period + "/" + duration);

                                    else
                                        h = XMLResponse.GenerateErrorHashtable("PWM", ResponseErrorType.InternalValueNotSet);
                                }
                                catch (Exception ex)
                                {
                                    h = XMLResponse.GenerateErrorHashtable("period", ResponseErrorType.ParameterConvertError);
                                    Debug.Print(ex.ToString());
                                }
                            }
                            catch (Exception ex)
                            {
                                h = XMLResponse.GenerateErrorHashtable("duration", ResponseErrorType.ParameterConvertError);
                                Debug.Print(ex.ToString());
                            }
                        }
                        catch (Exception ex)
                        {
                            h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterConvertError);
                            Debug.Print(ex.ToString());
                        }
                    }
                    else
                        h = XMLResponse.GenerateErrorHashtable("duration", ResponseErrorType.ParameterMissing);
                }
                else
                    h = XMLResponse.GenerateErrorHashtable("period", ResponseErrorType.ParameterMissing);
            }
            else
                h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterMissing);
        }

        /// <summary>
        /// Submit a 'pin' (0-13) GET parameter. Returns true or false
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        private void GetDigitalPinState(Request e, Hashtable h)
        {
            funcao = "Led";



            if (e.GetArguments.Contains("pin"))
            {
                try
                {
                    int pin = Int32.Parse(e.GetArguments["pin"].ToString());
                    h.Add("pin" + pin, PinManagement.GetDigitalPinState(pin) ? "1" : "0");
                }
                catch (Exception ex)
                {
                    h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterConvertError);
                    Debug.Print(ex.ToString());
                }
            }
            else
                h = XMLResponse.GenerateErrorHashtable("pin", ResponseErrorType.ParameterMissing);


        }

        /// <summary>
        /// Returns the state of all digital pins
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        /// 



        private void SetAllDigitalPinStates(Request e, Hashtable h)
        {

            funcao = "Leds";



            try
            {
                bool state = (e.GetArguments["state"].ToString() == "true") ? true : false;

                state = PinManagement.GetDigitalPinState(3);
                state = !state;

                Serial_Port.Serial("Alteração em todos os leds: " + " - Estado: " + state.ToString() + " - " + DateTime.Now);


                for (int i = 3; i <= 6; i++)
                {

                    PinManagement.SetDigitalPinState(i, state);
                    h.Add("pin" + i, PinManagement.GetDigitalPinState(i) ? "1" : "0");
                }
            }
            catch
            {
                h = XMLResponse.GenerateErrorHashtable("state", ResponseErrorType.ParameterRangeException);
            }


        }

        private void GetAllDigitalPinStates(Request e, Hashtable h)
        {
            funcao = "Leds";

            try
            {


                for (int i = 0; i <= 3; i++)
                {

                    h.Add("pin" + i, PinManagement.GetDigitalPinState(i) ? "1" : "0");
                }
            }
            catch (Exception ex)
            {

                h = XMLResponse.GenerateErrorHashtable("", ResponseErrorType.InternalOperationError);
                Debug.Print(ex.ToString());
            }




        }

        /// <summary>
        /// Returns the period and the duration of all PWM pins
        /// </summary>
        /// <param name="e"></param>
        /// <param name="h"></param>
        private void GetAllPWMValues(Request e, Hashtable h)
        {
            funcao = "PWM";
            try
            {
                for (int i = 0; i < PinManagement.PWM_IDs.Length; i++)
                {
                    int id = PinManagement.PWM_IDs[i];
                    h.Add("pin" + PinManagement.PWM_IDs[i] + "_period", PinManagement.GetPWMPeriod(id));
                    h.Add("pin" + PinManagement.PWM_IDs[i] + "_duration", PinManagement.GetPWMDuration(id));
                }
            }
            catch (Exception ex)
            {
                h = XMLResponse.GenerateErrorHashtable("", ResponseErrorType.InternalOperationError);
                Debug.Print(ex.ToString());
            }
        }
...

This file has been truncated, please download it to see its full contents.
XML ResponseC#
Modified NeonMika Webserver XML Response to process all GET Requests and recreate webpage on SD Card
using System;
using System.Text;
using System.Net.Sockets;
using System.Collections;
using Microsoft.SPOT;
using NeonMika.XML;
using System.IO;
using System.Threading;

namespace NeonMika.Webserver.Responses
{

    /// <summary>
    /// This class knows, HOW to send back the data to the client
    /// Write your own XMLResponseMethod, create a XMLResponse with XMLResponse(url,XMlResponseMethod), and add this response to your webserver instance
    /// </summary>
    public class XMLResponse : Response
    {




        public static string chave = "chave_off.gif";
        public static string buzzer = "buzzer_on.gif";
        public static string motor = "motor_off.gif";
        public static string motor2 = "motor_off.gif";
        public static string alarme = "Ultimo Alarme: ";
        public static int nalarme = 0;
        public static string texto = "<!DOCTYPE html>\n\n<html>\n</head>";
        public static string display = "";
        public static string angulo = "";


        static public string[] alarmes = new string[11];

        public XMLResponse(string url, XMLResponseMethod method)
            : base(url)
        {
            this._ResponseMethod = method;
            _Pairs = new Hashtable();
        }

        private XMLResponseMethod _ResponseMethod;
        private Hashtable _Pairs;

        /// <summary>
        /// Unifies the possible error messages
        /// </summary>
        /// <param name="parameter">Name of the parameter on which the error took place</param>
        /// <param name="ret">Error type</param>
        /// <returns>Hashtable that has to be returned to the client</returns>
        public static Hashtable GenerateErrorHashtable(String parameter, ResponseErrorType ret)
        {
            Hashtable h = new Hashtable();

            switch (ret)
            {
                case ResponseErrorType.ParameterConvertError:
                    h.Add("error", "Following parameter could not be converted: " + parameter + " to the right format (int, string, ...).");
                    break;
                case ResponseErrorType.ParameterMissing:
                    h.Add("error", "Following parameter was not submitted: " + parameter + ". Please include it in your URL");
                    break;
                case ResponseErrorType.InternalValueNotSet:
                    h.Add("error", "An internal error accured. Following value could not be set: " + parameter + ". Please check the requested method's source code");
                    break;
                case ResponseErrorType.ParameterRangeException:
                    h.Add("error", "Following parameter was out of range: " + parameter + ".");
                    break;
                case ResponseErrorType.InternalOperationError:
                    h.Add("error", "An internal error accured. Following code part threw the error: " + parameter + ". Please check the requested method's source code");
                    break;
            }

            return h;
        }











        /// <summary>
        /// Execute this to check if SendResponse shoul be executed
        /// </summary>
        /// <param name="e">The request that should be handled</param>
        /// <returns>True if URL refers to this method, otherwise false (false = SendRequest should not be exicuted) </returns>
        public override bool ConditionsCheckAndDataFill(Request e)
        {




            _Pairs.Clear();
            if (e.URL == this.URL)
                _ResponseMethod(e, _Pairs);
            else
                return false;
            return true;
        }

        public static void responde()
        {




            //  Send200_OK("text/html", byteCount, e.Client);
            // SendData(e.Client, bytes);
        }

        /// <summary>
        /// Sends XML to client
        /// </summary>
        /// <param name="e">The request which should be handled</param>
        /// <returns>True if 200_OK was sent, otherwise false</returns>
        public override bool SendResponse(Request e)
        {


            String xml = "";

            //Abertura do arquivo a partir do Sd

            FileStream filestream = new FileStream(@"\SD\index.html", FileMode.Open);
            StreamReader reader = new StreamReader(filestream);
            StreamWriter streamWriter = new StreamWriter(filestream);


            //construção da página index.html

            xml += "<!DOCTYPE html>\n\n<html>\n";

            //refresh automático 60 segundos
            xml += "<meta http-equiv=\"refresh\" content=\"60\"></head><body style='font-family=\"verdana\"'>";




            //Escreve a data e hora atual

            xml += "<table width=\"100%\"><tr><td align=\"center\"><p><font size=\"3\" color=\"red\">Data e Hora Atual: " + DateTime.Now + "</font></p></td>";


            //Escreve o último alarme

            xml += "<td align=\"center\"><p><font size=\"3\" color=\"red\">Numero de Alarmes: " + nalarme.ToString() + "</font></p></td>";
            xml += "<td align=\"center\"><p><font size=\"3\" color=\"red\">Ultimo Alarme: " + alarme + "</font></p></td></tr></table>";

            xml += "<hr>";
            //função dos leds
            xml += "<table width=\"100%\">";
            xml += "<form action=\"/setDigitalPin\" method=\"get\">";
            xml += "<tr valign=\"middle\"><td valign=\"middle\" align=\"center\"><input type=\"radio\" name=\"pin\" value=\"3\" checked>Led 0";
            xml += "<input type=\"radio\" name=\"pin\" value=\"4\">Led 1";
            xml += "<input type=\"radio\" name=\"pin\" value=\"5\">Led 2";
            xml += "<input type=\"radio\" name=\"pin\" value=\"6\">Led 3<br>";
            xml += "<input type=\"hidden\" name=\"state\" value=\"true\"><br>";
            xml += "<input type=\"submit\" value=\"ON/OFF\"></form><br></td>";
            xml += "<td valign=\"middle\" align=\"center\">Todos os Leds<br>";
            xml += "<form action=\"/setAllDigitalPinStates\" method=\"get\">";
            xml += "<input type=\"hidden\" name=\"state\" value=\"true\">";
            xml += "<input type=\"submit\" value=\"ON/OFF\"></form><br></td>";
            xml += "<td valign=\"middle\" align=\"center\">Estado dos Leds (1-4) <br>";


            //imagem dos leds
            for (int i = 3; i <= 6; i++)
            {
                xml += "<img src=\"/sd/images/led_";
                xml += (PinManagement.GetDigitalPinState(i)) ? "on" : "off";
                xml += ".gif\" height=\"50\">\n  ";
            }

            xml += "</td></tr></table>";
            xml += "<hr>";
            //chave
            xml += "<table width=\"100%\"><tr valign=\"middle\">";
            xml += "<td valign=\"middle\" align=\"center\"><b>Chave</b><br><form action=\"/getDigitalPinState\" method=\"get\">";
            xml += "<input type=\"hidden\" name=\"pin\" value=\"3\">";
            xml += "<input type=\"submit\" value=\"Atualizar\"></form><br>";
            //imagem da chave
            xml += "<img src=\"/sd/images/" + chave + "\" height=\"50\">\n </td>";


            //buzzer
            xml += "<td  valign=\"middle\" align=\"center\"><b>Buzzer</b><br>";
            xml += "<form action=\"/pwm\" method=\"get\">";
            xml += "<input type=\"hidden\" name=\"pin\" value=\"9\">";
            xml += "<input type=\"hidden\" name=\"period\" value=\"200\">";
            xml += "<input type=\"hidden\" name=\"duration\" value=\"100\">";
            xml += "<input type=\"submit\" value=\"ON/OFF\">";
            xml += "</form><br>";
            xml += "<br> ";

            //imagem do buzzer
            xml += "<img src=\"/sd/images/" + buzzer + "\" height=\"50\">\n  </td>";




            //Servo (ainda não está funcionando)
            xml += "<td  valign=\"middle\" align=\"center\"><b>Servo</b><br>";
            xml += "<form action=\"/servo\" method=\"get\">";

            xml += "<input type=\"text\" name=\"angulo\" value=\"90\">";
            xml += "<input type=\"submit\" value=\"Enviar\">";
            xml += "</form><br>";
            xml += "Angulo atual do servo: " + angulo;
            xml += "<br> </td>";

            xml += "</tr></table>";
            //Novas funções serão escritas aqui
            xml += "<hr>";
            //Display
            xml += "<table width=\"100%\"><tr valign=\"middle\">";

            xml += "<td valign=\"middle\" align=\"center\"><b>Display</b><br>";
            xml += "<form action=\"/display\" method=\"get\">";
            xml += "<input type=\"text\" name=\"texto\" value=\"\">";
            xml += "<input type=\"submit\" value=\"Enviar\">";
            xml += "</form><br>";
            xml += "Ultima Mensagem: " + display;
            xml += "</td></tr></table>";

            xml += "<hr>";
            //Motores
            xml += "<table width=\"100%\"><tr><td colspan=\"2\" align=\"center\"><b>Motores</b></td></tr>";
            xml += "<form action=\"/motores\" method=\"get\">";
            xml += "<tr><td valign=\"middle\" align=\"center\">";
            xml += "<input type=\"radio\" name=\"pin\" value=\"0\" checked>Motor 1  ";
            xml += "<input type=\"radio\" name=\"pin\" value=\"11\">Motor 2  <br>";
            xml += "<input type=\"radio\" name=\"dir\" value=\"true\"checked>Horario   ";
            xml += "<input type=\"radio\" name=\"dir\" value=\"false\">Anti-Horario<br>   ";
            xml += "<input type=\"radio\" name=\"state\" value=\"true\"checked>ON  ";
            xml += "<input type=\"radio\" name=\"state\" value=\"false\">OFF<br>";
            xml += "<input type=\"submit\" value=\"Enviar\">";
            xml += "</form></td>";

            xml += "<td valign=\"middle\" align=\"center\"><table width=\"100%\"><tr valign=\"middle\">";
            xml += "<td align=\"center\"><img src=\"/sd/images/" + motor + "\" height=\"50\"><br>Motor 1</td> ";
            xml += "<td align=\"center\"><img src=\"/sd/images/" + motor2 + "\" height=\"50\"><br>Motor 2</td></tr></table>";
            xml += "</td></tr></table>";


            //sobreescrever no final do arquivo, caso fica alguma informação indesejada
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";
            xml += "                                                                                       ";

            xml += "</body></html>";


            byte[] bytes = Encoding.UTF8.GetBytes(xml);
            int byteCount = bytes.Length;



            //reescreve a página index.html
            streamWriter.Write(xml);

            //fecha o arquivo
            streamWriter.Close();




            try
            {
                //resposta do webserver, recarrega a página index.html
                Send200_OK("text/html", byteCount, e.Client);
                SendData(e.Client, bytes);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.ToString());
                return false;
            }












            return true;

        }

    }

}
Pin ManagementC#
GPIO Management
using System;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Microsoft.SPOT.Hardware;
using System.Text;
using System.Threading;
using System.IO;
using System.Collections;
using System.Net;
using Microsoft.SPOT;
using NeonMika.Webserver.Responses;
using Toolbox.NETMF;
using Toolbox.NETMF.NET;
using NeonMikaWebserverExecuteable;


namespace NeonMika.Webserver
{
    /// <summary>
    /// Interface between NeonMika.Webserver and the executing programm
    /// Use this class to work with your pins
    /// </summary>
    static public class PinManagement
    {
        //public
        public const int DIGITAL_PIN_COUNT = 14;
        public const int ANALOG_PIN_COUNT = 6;
        public static int[] PWM_IDs = new int[] { 5, 6, 9, 10 };

        //Standard output ports
        static public OutputPort Digital0 = new OutputPort(Pins.GPIO_PIN_D0, false);
        static public OutputPort Digital1 = new OutputPort(Pins.GPIO_PIN_D1, false);
        static public InputPort Digital2 = new InputPort(Pins.GPIO_PIN_D2, false, Port.ResistorMode.Disabled);
        static private OutputPort Digital3 = new OutputPort(Pins.GPIO_PIN_D3, false);
        static private OutputPort Digital4 = new OutputPort(Pins.GPIO_PIN_D4, false);
        //static private OutputPort Digital7 = new OutputPort(Pins.GPIO_PIN_D7, false); // Used as serial port (COM3)
        //static private OutputPort Digital8 = new OutputPort(Pins.GPIO_PIN_D8, false);
        static public OutputPort Digital11 = new OutputPort(Pins.GPIO_PIN_D11, false);
        static public OutputPort Digital12 = new OutputPort(Pins.GPIO_PIN_D12, false);
        static public OutputPort Digital13 = new OutputPort(Pins.GPIO_PIN_D13, false);

        //Onboard led
        static public OutputPort OnboardLED = new OutputPort(Pins.ONBOARD_LED, false);


        //Onboard switch
        // static public InputPort OnboardBUTTON = new InputPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled);


        static InterruptPort OnboardBUTTON = new InterruptPort(Pins.ONBOARD_SW1, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);


        //Output ports with PWM functionallity
        static private PWM PWM5 = new PWM(Pins.GPIO_PIN_D5);
        static private PWM PWM6 = new PWM(Pins.GPIO_PIN_D6);
        static private PWM PWM9 = new PWM(Pins.GPIO_PIN_D9);
        static private PWM PWM10 = new PWM(Pins.GPIO_PIN_D10);

        //Analog inputs
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog0 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A0);
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog1 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A1);
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog2 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A2);
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog3 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A3);
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog4 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A4);
        static private SecretLabs.NETMF.Hardware.AnalogInput Analog5 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A5);

        //Arrays
        /// <summary>
        /// The statement (static private outputPort[]) has been modified to use the serial port (COM3). 
        /// </summary>
        /// <Digital7 = null>,<Digital8 = null> 
        static private OutputPort[] Digitals = new OutputPort[] { Digital0, Digital1, null, Digital3, Digital4, null, null, null, null, null, null, Digital11, Digital12, Digital13 };
        static private SecretLabs.NETMF.Hardware.AnalogInput[] Analogs = new SecretLabs.NETMF.Hardware.AnalogInput[] { Analog0, Analog1, Analog2, Analog3, Analog4, Analog5 };

        //PWM
        static private PWM[] PWMs = new PWM[] { PWM5, PWM6, PWM9, PWM10 };
        static private uint[] PWM_Durations = new uint[] { 0, 0, 0, 0 };
        static private uint[] PWM_Periods = new uint[] { 0, 0, 0, 0 };
        static private bool[] PWM_On = new bool[] { false, false, false, false };

        static public bool flag = false;

        static public int cont = 0;
        static public string texto;


        static string alarme0 = "                                                        ";
        static string alarme1 = "                                                        ";
        static string alarme2 = "                                                        ";
        static string alarme3 = "                                                        ";
        static string alarme4 = "                                                        ";
        static string alarme5 = "                                                        ";
        static string alarme6 = "                                                        ";
        static string alarme7 = "                                                        ";
        static string alarme8 = "                                                        ";
        static string alarme9 = "                                                        ";

        const int DEBOUNCE_TIME = 5000;
        static DateTime _lastButtonPress = DateTime.Now;

        public static void Main()
        {
            // write your code here
            // Inclusão do filtro para Glitch do Onboard button
            Cpu.GlitchFilterTime = new TimeSpan(0, 0, 0, 0, 5);

            // add an event handler for the push button
            OnboardBUTTON.OnInterrupt += new NativeEventHandler(button_Event);


        }

        //interrupção do botão de alarme

        static void button_Event(uint port, uint data, DateTime time)
        {
            if (time < _lastButtonPress.AddMilliseconds(DEBOUNCE_TIME)) return;
            _lastButtonPress = time;

            if (!flag)
            {
                flag = true;

                XMLResponse.nalarme += 1;

                //pega a data e hora atual e passa para o arquivo XMLResponse

                XMLResponse.alarme = DateTime.Now.ToString();


                Serial_Port.Serial("Alarme detectado: " + DateTime.Now.ToString());


                //acessa o arquivo alarmes.log (criado no Program.cs) e efetua um Append
                FileStream f_filestream = new FileStream(@"SD\alarmes.log", FileMode.Append, FileAccess.Write, FileShare.None);
                StreamWriter s_streamWriter = new StreamWriter(f_filestream);
                String message1 = "Registro: " + DateTime.Now.ToString();
                s_streamWriter.WriteLine(message1);
                Thread.Sleep(1000);
                s_streamWriter.Close();
                f_filestream.Close();

                //acumula um máximo de 10 alarmes mais recentes
                if (cont < 10)
                {
                    switch (cont)
                    {
                        case 0:
                            alarme0 = "<meta http-equiv=\"refresh\" content=\"30\">\n<br>" + message1;
                            break;
                        case 1:
                            alarme1 = message1;
                            break;
                        case 2:
                            alarme2 = message1;
                            break;
                        case 3:
                            alarme3 = message1;
                            break;
                        case 4:
                            alarme4 = message1;
                            break;
                        case 5:
                            alarme5 = message1;
                            break;
                        case 6:
                            alarme6 = message1;
                            break;
                        case 7:
                            alarme7 = message1;
                            break;
                        case 8:
                            alarme8 = message1;
                            break;
                        case 9:
                            alarme9 = message1;
                            break;
                    }
                    cont++;
                }
                else
                {
                    Serial_Port.Serial("Alarme detectado - Envio de email - " + DateTime.Now);

                    cont = 0;
                    //ENVIAR EMAIL
                    
                    SMTP_Client.MailContact From = new SMTP_Client.MailContact(Program.Sender_email, Program.Sender_name);
                    SMTP_Client.MailContact Receiver = new SMTP_Client.MailContact(Program.Receiver_email, Program.Receiver_name);
                    SMTP_Client.MailMessage Message = new SMTP_Client.MailMessage("[!] Limite de 5 Alarmes Acionados");


                    Message.Body += ">> Alarme: \r\n";
                    Message.Body += alarme4 + "\r\n";
                    Message.Body += ">> Número total de alarmes desde a inicialização: " + XMLResponse.nalarme.ToString() + "\r\n";

                    Message.Body += "Enviado em: " + DateTime.Now.ToString() + ".\r\n";

                    

                    // ALTERAR DE ACORDO - smtp.ita.br
                    
                    SMTP_Client Sender = new SMTP_Client(new IntegratedSocket(Program.SMTP_Server, 587), SMTP_Client.AuthenticationTypes.Login, "netduino@rjc.com.br", "ita2019teste");
                    Debug.Print("--> Trying to send the email...");
                    Sender.Send(Message, From, Receiver);
                    Debug.Print("--> Email sent!");
                    
                }

                //abre a página de alarmes
                FileStream filestream = new FileStream(@"\SD\frame_alarme.html", FileMode.Open);
                StreamWriter streamWriter = new StreamWriter(filestream);
                //escreve os alarmes correspondentes
                //as informações desta variavel vem do arquivo PinManagement.cs, interrupção da chave Onboard
                texto = "<!DOCTYPE html>\n\n<html>\n</head>Pagina de Alarmes<br><br>";
                texto += alarme0 + "<br>                                                        ";
                texto += alarme1 + "<br>                                                        ";
                texto += alarme2 + "<br>                                                        ";
                texto += alarme3 + "<br>                                                        ";
                texto += alarme4 + "<br>                                                        ";
                texto += alarme5 + "<br>                                                        ";
                texto += alarme6 + "<br>                                                        ";
                texto += alarme7 + "<br>                                                        ";
                texto += alarme8 + "<br>                                                        ";
                texto += alarme9 + "<br>                                                        ";
                texto += "<br><br><a href=\"alarmes.log\" target=\"frame_principal\">Acessar Histórico (log) Completo</a>                              ";
                texto += "                                                                                             ";
                streamWriter.Write(texto);
                streamWriter.Close();




                //aciona o buzzer
                SetPWM(9, 200, 100);

                //Aguarda 5 segundos
                Thread.Sleep(5000);

                //Desliga o buzzer
                SetPWM(9, 0, 0);




                Thread.Sleep(1000);
                flag = false;

            }



        }





        /// <summary>
        /// Switches a pin from true to false or vis-a-vis
        /// </summary>
        /// <param name="PinNumber"></param>
        static public void SwitchDigitalPinState(int PinNumber)
        {
            bool actState = GetDigitalPinState(PinNumber);

            SetDigitalPinState(PinNumber, !actState);
        }

        /// <summary>
        /// Sets a pin ON or OFF
        /// </summary>
        /// <param name="PinNumber"></param>
        /// <param name="active"></param>
        static public void SetDigitalPinState(int PinNumber, bool active)
        {
            if (Digitals[PinNumber] == null)
            {
                SetPWM(PinNumber, 20000, active ? (uint)20000 : (uint)0);
            }
            else
                Digitals[PinNumber].Write(active);

        }

        /// <summary>
        /// Sets the PWM value for a PWM-enabled pin
        /// </summary>
        /// <param name="PinNumber">5,6,9 or 10</param>
        /// <param name="Period"></param>
        /// <param name="Duration"></param>
        /// <returns></returns>
        static public bool SetPWM(int PinNumber, uint Period, uint Duration)
        {
            if (PinNumber == 5 || PinNumber == 6 || PinNumber == 9 || PinNumber == 10)
            {
                PWM tempPWM = null;
                int i = 0;

                switch (PinNumber)
                {
                    case 5:
                        i = 0;
                        break;
                    case 6:
                        i = 1;
                        break;
                    case 9:
                        i = 2;
                        break;
                    case 10:
                        i = 3;
                        break;
                }

                tempPWM = PWMs[i];
                tempPWM.SetPulse(Period, Duration);
                PWM_Durations[i] = Duration;
                PWM_Periods[i] = Period;

                if (Duration > 0)
                    PWM_On[i] = true;
                else
                    PWM_On[i] = false;

                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="PinNumber"></param>
        /// <returns>True if duration of PWM > 0</returns>
        static public bool GetPWM(int PinNumber)
        {
            if (PinNumber == 5 || PinNumber == 6 || PinNumber == 9 || PinNumber == 10)
            {
                bool state = false;

                switch (PinNumber)
                {
                    case 5:
                        state = PWM_On[0];
                        break;
                    case 6:
                        state = PWM_On[1];
                        break;
                    case 9:
                        state = PWM_On[2];
                        break;
                    case 10:
                        state = PWM_On[3];
                        break;
                }
                return state;
            }
            else
                return false;
        }

        static public int GetPWMDuration(int PinNumber)
        {
            switch (PinNumber)
            {
                case 5:
                    return (int)PWM_Durations[0];
                case 6:
                    return (int)PWM_Durations[1];
                case 9:
                    return (int)PWM_Durations[2];
                case 10:
                    return (int)PWM_Durations[3];
                default:
                    return -1;
            }
        }

        static public int GetPWMPeriod(int PinNumber)
        {
            switch (PinNumber)
            {
                case 5:
                    return (int)PWM_Periods[0];
                case 6:
                    return (int)PWM_Periods[1];
                case 9:
                    return (int)PWM_Periods[2];
                case 10:
                    return (int)PWM_Periods[3];
                default:
                    return -1;
            }
        }

        /// <summary>
        /// Check if pin is ON or OFF
        /// </summary>
        /// <param name="PinNumber"></param>
        /// <returns></returns>
        static public bool GetDigitalPinState(int PinNumber)
        {
            if (Digitals[PinNumber] == null)
                return GetPWM(PinNumber);
            else


                return Digitals[PinNumber].Read();


        }

        /// <summary>
        /// Reads the value from an analog pin
        /// </summary>
        /// <param name="PinNumber"></param>
        /// <returns></returns>
        static public double GetAnalogPinValue(int PinNumber)
        {

            return Analogs[PinNumber].Read() / 905.0 * 3.3;
        }
    }
}

Schematics

Fritzing Protoboard Schematic
projeto2_5ssDLY7WZS.fzz

Comments

Similar projects you might like

Notification Call System

Project tutorial by Jelle

  • 2,426 views
  • 0 comments
  • 10 respects

Low Power RF Beacon for Remote Sensing & Communication

Project tutorial by Shahariar

  • 1,889 views
  • 0 comments
  • 16 respects

WaterPi: Houseplant Remote Watering and Monitoring System

Project tutorial by Demirhan Aydin

  • 29,499 views
  • 14 comments
  • 128 respects

Smart Garbage Monitoring System Using Arduino 101

Project tutorial by Technovation

  • 22,746 views
  • 7 comments
  • 37 respects

Project KOOL: Temperature and Humidity Remote Monitoring

Project tutorial by vincent wong

  • 4,878 views
  • 1 comment
  • 12 respects

A fall detection system based on Arduino, Windows and Azure

Project tutorial by Jiong Shi

  • 21,591 views
  • 7 comments
  • 46 respects
Add projectSign up / Login