|
@ -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 <UIPEthernet.h>
|
|
|
|
|
|
//#include <EEPROM.h>
|
|
|
|
|
|
|
|
|
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 <SPI.h>
|
|
|
|
|
|
#include <UIPEthernet.h>
|
|
|
|
|
|
|
|
|
#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 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 ZMTRIGGERPORT 6802
|
|
|
#define LISTENPORT 80 // (port 80 is default for HTTP)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************Pins***************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EthernetClient client; |
|
|
|
|
|
|
|
|
//Digital
|
|
|
|
|
|
|
|
|
//IO
|
|
|
#define MODECTPIN 8
|
|
|
#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; |
|
|
uint8_t AlarmActive = 0; |
|
|
char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data
|
|
|
char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data
|
|
|
uint8_t TEMPERATUREVALUE = 0; |
|
|
uint8_t TEMPERATUREVALUE = 0; |
|
|
uint8_t TEMPERATUREVALUE2 = 0; |
|
|
uint8_t TEMPERATUREVALUE2 = 0; |
|
|
uint8_t SOUNDVALUE = 0; |
|
|
|
|
|
uint16_t MODECTVALUE = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
ZMTrigger Command to Send |
|
|
|
|
|
|
|
|
|
|
|
B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext> |
|
|
|
|
|
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; |
|
|
uint8_t first_interrupt = 0; |
|
|
|
|
|
|
|
|
//timer for debounce
|
|
|
|
|
|
|
|
|
//for debounce
|
|
|
ISR(TIMER1_OVF_vect){ |
|
|
ISR(TIMER1_OVF_vect){ |
|
|
timer1++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
timer1++; |
|
|
if (first_interrupt == 1 ){ |
|
|
if (first_interrupt == 1 ){ |
|
|
debouncetime++; |
|
|
debouncetime++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (debouncetime > 2) { |
|
|
if (debouncetime > 2) { |
|
|
first_interrupt = 0; |
|
|
first_interrupt = 0; |
|
|
debouncetime = 0; |
|
|
debouncetime = 0; |
|
|
AlarmActive = 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)
|
|
|
//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; |
|
|
TCCR1B = 0; |
|
|
|
|
|
|
|
|
// Set timer1_counter to the correct value for our interrupt interval
|
|
|
// 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
|
|
|
TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html
|
|
|
// search tccr1b
|
|
|
// search tccr1b
|
|
|
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
|
|
|
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
|
|
|
//end timer1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sei(); //timer needs interrupts, enable (set) interrupts
|
|
|
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); |
|
|
delay(10); |
|
|
MODECTVALUE = digitalRead(MODECTPIN); |
|
|
MODECTVALUE = digitalRead(MODECTPIN); |
|
|
delay(10); |
|
|
delay(10); |
|
|
Serial.print(F("Motion Detector Value (normal): ")); |
|
|
|
|
|
|
|
|
//Serial.print(F("Motion Detector Value (normal): "));
|
|
|
//Serial.println(String(MODECTVALUE));
|
|
|
//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;
|
|
|
//firstpacketsend = 0;
|
|
|
|
|
|
|
|
|
cli(); |
|
|
cli(); |
|
|
//some of this may be redundant, need to check
|
|
|
//some of this may be redundant, need to check
|
|
|
AlarmActive = 1; |
|
|
AlarmActive = 1; |
|
@ -333,141 +141,102 @@ void loop() |
|
|
debouncetime = 0; |
|
|
debouncetime = 0; |
|
|
sei(); |
|
|
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
|
|
|
// listen for incoming clients
|
|
|
EthernetClient client = server2.available(); |
|
|
|
|
|
|
|
|
EthernetClient client = serverHOST.available(); |
|
|
if (client) { |
|
|
if (client) { |
|
|
Serial.println(F("web visitor")); |
|
|
|
|
|
|
|
|
Serial.println("new client"); |
|
|
// an http request ends with a blank line
|
|
|
// an http request ends with a blank line
|
|
|
boolean currentLineIsBlank = true; |
|
|
boolean currentLineIsBlank = true; |
|
|
while (client.connected()) { |
|
|
while (client.connected()) { |
|
@ -478,7 +247,7 @@ void loop() |
|
|
// character) and the line is blank, the http request has ended,
|
|
|
// character) and the line is blank, the http request has ended,
|
|
|
// so you can send a reply
|
|
|
// so you can send a reply
|
|
|
if (c == '\n' && currentLineIsBlank) { |
|
|
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("HTTP/1.1 200 OK"); |
|
|
client.println("Content-Type: text/html"); |
|
|
client.println("Content-Type: text/html"); |
|
|
//client.println("Connection: close"); // the connection will be closed after completion of the response
|
|
|
//client.println("Connection: close"); // the connection will be closed after completion of the response
|
|
@ -487,10 +256,8 @@ void loop() |
|
|
client.println("<!DOCTYPE HTML>"); |
|
|
client.println("<!DOCTYPE HTML>"); |
|
|
client.println("<html><pre>"); |
|
|
client.println("<html><pre>"); |
|
|
client.println("<b>Steak Electronics</b>"); |
|
|
client.println("<b>Steak Electronics</b>"); |
|
|
client.println("\"Steak it easy... That is, don't overcook steak\""); |
|
|
|
|
|
|
|
|
client.println("\"Eat Steak, Use Birth Control\""); |
|
|
client.println(""); |
|
|
client.println(""); |
|
|
//client.println("<b>IP Address:</b>");
|
|
|
|
|
|
//client.println(Ethernet.localIP());
|
|
|
|
|
|
client.print("Sensor Location:"); |
|
|
client.print("Sensor Location:"); |
|
|
client.println(LOCATIONOFSENSOR); |
|
|
client.println(LOCATIONOFSENSOR); |
|
|
client.print("Type::"); |
|
|
client.print("Type::"); |
|
@ -515,19 +282,26 @@ void loop() |
|
|
delay(1); |
|
|
delay(1); |
|
|
// close the connection:
|
|
|
// close the connection:
|
|
|
client.stop(); |
|
|
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<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext> |
|
|
|
|
|
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. |
|
|
|
|
|
|
|
|
|
|
|
*/ |