Un monitor con Netduino


Las ratas se comen cualquier cosa

Hace unos años stewlg  cometío el error de almacenar alimentos en el sótano de una manera que era inferior a salvo de roedores. Un auge de la población pequeña en ratas se produjo antes de que entendíamos lo que estaba sucediendo. Cuando quitamos todo el acceso a la comida en el final del invierno, introdujimos un hambre cuya pánico después nos leemos en los plásticos roídos sobre todo encerrando alimento.

Rat-vs

Todo esto era malo. Caca de rata y orinar son desagradables. Pero lo peor fue que las ratas desesperadas comiendo el tubo de goma y las juntas dentro de nuestra lavadora. Una helada mañana me vino a encontrar jabonosa hemorragia agua fría de la lavadora y que cubre el suelo de nuestro sótano. De repente comprendí por qué alguien querría un monitor de inundación.

Empezó con un acuerdo con pilas de nueve voltios con una alarma audible.

IMG_5217

Esto es mejor que nada, pero no iba a ser capaz de decirle acerca de los problemas cuando estaba fuera de la ciudad, o, para el caso, cuando  stewlg  estaba en el trabajo. Quería más. En concreto,  quería que se conectara a Nagios(un proveedor de Iot) , que comenzó el seguimiento de unas cuantas unidades de disco duro para mí, pero ha crecido a lo largo de los años en algo que una empresa de tamaño medio que podría estar usando para monitorear su red. Nagios se había convertido en la forma en que llevaba la cuenta de los problemas en la casa. Ya paginado y me envió por correo electrónico, y que mantendrá las métricas y datos históricos.

Lo primero que hizo   stewlg   fue buscar un producto comercial que hizo esto – seguramente alguien más necesitado la misma cosa. Y, de hecho, se ha hecho :

SensorMetrix_225Pound

Mientras escribía este post   costaba  alrededor de 425 dólares de Estados Unidos, que todavía parece ridículo, no importa lo industrial y prueba de balas el dispositivo de seguridad es. Eencontró otra empresa que realizaba este también, pero te cobran un precio similar si no mayor para la misma funcionalidad.

¿No podría hacer todo esto con un Arduino ? Y los Internets de cosas?

¿Por qué Netduino

Miró a Arduino, pero una alternativa menos popular  a  stewlg  le  atrajo: Netduino .

* Ya utilizba .NET para el trabajo.  C # es un ambiente verdaderamente excelente.
* Hilos, eventos, temporizadores
Y, probablemente, lo mejor de todo:
* En el circuito de depuración

 stewlg  hizo lo suficiente programación de objetos incrustados para es apreciado tambien  la posibilidad de desplazarse por el código en un depurador o pausando el  programa de modo que  stewlg  estaba dispuesto a pagar un poco más por esto, y de tolerar algunos compromisos en el medio ambiente para evitar ReSharper withdrawl.

También significó mucho para  stewlg   que, si bien la placa de  netduino  cuesta  $ 60 en lugar de ~ $ 30 para un Arduino, pero Netduino +  venía con Ethernet incorporado y no tendría que futz por ahí con un escudo en el primer día. Esto parecía una introducción más suave más amable con el trabajo Arduino-esque.

Portar NRPE a C # y .NET Micro

Como agradable como C # generalmente es que se necesita trabajar en una versión más pequeña de él para recordarle cuánto hay en las bibliotecas, y no en el idioma adecuado. Trabajando en el marco Micro es como trabajar en una cocina cocina en un pequeño velero cuando estás acostumbrado a una cocina de casa decente .Plantillas? Nop. El formato de cadenas? Nop. LINQ? Hah – que es rico.

Afortunadamente, NRPE es un formato muy simple:

  [2 Byte int16_t] - Número de versión
 [2 Byte int16_t] - Tipo (Consulta / Respuesta)
 [4 Byte u_int32_t] - CRC32 Checksum
 [2 int16_t Byte] - código de resultado (OK, WARNING, ERROR DESCONOCIDO)
 [1024 Char Byte] Buffer

Aun así, tubo problemas con el orden de bytes y el relleno por un poco de tiempoantes de averiguarlo. El mayor problema era conseguir un CRC compatible de trabajo, y al final me terminó portar el código a C # . Hubo otro código por ahí que podría haber funcionado, pero casi todo otro código C # hace buen uso viril, sano, de plantillas y LINQ y todo lo que no se puede tener en 192kb de memoria.

¿Cómo funciona

Usted puede tener una mirada en el código mismo, pero los que no tienen una instalación de Nagios puede gustarte una vista previa de cómo funcionan las cosas, una vez que haya instalado las cosas.

He aquí cómo llamar a los diferentes controles manualmente. Aquí nos estamos quedando check_nrpe (el cliente en nuestro servidor Netduino) de Ubuntu:

  # ./check_nrpe -n -H Noah.doodle.local -c check_temp

 OK - Temperatura = 78.1F 25.6C Humedad relativa = 33,6% | temp_celsius = 25.6000004; 35; 38; 0; 100, relative_humidity = 33,6000023%; 70; 80; 0; 100, temp_fahrenheit = 78,080000686645519; 95; 100,40000000000001; 32; 212
  # ./check_nrpe -n -H Noah.doodle.local -c check_flood

 OK - No detectado agua | water_detected = 0
  # ./check_nrpe -n -H Noah.doodle.local -c check_uptime

 OK - Uptime: 03: 42: 51.2740000 memoria libre: 101364 | uptime_in_seconds = 13371, uptime_in_hours = 3, uptime_in_minutes = 222, free_memory = 101364

Estos son los tres servicios que he escrito hasta ahora. Hay tres partes principales visible aquí:

  • OKAY

El código de resultado. En este caso, el servicio se considera estar en un buen estado.

  • Temperatura = 78.1F 25.6C Humedad relativa = 33,6%

Este es el texto de estado legible que aparecerá en Nagios.

  • temp_celsius = 25.6000004; 35; 38; 0; 100, relative_humidity = 33,6000023%; 70; 80; 0; 100, temp_fahrenheit = 78,080000686645519; 95; 100.40000000000001; 32; 212:

Los valores después de la tubería es de datos de rendimiento que es todo lo registra, y puede ser graficada retrospectiva con diversos plug-ins.

Así que aquí está cómo aparece el servicio de Nagios. Aquí al parecer las ratas están de vuelta y han encontrado su camino más allá de las placas de metal que atornilladas a la parte inferior de la lavadora, o tal vez nuestro primer inodoro piso se ha desbordado y se echan por el conducto de calefacción en el sótano de nuevo (no hay ratas la culpa de eso , a menos que mi trasero puede ser considerada como un barco que se hunde) Y algo ha ido mal con el sensor de temperatura -. tal vez los cables han sido comido por las ratas.

NagiosStatusSlice2

Esto es lo que la salida de línea de comandos sería buscar estos dos casos problemáticos:

  ADVERTENCIA - No se puede leer la temperatura.  |
  CRÍTICA - Agua detecta!  | Water_detected = 1

Aquí hay una captura de pantalla de lo que se puede hacer con los datos de rendimiento recogidos a través del tiempo, desde un tiempo sin emergencias o fallas. Podemos ver un tiempo de actividad en constante aumento, y un uso de la memoria constante (no hay fugas aparentemente):

NagiosUptimeInMinutesAndFreeMemoyDemo

Alguna variación en la temperatura y una humedad casi constante:

NagiosTempAndHumidityGraphDemo

Limitaciones

Es importante señalar que la -n aquí es esencial * *:

  ./check_nrpe -n -H noah.doodle.local -c check_uptime

Esto inhabilita SSL para NRPE. Hay al parecer hay espacio en el Netduino para una gran biblioteca tales . Si esto es esencial para que supongo que se podría envolver dentro de un túnel VPN, etc.

Esto es lo que verás si intenta llamar NRPE sin SSL:

  # ./check_nrpe -H Noah.doodle.local -c check_flood
 Check_nrpe: tiempo de espera de socket después de 10 segundos.

También hay algo de cordura comprobar en el código; Si el tipo de consulta no se reconoce TinyNrpeServer no será capaz de responder a la consulta y no intentará.Un mensaje de depuración dará una pista sobre SSL si está conectado a la consola.

Estabilidad

Si se mira a través del código, puede que le resulte bastante paranoico acerca de los errores y accidentes, con dos reinicios duros independientes en el código. Esto se debe a que he probado el código bastante duro y yo estaba esforzándome por evitar que el dispositivo nunca deje de responder y que necesitan un reinicio.

El dispositivo ahora hace un reinicio duro en dos casos:

1) Cuando se hace una excepción

Hay algunas excepciones que descubrí que se producen normalmente, tales como errores de desconexión de socket, que a menudo pueden ser reclamadas a sin recurrir a reiniciar el dispositivo. Por desgracia, no todos ellos parecían ser recuperable, o al menos no de manera consistente, y en lugar de distinguir, me eligieron para reiniciar el dispositivo. En condiciones normales de funcionamiento son bastante raros.

2) Cuando no se haya recibido una consulta para un intervalo de tiempo configurable

En las pruebas, he probado usando condiciones muy abusivos, pero estas condiciones podría conseguir fácilmente el Netduino en un estado donde no sólo mi código no escuchar las conexiones de red entrantes (que podría decirse que tal vez podría ser mi culpa), pila de red del dispositivo se estrellaría, y sería dejar de responder a un ping, que me pareció mucho menos responsables.

En mi código tengo este tiempo de espera configurado así:

  /// <Summary>
 /// Número de milisegundos antes de que la junta se reiniciará.
 /// </ Summary>
 int const público InactivityTimeout = 60 * UpTimeCheck.SecondsPerMinute * UpTimeCheck.MillisecondsPerSecond;

En otras palabras, si no ha tenido un mensaje entrante en una hora, que va a reinicie por sí mismo. Si usted necesita para poner a punto este intervalo, me ponga esto en al menos dos veces el intervalo de control mínimo. Así que si usted comprueba el dispositivo cada 5 minutos, ajusta esto a por lo menos 10 minutos.

Elegí establecer este mucho más alto que yo pueda ver a través de la gráfica el tiempo de actividad, si esto ocurre en realidad nunca – una hora de inactividad debe ser inequívocamente visible.

Para ser justos con la plataforma Netduino, tengo serias dudas de que nadie va a colgar este servidor bajo una carga de red típica. Una encuesta discreta desde un único servidor Nagios cada minuto o dos no va a gravar seriamente nada. Tal vez en un azul-moon, una excepción a la red se producirá y el dispositivo se reinicie en silencio – si lo hace, usted debe ver que se refleja en los datos de rendimiento de tiempo de actividad, pero aún así disfrutar disponibilidad esencialmente ininterrumpida. No espero a nadie a hacer realidad el dispositivo no responde, y activar el reinicio de la vigilancia. Pero por favor dígame cómo va para usted.

Si tuviera que tomar esto más lejos a  stewlg   le gustaría que un temporizador de vigilancia adecuado en hardware .

Expansión

 stewlg   realmente no necesita nada más que un monitor de inundación, pero  pensó en tirar en al menos otra métrica para obtener el código listo para manejar múltiples cheques, por lo tanto, la comprobación de la temperatura.

Aquí es lo menos que había necesidad de hacer para poner en práctica un cheque:

  /// <Summary>
  /// Un ejemplo de lo mínimo que hay que hacer para poner en práctica un cheque
  /// </ Summary>
  DemoCheck clase pública: NrpeCheck
  {
      public override NrpeMessage.NrpeResultState GetStatus (fuera cadena statusString, fuera Hashtable performanceData)
      {
         performanceData = new Hashtable (); var demoMetric = 20;
         performanceData.Add ("demo_metric", demoMetric);
         statusString = "Demo métrica:" + demoMetric.ToString ();
         // Siempre Ok.
         volver NrpeMessage.NrpeResultState.Ok;
      }
  }

Usted probablemente querrá algo de código condicional para el ResultState, y cualquier métrica que tiene probablemente variar. Pero la adición de ningún tipo de supervisión debe ser fácil, al menos desde el punto de vista TinyNrpeServer.

Si usted sube un sensor que desea añadir, envíeme un correo electrónico con un parche o una solicitud de extracción. Me encantaría este servidor NRPE tienen más supervisión que ofrecer fuera de la caja.

Costo

Así que, si no es de $ 425, ¿qué dedico? Probablemente menos de $ 120.Hubiera sido mucho más barato si supiera  lo que estaba haciendo – esto erael primer proyecto de tipo Arduino y los conceptos básicos eran un misterio para  stewlg  . Terminó probando un montón de cosas que no funcionaron antes de encontrar cosas que funcionaron bien pasablemente.

Circuito

Noé V2

Instalación

Prueba inicial de monitor de inundación

Protoshield cableada

Sensor de Inundación comprobación final

Sensor sujeta con cintas para el pelo

Entre las máquinas

Brilla muy prominente en la penumbra

Primeros DHT-22 cableado

DHT-22 en su lugar

Instalado en la caja de ProyectoIMG_5271

Bibliografía y Apreciación

Para ayuda inestimable, indirectos con el protocolo NRPE núcleo, gracias sobre todo a Andreas Marschke y Sadris . Para la clase DhtSensor, Stanislav “CW” Simicek y todo el mundo en este hilo . Para  cluing en aproximadamente perros guardianes y reinicios duras, las personas en estas discusiones . Chris Walker para la clase Cronómetro (y todo lo demás en Netduino, por supuesto).

El Código

https://github.com/StewLG/NetduinoNrpe

 

 

 

Fuente aqui

Anuncios

Proyecto alarma casera con Netduino


En este original   proyecto  se trata de proteger una habitación de la bomba de sumidero  potencialmente peligrosa para los niños  asegurándose  de que las estancias quedan las  puertas cerradas y las personas (principalmente niños) no entran  en esta.

Las soluciones “alarma de la puerta” disponibles en el mercado parecen dirigidas a congeladores y simplemente no se adaptan a  necesidades mas complejas del autor   que pensaba mas bien  en una solución  con  Netduino.

La idea  original por tanto era algo que hiciera sonar  una alarma corta cuando se abriera la puerta y luego alertara a intervalos (cada pocos minutos), similar a un detector de humo con una batería que funcionase hasta agotar la batería o  hasta que la puerta se cerrase

esquema_alarma

La unidad controla la puerta a través de un interruptor magnético. Cuando se abre la puerta varias cosas suceden:

  1.  La luz del techo se enciende con un relé que controla una carga de baja  tensión.
  2.  Un servicio web se llama el cual envía un MMS a un teléfono.
  3. Un contador de tiempo que  se activa qeu al concluir  producirá una alerta sonora y hara una  llamada webservice (MMS) si la puerta permanece abierta durante un periodo de tiempo determinado.

Cuando se cierra la puerta a la luz se apaga y el temporizador de la alarma se detiene. El proyecto también incorpora una pantalla LCD de 2 líneas para mensajes, 2 LEDs (1 para la energía, 1 para la indicación de modo de problemas / override) y algunos botones para interactuar con el sistema.

Las funcionalidades de esta alarma de puerta basada en Netduino pues son las siguientes :

  •  Apaga/enciende  la luz : la enciende automáticamente cuando se abre la puerta y la apaga cuando la puerta está cerrada
  •  Alarma del MMS al abrir la puerta (a través de llamadas de servicio web)
  •  Alerta audible y alerta MMS adicional si la puerta se deja abierta más tiempo que  el  valor del temporizador
  •  Alerta que se repiten a intervalos especificados si la puerta sigue dejándose abierta
  • 4 botones :
    •  Botón 1: Manual de luz de encendido / apagado de anulación
    • – Botón 2: Regreso al control de forma automática la luz
    • – Botón 3: mensajes de error Revisión (principalmente para conexiones de red)
    • – Botón 4: Encender / apagar el sensor de la puerta (permite prolongado puerta abierta sin alerta)

Respecto al software para Netduino  se utilizan  cuatro clases :

Una clase para  dar soporte  a la comunicación de red:

public static class Network
{
public static bool NetworkAvail = false;
public static NetworkInterface ni = NetworkInterface.GetAllNetworkInterfaces()[0];

static NoteClass[] networkUpTune = {
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond)
};

static NoteClass[] networkDownTune = {
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond)
};

static NoteClass[] alertTune = {
new NoteClass(5,NoteClass.C, NoteClass.Eighth),
new NoteClass(6,NoteClass.C, NoteClass.Eighth),
new NoteClass(5,NoteClass.C, NoteClass.Eighth),
new NoteClass(6,NoteClass.C, NoteClass.Eighth)
};

public static void InitNetwork()
{
ParallaxLCD.Print(“Network…”);
int count = 0;
//DHCP can take a few seconds to finish so wait (up to 10 seconds) for it to complete
while (true)
{
count++;
ni = NetworkInterface.GetAllNetworkInterfaces()[0];
//only try for 10 seconds
if (ni.IPAddress != “0.0.0.0” || count > 10) break;
Thread.Sleep(1000);
}
if (ni.IPAddress == “0.0.0.0”)
{
ParallaxLCD.Print(“Network…\rError: Failed”);
}
else
{
ParallaxLCD.Print(“Network… IP:\r” + ni.IPAddress);
NetworkAvail = true;
}
//wire in event handler to keep track of the current network up/down state
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
}

static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
NetworkAvail = e.IsAvailable;
if (Program.initializing)
return;
if (NetworkAvail)
{
ParallaxLCD.Play(networkUpTune);
}
else
{
ParallaxLCD.Play(networkDownTune);
}
}

public static void SendAlert()
{
if (NetworkAvail)
{
try
{
//HttpWebRequest
HttpWebRequest alertRequest = (HttpWebRequest)WebRequest.Create(Program.AlertWebService);
alertRequest.Method = “GET”;
HttpWebResponse alertResponse = (HttpWebResponse)alertRequest.GetResponse();
if (alertResponse.StatusCode != HttpStatusCode.OK)
{
Program.LastError = “(SendAlert) ” + alertResponse.StatusCode.ToString() + “: ” + alertResponse.StatusDescription;
ParallaxLCD.Play(alertTune);
}
}
catch (Exception e)
{
Program.LastError = “(SendAlert) ” + e.Message;
ParallaxLCD.Play(alertTune);
}
}
else
{
Program.LastError = “(SendAlert) Network unavailable”;
ParallaxLCD.Play(alertTune);
}
}

}
}

La clase  para controlar el display LCD

//Non-visible characters (Decimal ASCII) used by the Parallax LCD as commands
public enum LCD_COMMAND_CHARS
{
PrintCustomChar0 = 0,
PrintCustomChar1 = 1,
PrintCustomChar2 = 2,
PrintCustomChar3 = 3,
PrintCustomChar4 = 4,
PrintCustomChar5 = 5,
PrintCustomChar6 = 6,
PrintCustomChar7 = 7,
Backspace = 8,
Right = 9,
LineFeed = 10,
FormFeed = 12, //clears display and sets cursor to row 0 column 0
CR = 13,
BacklightOn = 17,
BacklightOff = 18,
DisplayOff = 21,
DisplayOn_NoCursor_NoBlink = 22,
DisplayOn_NoCursor_CharBlink = 23,
DisplayOn_Cursor_NoBlink = 24,
DisplayOn_Cursor_CharBlink = 25,
//Sound control
NoteLength_1_64 = 208,
NoteLength_1_32 = 209,
NoteLength_1_16 = 210,
NoteLength_1_8 = 211,
NoteLength_1_4 = 212,
NoteLength_1_2 = 213,
NoteLength_Whole = 214,
NoteScale_3 = 215,
NoteScale_4 = 216,
NoteScale_5 = 217,
NoteScale_6 = 218,
NoteScale_7 = 219,
Note_A = 220,
Note_A_Sharp = 221,
Note_B = 222,
Note_C = 223,
Note_C_Sharp = 224,
Note_D = 225,
Note_D_Sharp = 226,
Note_E = 227,
Note_F = 228,
Note_F_Sharp = 229,
Note_G = 230,
Note_G_Sharp = 231,
Note_Rest = 232,
LoadCustomChar0 = 248,
LoadCustomChar1 = 249,
LoadCustomChar2 = 250,
LoadCustomChar3 = 251,
LoadCustomChar4 = 252,
LoadCustomChar5 = 253,
LoadCustomChar6 = 254,
LoadCustomChar7 = 255
}

//This class assumes the Parallax LCD/speaker combo unit is connected to Netduino Plus Digital I/O PIN 3
//which is reserved for COM2 in the Netduino framework. Also assumes the Parallax LCD has been set to
//9600 baud using it’s onboard dip switches.
public static class ParallaxLCD
{
private static SerialPort LCD_PORT;
private static string COM_PORT = “COM2”; //Netduino Plus Digital I/O PIN 3
private static int COM_BAUD = 9600;

private static bool _LCD_state = false;

public static bool LCD
{
get
{
return _LCD_state;
}
set
{
if (value == _LCD_state)
{
//LCD already in specified state, don’t do anything
return;
}
if (value)
{
LCDOn();
BacklightOn();
}
else
{
BacklightOff();
LCDOff();
}
_LCD_state = value;
}
}
public static void Print(string inputstring)
{
//if the first line is >= 16 characters then remove the line break for a more natural behavior
int cr = inputstring.IndexOf(‘\r’, 0);
if (cr >= 16)
{
inputstring = inputstring.Substring(0, cr) + inputstring.Substring(cr + 1);
}
//this routine assumes all output will be “full screen”, meaning no other data is left on the screen
ClearLCD();
byte[] bytes = UTF8Encoding.UTF8.GetBytes(inputstring);
LCD_PORT.Write(bytes, 0, bytes.Length);
}

public static void StartSerial()
{
LCD_PORT = new SerialPort(COM_PORT, COM_BAUD, Parity.None, 8, StopBits.One);
LCD_PORT.Open();
}

public static void BacklightOn()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.BacklightOn }, 0, 1);
}

public static void BacklightOff()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.BacklightOff }, 0, 1);
}

public static void ClearLCD()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.FormFeed }, 0, 1);
}

public static void LCDOff()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.DisplayOff }, 0, 1);
}

public static void LCDOn()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.DisplayOn_NoCursor_NoBlink }, 0, 1);
}

public static void LCDCR()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.CR }, 0, 1);
}

//Short, high-pitched sound to ack as notification that an action was detected (like a button press)
public static void Acknowledge()
{
Play(new NoteClass(7, NoteClass.A, NoteClass.ThirtySecond));
}

//Sound a traditional computer beep
public static void Beep()
{
Play(new NoteClass(5, NoteClass.A, NoteClass.Quarter));
}

public static void Play(NoteClass note)
{
byte[] sequence = new byte[3];
sequence[0] = (byte)note.ScaleChar;
sequence[1] = (byte)note.LengthChar;
sequence[2] = (byte)note.NoteChar;
LCD_PORT.Write(sequence, 0, 3);
}
public static void Play(NoteClass[] notes)
{
int currentScale = 0;
int currentLength = 0;
int count = 0;
if (notes != null && notes.Length > 0)
{
byte[] sequence = new byte[notes.Length * 3];
foreach (NoteClass note in notes)
{
if (note.ScaleChar != currentScale)
{
currentScale = note.ScaleChar;
sequence[count++] = (byte)currentScale;
}
if (note.LengthChar != currentLength)
{
currentLength = note.LengthChar;
sequence[count++] = (byte)currentLength;
}
sequence[count++] = (byte)note.NoteChar;
}
LCD_PORT.Write(sequence, 0, count);
}
}

public static byte[] CharsToBytes(char[] Input)
{
byte[] ReturnValue = new byte[Input.Length];

for (int Counter = 0; Counter < Input.Length; ++Counter)
{
ReturnValue[Counter] = (byte)Input[Counter];
}
return ReturnValue;
}

}
public class NoteClass
{
//Helper constants
public const int A = 0;
public const int ASharp = 1;
public const int B = 2;
public const int C = 3;
public const int CSharp = 4;
public const int D = 5;
public const int DSharp = 6;
public const int E = 7;
public const int F = 8;
public const int FSharp = 9;
public const int G = 10;
public const int GSharp = 11;
public const int Rest = 12;

public const int SixtyQuarter = (int)LCD_COMMAND_CHARS.NoteLength_1_64;
public const int ThirtySecond = (int)LCD_COMMAND_CHARS.NoteLength_1_32;
public const int Sixteenth = (int)LCD_COMMAND_CHARS.NoteLength_1_16;
public const int Eighth = (int)LCD_COMMAND_CHARS.NoteLength_1_8;
public const int Quarter = (int)LCD_COMMAND_CHARS.NoteLength_1_4;
public const int Half = (int)LCD_COMMAND_CHARS.NoteLength_1_2;
public const int Whole = (int)LCD_COMMAND_CHARS.NoteLength_Whole;

private int _scale = 5;
private int _note = A;
private int _length = Quarter;

public int Scale
{
get
{
return _scale;
}
set
{
if (value >= 3 && value <= 7)
{
_scale = value;
}
}
}
public int ScaleChar
{
get
{
return ((int)LCD_COMMAND_CHARS.NoteScale_3 – 3) + _scale;
}
}
public int Note
{
get
{
return _note;
}
set
{
if (value >= A && value <= Rest)
{
_note = value;
}
}
}
public int NoteChar
{
get
{
return (int)LCD_COMMAND_CHARS.Note_A + _note;
}
}
public int Length
{
get
{
return _length;
}
set
{
if (value >= SixtyQuarter && value <= Whole)
{
_length = value;
}
}
}
public int LengthChar
{
get
{
return _length;
}
}

public NoteClass(int scale, int note, int length)
{
Scale = scale;
Note = note;
Length = length;
}
}

Una clase para controlar los pulsadores

public static class Utility
{
public static string PadLeft(string val, int maxlen, string padchar)
{
string newval = val;
while (newval.Length < maxlen)
{
newval = padchar + newval;
}
return newval;
}
public static string PadRight(string val, int maxlen, string padchar)
{
string newval = val;
while (newval.Length < maxlen)
{
newval += padchar;
}
return newval;
}
}

Y por último la clase principal:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace DoorManager
{
public enum LightModes { Auto, ManualOn, ManualOff }

public class Program
{
#region User Settings & Constants
public static Cpu.Pin DoorSensorPin = Pins.GPIO_PIN_D11; //Magnetic switch to monitor door open/close state
public static Cpu.Pin LEDPin = Pins.GPIO_PIN_D13; //Status indicator (blinks if error or override on)
public static Cpu.Pin LightPin = Pins.GPIO_PIN_D12; //Connection to high voltage relay to control room light
public static Cpu.Pin Button1Pin = Pins.GPIO_PIN_D7; //Manually turns light on/off
public static Cpu.Pin Button2Pin = Pins.GPIO_PIN_D6; //Returns light control to automatic
public static Cpu.Pin Button3Pin = Pins.GPIO_PIN_D5; //Display error messages
public static Cpu.Pin Button4Pin = Pins.GPIO_PIN_D4; //Toggles door sensor (when off, no alerts are created)
public const int InitialDoorOpenAlertDelay = 30; //in minutes
public const int OngoingDoorOpenSoundAlertDelay = 1; //in minutes
public const int OngoingDoorOpenMessageAlertDelay = 30; //in minutes
public const int LCDOffDelay = 10; //in seconds
public const string AlertWebService = “http://192.168.1.2/WS/SendAlert.aspx?a=Door+Manager&e=Door+Opened&#8221;;
#endregion

#region Fields
public static string LastError = “”;
public static InterruptPort DoorSensor;
public static OutputPort LED;
public static OutputPort Light;
public static InterruptPort Button1;
public static InterruptPort Button2;
public static InterruptPort Button3;
public static InterruptPort Button4;
private static bool IsDoorSensorProcessing = false;
private static bool IsDoorSensorIgnored = false;
public static bool IsDoorOpen = false;
private static bool _LightState = false;
public static bool initializing = true;
public static bool IgnoreButtons = true;
public static bool IgnoreAlerts = false;
public static bool AlertScheduled = false;
public static Timer DoorTimer = new Timer(new TimerCallback(DoorTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer LCDTimer = new Timer(new TimerCallback(LCDTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer LEDTimer = new Timer(new TimerCallback(LEDTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer ButtonTimer = new Timer(new TimerCallback(ButtonTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer SendAlertTimer = new Timer(new TimerCallback(SendAlertTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer DoorCloseTimer = new Timer(new TimerCallback(DoorCloseTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static int CurrentMessageAlertDelayTimeout = 0;
public static int CurrentSoundAlertDelayTimeout = 0;
public static int CurrentAlertDelayTime = 0;
public static int CurrentLCDDelayTime = 0;
public static LightModes LightMode = LightModes.Auto;
private static int _LEDBlinkCount = 0;
public static bool _LEDBlink = false;

static NoteClass[] initTune = {
new NoteClass(5,NoteClass.C, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.D, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.E, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.F, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.G, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.A, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.B, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.C, NoteClass.Sixteenth)
};
#endregion

#region Properties
public static bool LEDBlink
{
set
{
if (value)
_LEDBlinkCount++;
else
_LEDBlinkCount–;
if (_LEDBlinkCount > 0 && !_LEDBlink)
{
_LEDBlink = true;
LEDTimer.Change(250, Timeout.Infinite); //start timer
}
else if (_LEDBlinkCount == 0 && _LEDBlink)
{
LEDTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
_LEDBlink = false;
LED.Write(false);
}
}
}
#endregion

#region Program Start
public static void Main()
{
Initialize();
ShowDoorSensorState();

Thread.Sleep(Timeout.Infinite); //keep running forever
}
#endregion

#region Methods
static void IgnoreButton()
{
IgnoreButtons = true;
ButtonTimer.Change(500, Timeout.Infinite); //restart timer
}

public static bool SetLightState()
{
bool expectedState = IsDoorOpen;
switch (LightMode)
{
case LightModes.ManualOn:
expectedState = true;
break;
case LightModes.ManualOff:
expectedState = false;
break;
}
if (expectedState != _LightState)
{
_LightState = expectedState;
Light.Write(expectedState);
}
return _LightState;
}

public static void SetIgnoreDoorSensor(bool ignore)
{
if (ignore != IsDoorSensorIgnored)
{
IsDoorSensorIgnored = ignore;
if (ignore)
{
LEDBlink = true;
//stop door sensor
DoorTimer.Change(Timeout.Infinite, Timeout.Infinite);
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“Door Sensor\rDisabled”);
SetLCDOffTimer();
}
else
{
LEDBlink = false;
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“Door Sensor\rEnabled”);
Thread.Sleep(2000);
//Check door
ShowDoorSensorState();
}
}
}

static void ShowDoorSensorState()
{
if (IsDoorSensorIgnored)
return;
ParallaxLCD.LCD = true; //ensure LCD is on
ParallaxLCD.Print(“Door ” + (IsDoorOpen ? “Open” : “Closed”));
if (IsDoorOpen)
{
//start door timer
CurrentSoundAlertDelayTimeout = InitialDoorOpenAlertDelay * 60 * 1000; //convert minutes to milliseconds
CurrentAlertDelayTime = 0;
DoorTimer.Change(0, Timeout.Infinite);
}
else
{
//clear door timer
DoorTimer.Change(Timeout.Infinite, Timeout.Infinite);
//set LCD timer
SetLCDOffTimer();
}
SetLightState();
}

static void SetLCDOffTimer()
{
CurrentLCDDelayTime = LCDOffDelay * 1000;
LCDTimer.Change(1000, Timeout.Infinite);
}

static void Initialize()
{
ParallaxLCD.StartSerial();
ParallaxLCD.LCD = true;
ParallaxLCD.ClearLCD();
Thread.Sleep(1000);
ParallaxLCD.Print(“Initializing…”);
ParallaxLCD.Beep();
Thread.Sleep(1000);

//set LED
LED = new OutputPort(LEDPin, false);
LEDBlink = true;

//setup door sensor
DoorSensor = new InterruptPort(DoorSensorPin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
DoorSensor.OnInterrupt += new NativeEventHandler(DoorSensor_OnInterrupt);
IsDoorOpen = DoorSensor.Read();

//setup light control
Light = new OutputPort(LightPin, false);
Light.Write(_LightState);

//setup buttons
Button1 = new InterruptPort(Button1Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button1.OnInterrupt += new NativeEventHandler(Button1_OnInterrupt);
Button2 = new InterruptPort(Button2Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button2.OnInterrupt += new NativeEventHandler(Button2_OnInterrupt);
Button3 = new InterruptPort(Button3Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button3.OnInterrupt += new NativeEventHandler(Button3_OnInterrupt);
Button4 = new InterruptPort(Button4Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button4.OnInterrupt += new NativeEventHandler(Button4_OnInterrupt);

//setup network
Network.InitNetwork();

Thread.Sleep(5000);

ParallaxLCD.Print(“Ready”);
ParallaxLCD.Play(initTune);

Thread.Sleep(2000);

LEDBlink = false;

initializing = false;
IgnoreButtons = false;
}
#endregion

#region Timer Handlers
static void DoorCloseTimerHandler(object sender)
{
//this timer turns off sending alerts for a period of time after the door has been closed; this is another “bounce” preventative measure
DoorCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
IgnoreAlerts = false;
}

static void SendAlertTimerHandler(object sender)
{
//performing this in a timer ensures switch “bounce” doesn’t send multiple alerts
SendAlertTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
Network.SendAlert();
AlertScheduled = false;
}

static void ButtonTimerHandler(object sender)
{
//this routine is to delay reaction to button presses to eliminate “bounce” and false presses
ButtonTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
IgnoreButtons = false;
}

static void LEDTimerHandler(object sender)
{
if (_LEDBlink)
{
LED.Write(!LED.Read());
LEDTimer.Change(250, Timeout.Infinite); //restart timer
}
else
{
LED.Write(false);
}
}

static void LCDTimerHandler(object sender)
{
if (!IsDoorOpen || IsDoorSensorIgnored)
{
CurrentLCDDelayTime -= 1000;
if (CurrentLCDDelayTime <= 0)
{
CurrentLCDDelayTime = 0;
ParallaxLCD.LCD = false; //turn off LCD
//clear LCD timer
LCDTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
else
{
LCDTimer.Change(1000, Timeout.Infinite);
}
}
else
{
//clear LCD timer
LCDTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
}

static void DoorTimerHandler(object sender)
{
if (IsDoorOpen && !IsDoorSensorIgnored)
{
if (CurrentSoundAlertDelayTimeout > 0)
{
CurrentSoundAlertDelayTimeout -= CurrentAlertDelayTime;
}
if (CurrentMessageAlertDelayTimeout > 0)
{
CurrentMessageAlertDelayTimeout -= CurrentAlertDelayTime;
}
if (CurrentMessageAlertDelayTimeout <= 0)
{
//alert
SendAlertTimer.Change(5000, Timeout.Infinite); //send alert after 5 seconds
//restart delay
CurrentMessageAlertDelayTimeout = OngoingDoorOpenMessageAlertDelay * 60 * 1000; //convert minutes to milliseconds
}
if (CurrentSoundAlertDelayTimeout > 0)
{
int mins = CurrentSoundAlertDelayTimeout / 60000;
int secs = (CurrentSoundAlertDelayTimeout – (mins * 60000)) / 1000;
ParallaxLCD.Print(“Door Open\rAlert in ” + (mins > 1 ? mins.ToString() + ” min” : secs.ToString() + ” sec”));
if (mins > 1)
{
CurrentAlertDelayTime = 60000;
}
else
{
CurrentAlertDelayTime = 1000;
}
}
else
{
//alert
ParallaxLCD.Play(new NoteClass(7, NoteClass.A, NoteClass.Half));
//restart delay
CurrentSoundAlertDelayTimeout = OngoingDoorOpenSoundAlertDelay * 60 * 1000; //convert minutes to milliseconds
CurrentAlertDelayTime = 0;
}
DoorTimer.Change(CurrentAlertDelayTime, Timeout.Infinite);
}
}
#endregion

#region Event Handlers
static void DoorSensor_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing || IsDoorSensorProcessing)
return;
IsDoorSensorProcessing = true;
//magnetic switch wired to normally open / onboard switch normally high
//therefore when the door is closed (magnetic switch open) the onboard switch (normally high) is on
IsDoorOpen = (data2 == 1);
if (IsDoorOpen && !IgnoreAlerts)
{
AlertScheduled = true;
SendAlertTimer.Change(5000, Timeout.Infinite); //send alert after 5 seconds
}
else if (!IsDoorOpen && !AlertScheduled)
{
IgnoreAlerts = true;
DoorCloseTimer.Change(5000, Timeout.Infinite); //prevent alerts for 5 seconds
}
ShowDoorSensorState();
IsDoorSensorProcessing = false;
}

/// <summary>
/// Button 1 turns the light on/off manually.
/// </summary>
static void Button1_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
LightModes oldMode = LightMode;
if (_LightState)
LightMode = LightModes.ManualOff;
else
LightMode = LightModes.ManualOn;
SetLightState();
//if we’re moving off auto mode start the led blinking for awareness
if (oldMode == LightModes.Auto)
LEDBlink = true;
IgnoreButton();
}
}

/// <summary>
/// Button 2 sets the light back to automatic (door sensor controlled).
/// </summary>
static void Button2_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
if (LightMode != LightModes.Auto)
{
ParallaxLCD.Acknowledge();
LightMode = LightModes.Auto;
SetLightState();
LEDBlink = false;
}
IgnoreButton();
}
}

static void Button3_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons && (!IsDoorOpen || IsDoorSensorIgnored))
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
if (LastError != null && LastError.Length > 0)
{
string msg = LastError;
//show error in byte size pieces
ParallaxLCD.LCD = true;
while (msg.Length > 0)
{
if (msg.Length > 32)
{
ParallaxLCD.Print(msg.Substring(0,32));
msg = msg.Substring(32);
}
else
{
ParallaxLCD.Print(msg);
msg = “”;
}
Thread.Sleep(5000);
}
ParallaxLCD.Acknowledge();
SetLCDOffTimer();
}
else
{
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“No Errors”);
SetLCDOffTimer();
}
IgnoreButton();
}
}

/// <summary>
/// Button 4 disables/re-enables the door sensor.
/// </summary>
static void Button4_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
SetIgnoreDoorSensor(!IsDoorSensorIgnored);
IgnoreButton();
}
}
#endregion
}
}

Lista de componentes :

  • 2 LED, 4 interruptores momentáneos, tornillos diverso, caja de proyecto
  • Opcional: Kit Protoshield para Ardiono – $ 9.90  http://www.seeedstud…uino-p-318.html
  • Este kit incluye una placa de circuito de prototipos, conectores, resistencias, los LED (no caja montable en proyecto), conmutadores (no caja montable proyecto) y otras piezas misceláneas que puede ayudar a un iniciado a empezar.

Fuente  aqui

Demo de alarma con 11Netduinos


Mike Linnen   ha creado un ingenioso sistema de Alarma con 11 dispositivos Netduino simulando los componentes de un sistema de seguridad para el hogar ,donde todos ellos están  conectados  entre  si   gracias a servicios en la nube alojados en Windows Azure.

Este  prototipo  fue creado como una presentación para un grupo local de usuarios .net explicándoles  los conceptos de Internet de las cosas  o M2M (machine to machine).

Todos los dispositivos de comunicación al servicio de nube van  sobre un bus de mensajes de MQTT.

El servicio en la nube es el cerebro del sistema y toma las decisiones sobre cómo el sistema reacciona a varias entradas.

Gracias a un panel de control que puede verse mediante un navegador web  se puede interactuar  con el sistema  y las  actualizaciones  se envían en tiempo real a los navegadores vía signalr.

Sistema de alarma casera utilizando Netduino Plus (proyecto HomeAlarmPlus)


Se trata de un sistema de monitoreo de alarma simple con Netduino Plus y un panel de alarma típico. Esta aplicación podría ser usado en conjunción con los PC5010 Digital Security Controls (DSC) del panel de control del sistema de seguridad PowerSeries y sensores. Probado con. NET Micro Framework 4.2 (QFE1 y qfe2).

El objetivo de este proyecto es utilizar capacidades de Netduino Plus para controlar el sistema de alarma y reportar las actividades de cualquier detector del sensor de movimiento / por correo electrónico (utilizando protocolo simple de transferencia de correo (SMTP)), un servidor web local y Pachube (ahora Cosm).

Advertencia

Este código contiene información relacionada con un típico sistemas de alarma. Por favor, tenga en cuenta que este procedimiento puede anular la garantía. Cualquier sistema de alarma de cualquier tipo puede ser comprometido deliberadamente o puede fallar al operar como se espera por una variedad de razones.

El autor, Gilberto García, no se hace responsable de los fallos del sistema, tales como: instalación inadecuada, el conocimiento criminal, el acceso de intrusos, la falta de energía, falta de baterías reemplazables, el compromiso de Radio Frecuencia (Wireless) los dispositivos, los usuarios del sistema, detectores de humo, de movimiento detectores, dispositivos de alarma (sirenas, campanas, bocina), líneas telefónicas, falta de tiempo, falta de componentes, pruebas insuficientes, la seguridad y los seguros (propiedad o seguro de vida).

 Hardware
  • Tarjeta Micro SD
  • Adaptador de tarjeta SD
  • 3mm diodo emisor de luz (LED) verde por zona de alarma y detector de movimiento.
  • 330 ohmios para cada LED.
  • Resistencia 5600 ohmios por zona de alarma y detector de movimiento.
  • Schottky diodo por zona de alarma. Schottky diodo debe tener una baja caída de tensión como el SBR10U40CT.
  • Sparkfun ProtoScrewShield (sku: DEV-09729). Otros escudos que trabajarán son: Proto-Screwshield (Wingshield) kit de Adafruit o WingShield Industries.
  • Conexion WiFi  via WiFly Shield o  un adaptador WiFi .  Testado  con Netgear WNCE3001 , IOGEAR GWU627 y adap tadorMIFI de Telefónica.

OPcional

LED verde con soporte)

Conector Panel impermeable (RR-211300-30)

Cable USB 2.0 tipo A macho a un macho (10 pies o más). Se utiliza para acceder al Netduino Plus tabla en el panel de alarma.
200 Vatios / 350 VA UPS (APC System UPS BE350G o similar).
Botón de reset externo Empuje.
Arduino Proto Shield R3. Más espacio para los componentes adicionales. Mouser Electronics y otros.
LCD 16×2  3.3V para Netduino o 5V para Arduino.
Interruptor DPDT (o éste de Mouser Electronics) para la selección de voltaje LCD.

Circuito
El diagrama realizado con la herramienta Fritzing siguiente muestra cómo el Netduino plus, LEDs y las zonas de alarma (o detector de movimiento) están conectados. LCD circuitos de referencia de Szymon Kobalczy.

HomeAlarmPlus connection diagram (basic circuit) Rev-
HomeAlarmPlus connection diagram (basic circuit) RevA
HomeAlarmPlus connection diagram (enhanced circuit) RevG
Zone/Sensor connection

Tenga en cuenta que una o más zonas consisten en lo siguiente:
a) 1 contacto normalmente abierto y 1 contacto NC con fin de línea (EOL) resistencia.
b) Doble circuito de EOL, 1 Contacto normalmente cerrado con 5.6kohm EOL resistencia y diodo Schottky. Esto hará que la protección necesaria para la Netduino o Arduino.
c) Cada zona de tierra debe ser conectado a la ProtoScrewShield GND.
Netduino / ProtoScrewShield Pin
descripción
A0 Zona # 1
Zona A1 # 2
A2 Zona # 3
A3 Zona # 4
Sensor A4 # 1 [Detector de movimiento]
Zona de LED D2 # 1
D3 Zona LED # 2
D4 Zone LED # 3
D5 LED Zona # 4
D6 o D7 Sensor LED # 1 [Detector de movimiento]

AlarmCircuit_schem

Opciones Web Server

 

 

Opciones
descripción
Page / Root
/ open Abrir último archivo en la tarjeta SD.
/ files Lista sdcard en la tarjeta SD.
/ su superusuario. Muestra opciones adicionales.
/ Pachube muestra la actividad Pachube por zona / Datastream.
/ sobre los créditos de aplicación y versión.
/ delete-confirmar ¿Eliminar último archivo en la tarjeta SD [Ventana de confirmación].
/ delete-última Borrar el último archivo en la tarjeta SD [ninguna ventana de confirmación].
/ diagnóstico por ahora, muestra la memoria disponible en Netduino y las fuerzas para despejar el recolector de basura.
Código
Archivo config.ini debe copiarse en el directorio raíz de la tarjeta SD. La finalidad de este fichero es la de personalizar los parámetros en la tarjeta SD y evitar una mínima modificación del código fuente. Archivos CSS (header_style.css y table_style.css) deben ubicarse en WebResources carpeta.

 

microSD directory structure

Config.ini content:

01 ;AlarmByZones - Programmed for Netduino by Gilberto García - 5/9/2012 
02 ;Feel free to customize this file with your own definitions. 
03 ;[NETDUINO_PLUS_HTTP_PORT] HTTP server port. 
04 ;[ALARM_ZONES] should match with ACTIVE_ZONES constant defined in AlarmByZones.cs and Definitions.cs . 
05 ;[SENSORS] should match with MOTION_SENSORS constant defined in AlarmByZones.cs and Definitions.cs . 
06 ;[USE_EMAIL] Activate/Deactivate email option. Y or N arguments expected. 
07 ;[EMAIL_FREQ] Email frequency in minutes when the alarm/sensor is active.  
08 ;       This will define EMAIL_FREQUENCY in ConfigDefault.cs . 
09 ;[STORE_LOG] Saves alarm/sensor log. Y or N arguments expected. 
10 ;[STORE_EXCEPTION] Saves Netduino exceptions. Y or N arguments expected. 
11 ;[USE_PACHUBE] Activate/Deactivate Pachube option. Y or N arguments expected. 
12
13
14
15 [NETDUINO_PLUS_HTTP_PORT] 
16 8080 
17 [ALARM_ZONES] 
18 Zone1=FIRST FLOOR - Living room windows, Dining room windows, Porch (sliding doors), Garage door access. 
19 Zone2=SECOND FLOOR - Master Bedroom and Bathroom Windows. 
20 Zone3=FIRST FLOOR - Master Bedroom windows. 
21 Zone4=SECOND FLOOR - Bedroom 2 and bathroom windows. 
22 [SENSORS] 
23 Sensor1=Main door access 
24 [USE_EMAIL] 
25
26 [EMAIL_FREQ] 
27 10 
28 [STORE_LOG] 
29
30 [STORE_EXCEPTION] 
31
32 [USE_PACHUBE] 
33

 

Architecture of AlarmByZones (main)

Declaration

01 /// <summary> 
02  /// Alarm zones (Analog Input) 
03  /// </summary> 
04  static SecretLabs.NETMF.Hardware.AnalogInput[] Zones = newSecretLabs.NETMF.Hardware.AnalogInput[Alarm.User_Definitions.Constants.ACTIVE_ZONES]; 
05  /// <summary> 
06  /// Alarm zones LEDs (Digital Output) 
07  /// </summary> 
08  static Microsoft.SPOT.Hardware.OutputPort[] AlarmLeds = newMicrosoft.SPOT.Hardware.OutputPort[Alarm.User_Definitions.Constants.ACTIVE_ZONES]; 
09  /// <summary> 
10  /// Motion detector sensors (Analog Input) 
11  /// </summary> 
12  static SecretLabs.NETMF.Hardware.AnalogInput[] Sensors = newSecretLabs.NETMF.Hardware.AnalogInput[Alarm.User_Definitions.Constants.MOTION_SENSORS]; 
13  /// <summary> 
14  /// Motion detector LEDs (Digital Output) 
15  /// </summary> 
16  static Microsoft.SPOT.Hardware.OutputPort[] MotionLeds = newMicrosoft.SPOT.Hardware.OutputPort[Alarm.User_Definitions.Constants.MOTION_SENSORS]; 
17  /// <summary> 
18  /// Gets the total elapsed time measured by the current instance of each alarm zone. 
19  /// </summary> 
20  static System.Diagnostics.Stopwatch[] stopwatchZones = newStopwatch[Alarm.User_Definitions.Constants.ACTIVE_ZONES]; 
21  /// <summary> 
22  /// Gets the total elapsed time measured by the current instance of each motion detector sensor. 
23  /// </summary> 
24  static System.Diagnostics.Stopwatch[] stopwatchSensors = newStopwatch[Alarm.User_Definitions.Constants.MOTION_SENSORS]; 
25  /// <summary> 
26  /// Flag for detected zones when trigger. 
27  /// </summary> 
28  static bool[] detectedZones = newbool[Alarm.User_Definitions.Constants.ACTIVE_ZONES]; 
29  /// <summary> 
30  /// Flag for detected sensors when is trigger. 
31  /// </summary> 
32  static bool[] detectedSensors = newbool[Alarm.User_Definitions.Constants.MOTION_SENSORS]; 
33  /// <summary> 
34  /// Email 
35  /// </summary>    
36  /// <example> SMTPClient.Email("mail.gmx.com", 587, "[email protected]", "[email protected]", "user password");  
37  /// </example> 
38  static SMTPClient.Email email = newSMTPClient.Email(Alarm.UserData.Email.host, Alarm.UserData.Email.port, 
39    Alarm.UserData.Email.From, Alarm.UserData.Email.To, Alarm.UserData.Email.smtpPassword); 
40  /// <summary> 
41  /// SD Card Event Logger 
42  /// </summary> 
43  public static EventLogger SdCardEventLogger = newEventLogger(); 

Delegates 

1 /// <summary> 
2 /// Monitor zones delegate 
3 /// </summary> 
4 public delegate void MonitorZonesDelegate(); 
5 /// <summary> 
6 /// Monitor motion sensor delegate 
7 /// </summary> 
8 public delegate void MonitorMotionSensorDelegate(); 

Main 

01 public static void Main() 
02
03   Zones[0] = newSecretLabs.NETMF.Hardware.AnalogInput(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_A0); 
04   Zones[1] = newSecretLabs.NETMF.Hardware.AnalogInput(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_A1); 
05   Zones[2] = newSecretLabs.NETMF.Hardware.AnalogInput(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_A2); 
06   Zones[3] = newSecretLabs.NETMF.Hardware.AnalogInput(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_A3); 
07   AlarmLeds[0] = newMicrosoft.SPOT.Hardware.OutputPort(Pins.GPIO_PIN_D2,false);       
08   AlarmLeds[1] = newMicrosoft.SPOT.Hardware.OutputPort(Pins.GPIO_PIN_D3, false); 
09   AlarmLeds[2] = newMicrosoft.SPOT.Hardware.OutputPort(Pins.GPIO_PIN_D4, false); 
10   AlarmLeds[3] = newMicrosoft.SPOT.Hardware.OutputPort(Pins.GPIO_PIN_D5, false); 
11   Sensors[0] = newSecretLabs.NETMF.Hardware.AnalogInput(SecretLabs.NETMF.Hardware.NetduinoPlus.Pins.GPIO_PIN_A4); 
12   MotionLeds[0] = newMicrosoft.SPOT.Hardware.OutputPort(Pins.GPIO_PIN_D7, false); 
13   MonitorZonesDelegate monitorZones = newMonitorZonesDelegate(MonitorZones); 
14   MonitorMotionSensorDelegate monitorMotion = newMonitorMotionSensorDelegate(MonitorSensors); 
15   //based on a post by Valkyrie-MT 
17   Console.DEBUG_ACTIVITY("Setting NTP-time"); 
18   SetTime(); 
19   SdCardEventLogger.parseConfigFileContents(Alarm.User_Definitions.Constants.ALARM_CONFIG_FILE_PATH); 
20   InitArrays(); 
21   Console.DEBUG_ACTIVITY(Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].IPAddress); 
22   SdCardEventLogger.SDCardAccess(); 
23   new Thread(Alarm.ProtoScrewShield_LED.Blink).Start();       
24   new Thread(Alarm.WebServer.startHttp).Start(); 
25   if (Alarm.ConfigDefault.Data.USE_PACHUBE) 
26   
27     Pachube.PachubeLibrary.InitPachubleLibrary(SdCardEventLogger.IsSDCardAvailable(), Alarm.ConfigDefault.Data.STORE_EXCEPTION); 
28     new Thread(Pachube.PachubeLibrary.PachubeConnect).Start(); 
29   
30   while (true
31   
32     Debug.Print("Memory available: " + Debug.GC(true)); 
33     monitorZones(); 
34     monitorMotion(); 
35     Thread.Sleep(Alarm.Common.Alarm_Constants.ALARM_DELAY_TIME); 
36   
37

Main Methods 

001 /// <summary> 
002 /// Loops thru each alarm zone 
003 /// </summary> 
004 static void MonitorZones() 
005
006   for (int i = 0; i < Zones.Length; i++) 
007   
008     int vInput = Zones[i].Read(); 
009     float volts = ((float)vInput / 1024.0f) * 3.3f; 
010     string strZoneDescription = "N/A"//If zone description is not found on SD Card N/A is default description. 
011     Console.DEBUG_ACTIVITY("Zone " + (i + 1).ToString() + ": Volts: " + volts); 
012     //format:                //Zone number, voltage 
013     Pachube.PachubeLibrary.statusToPachube = i == 0 ? (i + 1).ToString() + "," + volts : (i + 1).ToString() + "," + volts +"\r\n" + Pachube.PachubeLibrary.statusToPachube; 
014     AlarmLeds[i].Write(volts >= 3); 
015     //elapsed seconds 
016     double eSeconds = stopwatchZones[i].ElapsedSeconds; 
017     //elapsed minutes 
018     double eMinutes = stopwatchZones[i].ElapsedMinutes; 
019     Console.DEBUG_ACTIVITY("stopwatch[" + i.ToString() + "] = " + eSeconds.ToString() + " seconds"); 
020     Console.DEBUG_ACTIVITY("stopwatch[" + i.ToString() + "] = " + eMinutes.ToString() + " minutes\n"); 
021     if (volts >= 3 ) 
022     
023       /* 
024        Case #1: 
025         !detectedZones[i] = not triggered before. This is the first time in this cycle and first email to send. 
026        Case #2: 
027         detectedZones[i] && eMinutes >= EMAIL_FREQUENCY = triggered before and time is up for sending another email.            
028        */
029       if (!detectedZones[i] || (detectedZones[i] && eMinutes >= Alarm.ConfigDefault.Data.EMAIL_FREQUENCY)) 
030       
031         if (Alarm.Common.Alarm_Info.zoneDescription.Count>0) 
032         
033           if(Alarm.Common.Alarm_Info.zoneDescription.Contains("Zone" + (i + 1).ToString())) 
034           
035             strZoneDescription = (string)Alarm.Common.Alarm_Info.zoneDescription["Zone" + (i + 1).ToString()]; 
036           
037         
038         string info = "Zone " + (i + 1).ToString() + " " + strZoneDescription; 
039         stopwatchZones[i] = Stopwatch.StartNew(); 
040         detectedZones[i] = true
041         email.SendEmail("Alarm Trigger!", info); 
042         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<tr>");
043         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center>" + DateTime.Now.ToString() + "</center></td> ");
044         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center> Zone " + (i + 1).ToString() + "</center></td>");
045         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center>" + strZoneDescription + "</center></td>");
046         Alarm.Common.Alarm_Info.sbActivity.AppendLine("</tr>");             if (Alarm.ConfigDefault.Data.USE_PACHUBE) 
047         
048           //supress timer and update Pachube with new status 
049           Pachube.PachubeLibrary.forceUpdate = true
050         
051         if (SdCardEventLogger.IsSDCardAvailable() && Alarm.ConfigDefault.Data.STORE_LOG) 
052         
053           SdCardEventLogger.saveFile(DateTime.Now.ToString("d_MMM_yyyy--HH_mm_ss") + ".log", info, "Log"); 
054         
055       
056     
057     else
058     
059       detectedZones[i] = false
060     
061   
062
063 /// <summary> 
064 /// Loops thru each sensor 
065 /// </summary> 
066 static void MonitorSensors() 
067 {   
068   for (int i = 0; i < Sensors.Length; i++) 
069   
070     int vInput = Sensors[i].Read(); 
071     float volts = ((float)vInput / 1024.0f) * 3.3f; 
072     string strSensorDescription = "N/A"//If sensor description is not found on SD Card N/A is default description. 
073     Console.DEBUG_ACTIVITY("Sensor " + (i + 1).ToString() + ": Volts: " + volts); 
074     MotionLeds[i].Write(volts >= 3); 
075     double eSeconds = stopwatchSensors[i].ElapsedSeconds; 
076     double eMinutes = stopwatchSensors[i].ElapsedMinutes; 
077     Console.DEBUG_ACTIVITY("stopwatch[" + i.ToString() + "] = " + eSeconds.ToString() + " seconds"); 
078     Console.DEBUG_ACTIVITY("stopwatch[" + i.ToString() + "] = " + eMinutes.ToString() + " minutes\n"); 
079     if (volts >= 3) 
080     
081       /* 
082        Case #1: 
083         !detectedZones[i] = not triggered before. This is the first time in this cycle and first email to send. 
084        Case #2: 
085         detectedZones[i] && eMinutes >= EMAIL_FREQUENCY = triggered before and time is up for sending another email.            
086        */
087       if (!detectedSensors[i] || (detectedSensors[i] && eMinutes >= Alarm.ConfigDefault.Data.EMAIL_FREQUENCY)) 
088       
089         if (Alarm.Common.Alarm_Info.sensorDescription.Count > 0) 
090         
091           if(Alarm.Common.Alarm_Info.sensorDescription.Contains("Sensor" + (i + 1).ToString())) 
092           
093             strSensorDescription = (string)Alarm.Common.Alarm_Info.sensorDescription["Sensor" + (i + 1).ToString()]; 
094           
095         
096         string info = "Sensor " + (i + 1).ToString() + " " + strSensorDescription; 
097         stopwatchSensors[i] = Stopwatch.StartNew(); 
098         detectedSensors[i] = true
099         email.SendEmail("Alarm Trigger!", info); 
100         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<tr>");
101         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center>" + DateTime.Now.ToString() + "</center></td> ");
102         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center> Sensor " + (i + 1).ToString() + "</center></td>");
103         Alarm.Common.Alarm_Info.sbActivity.AppendLine("<td><center>" + strSensorDescription + "</center></td>");
104         Alarm.Common.Alarm_Info.sbActivity.AppendLine("</tr>"); 
105         if (Alarm.ConfigDefault.Data.USE_PACHUBE) 
106         
107           //supress timer and update Pachube with new status 
108           Pachube.PachubeLibrary.forceUpdate = true
109         
110         if (SdCardEventLogger.IsSDCardAvailable() && Alarm.ConfigDefault.Data.STORE_LOG) 
111         
112           SdCardEventLogger.saveFile(DateTime.Now.ToString("d_MMM_yyyy--HH_mm_ss") + ".log", info, "Log"); 
113         
114       
115     
116     else
117     
118       detectedSensors[i] = false
119     
120   
121
122 /// <summary> 
123 /// Synchronize Netduino time with NTP Server 
124 /// </summary> 
125 public static void SetTime() 
126
128   Extension.SetFromNetwork(DateTime.Now, new TimeSpan(-5, 0, 0)); 
129
130 /// <summary> 
131 /// Initializes stopwatch and alarms/sensors arrays 
132 /// </summary> 
133 private static void InitArrays() 
134
135   for (int i = 0; i < Alarm.User_Definitions.Constants.ACTIVE_ZONES; i++) 
136   
137     stopwatchZones[i] = Stopwatch.StartNew(); 
138     detectedZones[i] = false
139   
140   for (int i = 0; i < Alarm.User_Definitions.Constants.MOTION_SENSORS; i++) 
141   
142     stopwatchSensors[i] = Stopwatch.StartNew(); 
143     detectedSensors[i] = false
144   
145

 

Cosm, formerly Pachube, Alarm Console

Final Product

LCD and WiFi Internet Adapter
Alarm Panel with Netduino Plus, LCD and WiFi Internet Adapter

 

Comentarios comunidad Netduino

http://forums.netduino.com/index.php?/topic/4202-home-alarm-system-using-netduino-plus-homealarmplus-project/

Repositorio código fuente
https://github.com/ferraripr/HomeAlarmPlus

Video

YouTube video

Fuente Gilberto García