Hardware components | ||||||
| × | 4 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
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"
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);
}
}
}
}
No preview (download only).
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();
}
}
}
Server
C#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 Response
C#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;
}
}
}
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;
}
}
}
Comments