diff --git a/ZMHW_Modector/ZMHW_Modector.ino b/ZMHW_Modector/ZMHW_Modector.ino index f526b16..d56a547 100644 --- a/ZMHW_Modector/ZMHW_Modector.ino +++ b/ZMHW_Modector/ZMHW_Modector.ino @@ -1,233 +1,107 @@ /* + * ZMHW Modector * - * ZoneMinder Hardware Project - * + * Digital High outputs TCP Packet to ZMTrigger + * Steak Electronics Company 2019 * * - * A sensor on an Arduino UNO communicating - * via ethernet to ZMTrigger daemon for ZoneMinder - * CCTV GNU/Linux software. - * - * - */ - - -/* - * What it does: - * Works with accompanying shield to act as motion sensor - * for Zoneminder via ZMTrigger. Shield is optional but recommended - * as it's easier to build. - * - * Components: - * ENC28J60 - * Motion Sensor (Either PIR, or microwave HFS-DC06H) - * Microphone for Loud Noise alarms - * LM35 Temperature Sensor - * RGB Status LED - * Speaker - * - * Power from External 12V supply, not USB!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * */ /* - * - * - * - * Directions: - * Use Arduino Uno - * See https://git.steakelectronics.com/adminguy/ZMHW_Project_InfraredDiodeSensor - * - * Connect ENC28J60 using these instructions: - * https://github.com/ntruchsess/arduino_uip - * http://web.archive.org/save/https://create.arduino.cc/projecthub/Sourcery/how-to-connect-the-enc28j60-to-an-arduino-efd0dd - * CS for ENC and UIP library is 10 by default on UNO. Not 8, like that link says. - * - * - * - * - * - */ +Same as default library but uses UIPEthernet. Requires UIPEthernet. +Manage Libraries - Download UIP Ethernet library +*/ +/* + Web Server -#include -//#include + A simple web server that shows the value of the analog input pins. + using an Arduino Wiznet Ethernet shield. + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 02 Sept 2015 + by Arturo Guadalupi + */ -//Edit the below values +#include +#include -#define DEBUGMODE 0 // 1 == on. 0 == off. -#define MIC 0 // "" -#define SICK 0 // set to 1 if using sick sensor (on analog pin) - // sick sensor is a transistor activated photoelectric - // sensor. More details in docs, and below. #define NORMALMODECT 1 // For a digital High motion sensor. +#define TWOSERVERS 1 -/***************Ethernet ENC28J60***************/ - -//Mac must be unique for each sensor -byte mac[] = { 0xD3, 0x5D, 0xBE, 0xEF, 0xEE, 0x52 }; -//Static IP of Arduino -byte ip[] = { 192, 168, 78, 52 }; -//IP of ZM Server -byte server[] = { 192, 168, 78, 123 }; -//ZM server IP to put in requests. -String host="192.168.78.123"; - -char* monnum = "14"; //monitor number - -char* LOCATIONOFSENSOR = "Bay 1"; +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x50 +}; +IPAddress ip(192, 168, 1, 50); +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +#define LISTENPORT 80 +EthernetServer serverHOST(LISTENPORT); + + +//Client +byte server[] = { 192, 168, 1, 115 }; +//byte serverB[] = { 192, 168, 1, 116 }; //can't be server2, as that is already set for ethernetserver below +String host="192.168.1.115"; +char* monnum = "32"; //monitor number +char* LOCATIONOFSENSOR = "FtLab"; #define ZMTRIGGERPORT 6802 -#define LISTENPORT 80 // (port 80 is default for HTTP) - - - - -/***************Pins***************/ - +EthernetClient client; -//Digital +//IO #define MODECTPIN 8 -#define SPEAKERPIN 6 -#define LEDPIN 9 - - - -//Analog -#define TEMPPIN A0 -#define SICKPIN A1 -#define MICROPHONEPIN A2 - - - - - -/***************Variables************/ - +//GLOBALS uint8_t AlarmActive = 0; char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data uint8_t TEMPERATUREVALUE = 0; uint8_t TEMPERATUREVALUE2 = 0; -uint8_t SOUNDVALUE = 0; -uint16_t MODECTVALUE = 0; - - -/* - ZMTrigger Command to Send - -B|B|B|B|B|B -which in this code is: -monnum | onoff + timealarm | score | source - -e.g. -2|on+5|100|ZoneAVR|| - -This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100 -and the source of ZoneAVR. The text field, and show text are not setup here. - -*/ - - -char* onoff = "on"; //command to send to zmtrigger. -char* timealarm = "10"; //time to set monitor to alarm -char* score = "77"; //score to assign -char* source = "ZMHW"; //source. Add details as needed (e.g. Hallway sensor) - - - - -//Do not need to edit below - - - - - -// Initialize the Ethernet server library - - -EthernetClient client; -EthernetServer server2 = EthernetServer(LISTENPORT); - -/* -void chime(int freq){ - tone(SPEAKERPIN, freq, 50); - delay(50); -} - -void chimefast(int freq, int fast){ - tone(SPEAKERPIN, freq, fast); - delay(fast); -}*/ - -//timer/interrupt -uint16_t timer1; -uint16_t timer1_counter; -uint8_t debouncetime; +uint8_t MODECTVALUE = 0; +char* onoff = "on"; //command to send to zmtrigger. +char* timealarm = "10"; //time to set monitor to alarm +char* score = "77"; //score to assign +char* source = "ZMHW";//source. Add details as needed (e.g. Hallway sensor) +uint8_t ActivateServer2 = 0; + +//Interrupt / Timer +uint16_t timer1 = 0; +uint16_t timer1_counter = 0; +uint8_t debouncetime = 0; uint8_t first_interrupt = 0; -//timer for debounce +//for debounce ISR(TIMER1_OVF_vect){ - timer1++; - + timer1++; if (first_interrupt == 1 ){ debouncetime++; } - if (debouncetime > 2) { first_interrupt = 0; debouncetime = 0; AlarmActive = 0; } - -} - - - -void setup() -{ - - Serial.begin(9600); - Serial.println(F("ZMHW Project")); - Serial.println(F("Motion Sensor")); - - //if sick - pinMode(SICKPIN, INPUT); - //if mic - pinMode(MICROPHONEPIN, INPUT); - //if speaker - pinMode(SPEAKERPIN, OUTPUT); - pinMode(MODECTPIN, INPUT); - pinMode(TEMPPIN, INPUT); + } - //Be careful. This sets Areg to 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - //Used for LM35. - analogReference(INTERNAL); - - - - Ethernet.begin(mac, ip); - server2.begin(); - Serial.print(F("server is at ")); - Serial.println(Ethernet.localIP()); - - - - //timer 1, setup +void TimerInit(void){ //Crystal of Uno is == Mega (16MHz) - - - //this timer is all bodged up, but doesn't matter, as we only - //need two or three counts between alarms. Not going to fix atm. - //and it works. + //this timer init is flawed, but doesn't matter, as we only + //need two or three counts between alarms. TODO: clean up - //Clear existing registers - TCCR1A = 0; + TCCR1A = 0; //Clear existing registers TCCR1B = 0; // Set timer1_counter to the correct value for our interrupt interval @@ -238,94 +112,28 @@ void setup() TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html // search tccr1b TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged) - //end timer1 - - - sei(); //timer needs interrupts, enable (set) interrupts - - //tone(SPEAKERPIN, 1000, 200); - //delay(100); - //tone(SPEAKERPIN, 2000, 200); - //delay(100); - //tone(SPEAKERPIN, 2200, 200); - //delay(100); } - - -void loop() -{ - //delay(50); - - - -/*****************ANALOG SECTION******************/ - - //The SICK infrared laser requires a transistor to output - //high or low, but we will cheat and instead, put it through - //a serial diode, and then use the ADC instead of a digital pin - //saves a few seconds to put a diode on the end instead of transistor - //when soldering by hand. Works equally as well. Requires ADC pin. - -/* - if (SICK){ - MotionSensorRead = analogRead(SICKPIN); - Serial.print("Motion Sensor Value: "); - Serial.println(String(MotionSensorRead)); - //Serial.println(String(timer1)); - delay(30); - } -*/ - - - //todo: only serial.print temp every 10 or so reads - TEMPERATUREVALUE = analogRead(TEMPPIN); - Serial.print(F("Temperature Value: ")); - // See resources. uses 1.1 aref, converts to celcius, then to Fareinheit. - TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30; - Serial.println(String(TEMPERATUREVALUE2)); - delay(30); - -/* - if (MIC){ - SOUNDVALUE = analogRead(MICROPHONEPIN); - Serial.print("Sound Value: "); - Serial.println(String(SOUNDVALUE)); - delay(30); - } -*/ - if (NORMALMODECT){ +void ReadModect(void){ + if (NORMALMODECT){ delay(10); MODECTVALUE = digitalRead(MODECTPIN); delay(10); - Serial.print(F("Motion Detector Value (normal): ")); + //Serial.print(F("Motion Detector Value (normal): ")); //Serial.println(String(MODECTVALUE)); - Serial.println(MODECTVALUE); - delay(30); + //Serial.println(MODECTVALUE); + delay(30); } +} - - if(DEBUGMODE){ - delay(10); - } - - - - -/****************MOTION SENSING****************/ - - - - //SICK - //Motion sensing for Sick Photoelectric sensor only - //upon boot, values are around 400 sometimes, so only alert at higher - if(SICK){ - if (MODECTVALUE > 500 && AlarmActive == 0){ - Serial.println(F("Motion Detected on Sick")); - +void DigiModectChkandSend(void){ + //Digital High Motion Sensor + if(NORMALMODECT){ + + if (MODECTVALUE==HIGH && AlarmActive == 0){ + Serial.println(F("Motion Detected on Normal Sensor")); //firstpacketsend = 0; - cli(); //some of this may be redundant, need to check AlarmActive = 1; @@ -333,141 +141,102 @@ void loop() debouncetime = 0; sei(); - //Want the chime to be only noticeable if you know what to listen - //for. Make it a high freq. sound that is easy to miss. - //Resistors to speaker should be high - //chime(13000); - - - Serial.println("Connecting..."); + delay(10); + Serial.println(F("Connecting To Cam Srv")); + if (client.connect(server, ZMTRIGGERPORT)) { + //beware that the buffer in snprintf is big enough to hold everything + snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source); + Serial.print(F("the TCP Packet being sent:")); + Serial.println(String(ZMTriggerMessage)); + client.println(String(ZMTriggerMessage)); //required + Serial.println(F("TCP packet sent to ZMTrigger")); + client.stop(); + if(TWOSERVERS){ + ActivateServer2 = 1; + } + } + else { + //NOTE: If you are not connected to the network + //the device will currently freeze up, and not timeout. + //Need to implement a watchdog. + //If you ARE connected to the network, and server is not available + //then it will timeout. + Serial.println(F("Connection to Server failed")); + } + } + } +} +void SendtoServer2(void){ + server[0] = 192; + server[1] = 168; + server[2] = 1; + server[3] = 116; + host="192.168.1.116"; + delay(10); + Serial.println(F("Connecting To Cam Srv")); + if (client.connect(server, ZMTRIGGERPORT)) { + client.println(String(ZMTriggerMessage)); //required + Serial.println(F("TCP packet sent to Server Two ZMTrigger")); + client.stop(); + } + server[0] = 192; + server[1] = 168; + server[2] = 1; + server[3] = 115; + host="192.168.1.115"; + ActivateServer2 = 0; +} - if (client.connect(server, ZMTRIGGERPORT)) { - //chime(13000); - - //beware that the buffer in snprintf is big enough to hold everything - snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source); - Serial.print(F("the TCP Packet being sent:")); - //Serial.println(String(ZMTriggerMessage)); - client.println(String(ZMTriggerMessage)); //required - Serial.println(F("TCP packet sent to ZMTrigger")); - client.stop(); - } - else { - //NOTE: If you are not connected to the network - //the device will currently freeze up, and not timeout. - //Need to implement a watchdog. - //If you ARE connected to the network, and server is not available - //then it will timeout. - - Serial.println(F("Connection to ZM Server failed")); - - - /*chime(50); - delay(100); - chime(50); - delay(100); - chime(50); - delay(100); - */ - } +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only } - }//end sick - - + Serial.println(F("ZMHW Project")); + Serial.println(F("Motion Sensor")); + // start the Ethernet connection and the server: + Ethernet.begin(mac, ip); + serverHOST.begin(); + Serial.print(F("server is at ")); + Serial.println(Ethernet.localIP()); - //Digital High Motion Sensor - if(NORMALMODECT){ - - if (MODECTVALUE==HIGH && AlarmActive == 0){ - Serial.println(F("Motion Detected on Normal Sensor")); + pinMode(MODECTPIN, INPUT); - //firstpacketsend = 0; + TimerInit(); +} - cli(); - //some of this may be redundant, need to check - AlarmActive = 1; - first_interrupt = 1; - debouncetime = 0; - sei(); - //Want the chime to be only noticeable if you know what to listen - //for. Make it a high freq. sound that is easy to miss. - //Resistors to speaker should be high - //chime(13000); - delay(10); +void loop() { - - Serial.println(F("Connecting...")); +ReadModect(); +DigiModectChkandSend(); +if(TWOSERVERS && ActivateServer2){ + SendtoServer2(); +} - if (client.connect(server, ZMTRIGGERPORT)) { - //chime(13000); - //delay(10); - - //beware that the buffer in snprintf is big enough to hold everything - snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source); - Serial.print(F("the TCP Packet being sent:")); - Serial.println(String(ZMTriggerMessage)); - client.println(String(ZMTriggerMessage)); //required - Serial.println(F("TCP packet sent to ZMTrigger")); - client.stop(); - } - else { - //NOTE: If you are not connected to the network - //the device will currently freeze up, and not timeout. - //Need to implement a watchdog. - //If you ARE connected to the network, and server is not available - //then it will timeout. - - Serial.println(F("Connection to ZM Server failed")); - - /* chime(40); - delay(100); - chime(60); - delay(100); - chime(60); - delay(100); - */ - } - } - MODECTVALUE=LOW; - }//end normal Motion Sensor - - - //disconnect - if (!client.connected()) { - client.stop(); - - } -/********************SERVER STATUS PAGE*********************/ -/* - * With this, you can logon to the Sensor from your LAN to find - * out just what device this IP address is, in case you happen to - * forget. We can also pull the temperature from this page, and - * populate it to the camera feed, via ZMTrigger, from a server - * side wget. - */ - //Serve Status Page + // listen for incoming clients - EthernetClient client = server2.available(); + EthernetClient client = serverHOST.available(); if (client) { - Serial.println(F("web visitor")); + Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { @@ -478,7 +247,7 @@ void loop() // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { - // send a standard http response header + // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); //client.println("Connection: close"); // the connection will be closed after completion of the response @@ -487,10 +256,8 @@ void loop() client.println(""); client.println("
");
           client.println("Steak Electronics");
-          client.println("\"Steak it easy... That is, don't overcook steak\"");
+          client.println("\"Eat Steak, Use Birth Control\"");
           client.println("");
-          //client.println("IP Address:");
-          //client.println(Ethernet.localIP());
           client.print("Sensor Location:");
           client.println(LOCATIONOFSENSOR);
           client.print("Type::");
@@ -515,19 +282,26 @@ void loop()
     delay(1);
     // close the connection:
     client.stop();
-    Serial.println(F("client disconnected"));
+    Serial.println("client disconnected");
   }
+}
 
 
 
 
-        
-          //write to eeprom if connection failed, and try again upon reboot
-          //EEPROM.write(EEPROM_RETRY, switch_pressed);
-      
-      
 
 
+/*
+        ZMTrigger Command to Send
 
-    
-} //end main loop
+B|B|B|B|B|B
+which in this code is:
+monnum | onoff + timealarm | score | source
+
+e.g.
+2|on+5|100|ZoneAVR||
+
+This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100
+and the source of ZoneAVR. The text field, and show text are not setup here.
+
+*/