Home Intelligent Management System “iHome”

Home Intelligent Management System “iHome”

Welcome to  my intelligent “iHome”  smart devices and home automation system  page!

Few words about what “iHome” system is and it’s principles of work:

System consist of:

  • Main Control Unit (MCU), which is designed to be integrated into main distribution board at your home.
  • Remote control units (RCU), developed to control  electronic devices at certain distance (depend on which of 2 radios used) such as: automatic curtains, light switches, level sensors, heaters, pumps e.t.c.

MCU built on a modular basis, where main processing done by famous Arduino MEGA 2560 platform. Additional modules facilitated on the board, such as:

  1. SIM800L GSM communication module  – provides “iHome” system control over GSM network by voice and SMS messaging.
  2. HC-12 Long distance radio communication module – provides  communication with remote devices  through “iHome” protocol on variable frequencies.
  3. RXB12 433.92Mhz radio communication module – built on quality heterodyne principle with quality interference filters provides  fixed and rolling code communication with burglar alarm sensors and entrance access.
  4. W5100 Network module – LAN connection, internet access and web based control interface.

All this modules will be installed on Arduino Megashield which is on final stage of development. Real scale model of the MEGASHIELD mainboard PCB  shown on the pictures below:

 

My smarthouse philosophy.

By building smarthouse project I aim to achieve number of goals:

  1. Home Security.
  2. Environmentally friendly and economic living,
  3. Comfort and intelligent.

By using hardware, widely available  on the market  and  with certain knowledge of programming, integrating number of electronic devices, applying control algorithms and communication protocols I’ve achieved this within one simple device, sized regular school exercise book.

Modular design provides versatility of the device, it’s abilities and functionality. Adding and removing modules are very simple and does not require special knowledge. Mainboard comes with 6 high power relay modules, which can control 6 different rooms. Additional 24 relay connections are present on the mainboard, which can be used to control loads by connecting external relay modules if it would be necessary.

Relays are rated to 30Amps each and  able to control loads in total up to 39.6 Kilowatts max! Each of 6 channels has it’s own precise current sensor based on Allegro ACS758 chip. Every channel is controlled and it’s current monitored over the web interface as well as over GSM by SMS messages. In addition main board has 1 channel for main power control with screw terminal  connection for external relay, which can be either mechanical or Solid State. That channel monitored over separate page on web interface page, which generates graphs for Voltage, Amperage and calculated Power usage. Total power usage and monthly/total electricity  fees are also represented on the page:

Additional safety provided by connecting MCU to the house automatic break switches at home distribution panel in series. This provides both electronic and mechanical overload protection in case of short circuit for instance.

Peripherals controlled by radio over the distance. Those can be :

  • Entrance doors and gates (channel is encrypted with 64-bit keys by rolling code algorithm).
  • Water pumps, water/sewage reservoir  control and monitoring.
  • Receiving data from weather stations.
  • Control and monitoring of green energy supplies: wind turbines, solar heaters and panels.
  • Main natural gas and water supply valve controls, pressure monitoring.
  • Garden irrigation system monitoring and control,
  • Greenhouse/Glasshouse monitoring and control,
  • Water filtering and swimming pool controls,
  • Heater and Ventilation Control (HVAC)
  • Autostart and control of backup power generator,
  • Burglar system control and monitoring,
  • and even pet’s feeder and access!

e.t.c…

GSM module – provides controls means from anywhere in the world by sending and receiving SMS messages. Functions such as: arming and disarming burglar systems, opening and closing gates, doors, switching heaters on, receiving notifications and parameters of remote sensors and lighting control. Also it allow to make regular phone calls and send SMS messages straight through the web interface:

Ethernet module provides:

  • Date and time sync,
  • Internet access,
  • IP camera surveillance,
  • Web based interface.

Below are screenshots of 2D and 3D modes, and also some video taken on different stage of project:

2D main page:

Burglar system deactivation screen:

Locked screen:

3D mode:

Снимок_2016_07_04_23_03_47_497 Снимок_2016_07_04_23_03_57_415 Снимок_2016_07_04_23_04_03_175 Снимок_2016_07_04_23_04_18_748 Снимок_2016_07_04_23_04_41_221

Video gallery:

Generator auto-start trial unit:

Backup 6.5KVA power generator first start:

Furniture integration:

Burglar system introduction:

Demo, where you can play with web interface, Use Firefox browser to play with it!

Please note, some pages are still under construction!

Project is  opensource, you can add, modify and improve system on your own. The only limitation is:

YOU CAN NOT USE IT FOR COMMERCIAL PURPOSES!

 

How to build the system.

Current version of the “iHome” is – 0.0.2

You can easily build system using only 2 modules without need for MEGASHIELD mainboard? but the functionality will be limited!

You will only need:

  • Arduino MEGA 2560
  • Ethernet shield based on wiznet W5100
  • Micro SD card for webserver files 1-4Gb in size.

First upload firmware into Arduino board using latest version of  Arduino IDE  and then place web-server files into the root of your micro-SD.

Update Sketch for Arduino MEGA2560 (Stable version from 27Apr2017):

 /*
    iHome MEGA SHIELD UWS_v1.8
    Installation:
   1) Connect all hardwire as per drawing and use pinmapping below as reference
   2) Clear EEPROM using Clear_EEPROM sketch in workfolder
   3) Config HC12 transceiver using HC12_COMM sketch in the
      workfolder: first set both serial communications to 9600bod speed,
      setup channel 1 and UART of the radio to 2400bot, then change sketch to
      2400bod UART speeds and test to confirm that module is setup properly.
      Use HC12 manual as reference.
   4) Configure SIM800L UART speed to 19200
   5) Make sure your MEGA supports watchdog feature, if not then comment all
      watchdog features in this sketch, otherwise read how to burn bootloader which supports it!
   6) Upload this sketch, connect LAN, makesure IP address of the server has the same mask as yours


//-----------------------------------------------------------  EEPROM MEMORY DISTRIBUTION: ARDUINO MEGA 4096 bytes -----------------------------------------------------------------------------------------------------------------------------------------------------
   
   ADDRESS:           0-26                           27-63                      64                     66-266                         268 - 368           370                          372 - 404             405 - 408                  409-412                  
   DATA TYPE:         Ariadne EEPROM addresses       Ariadne password           Unsigned int           Unsigned int                   Byte                unsigned int < 42000         Local Switch State    Total power meter          Stage power meter        
   DATA STORED:                                                                 Unique Device ID       100x Remote Devices            iHouse ReqNumber    Keeloq Counter               32x Switches          unsigned long              unsigned long            
   MEMORY USED::                                                                int - 2 bytes          200 bytes                      100 bytes           2 bytes                      32 bytes              4 bytes                    4 bytes
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
//------------------------------------------------------------EEPROM MEMORY DISTRIBUTION: ARDUINO MEGA 4096 bytes -------------------------------------------------------------------------------------------------------------------------------------------------------
  ADDRESS:             410-610                      612 (311)                       613(312)               615 - 755                           756 - 2256                                    2258 - 2358                    2360 - 2460 
  DATA TYPE:           Empty                        Security Status [1 byte]        Security Code[int]     Security System 10 MobNumbers       phone address book      :                     Fixed code device zone         Fixed code device description 
  DATA STORED:         100EA int(2bytes)            1 - Disarmed;                   2 bytes                International! 10 x 14 bytes        50 numbers 50 x 14 = 700 bytes                1byte x 100 devices            1byte x 100 devices 
  MEMORY USED:         200bytes                     2 - Armed;                                                                                 50 names - 20characters x 50bytes             100bytes                       100bytes
                                                    3 - Alarm Activated                                                                        1000 bytes
                                                    
//------------------------------------------------------------EEPROM MEMORY DISTRIBUTION: ARDUINO MEGA 4096 bytes -------------------------------------------------------------------------------------------------------------------------------------------------------
  ADDRESS:         2462 - 2562                  2564                 2566                   2568                   2570                   2572                      2574-2774(not used!)       2776-2876          2878-2978           2980-3080 
  DATA TYPE:       Fixed code device status     1byte delayed arm    1byte delayed siren    1byte siren on off     1byte Siren Level      1byte send SMS function   Empty                      Button Zone        Button Description  Button Stat
  DATA STORED:     1byte x 100 devices          seconds max 254      seconds max 254                                                                                100EA int(2bytes)          100EA int(1bytes)  100EA int(1bytes)   100EA int(1bytes)
  MEMORY USED:     100bytes                     1byte                1byte                  1byte                  1byte                  1byte                     200bytes                   100bytes           100bytes            100bytes
  
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  ADDRESS:         3082 - 3107(not used)        3108 - 3508                    3610-4010
  DATA TYPE:       Fixed Code Switches          Fixed Code Security Devices    Fixed Code Remote Button
  DATA STORED:     25Switches  x 1byte          100EA long(4bytes)             100EA long(4bytes)
  MEMORY USED:     25bytes                      400bytes                       400bytes
  
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------   
  
   Enjoy.
   Current version designed to work with iHome v1.8! 
   For different setup some features needs to be reprogrammed, such as:
   1) Registration number of iHome remote devices (rgrd) setup:
                                                                Backup Power Generator control          - 7,
                                                                Gate Operation                          - 8,
                                                                Backup Power Generator gas valve       - 10,
                                                                Water Tank Level -
                                                                Sewage Level -
   Visit www.voltrans.az for support.
   created by Elik745i
   date last updated 27.04.2017
*/
#include 
#include 

#include               // watchdog
#include              // For remote control, security system sensors...
#include                // Use Keeloq encryption for sensitive equipment control, gate, door e.t.c.

//Update over ethernet
//#include 
//#include 
//#include 

//W5100
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//EthernetReset reset(8080);    //setup reset function for ethernet firmware uploading

//---------------------------------------------------------------------------------------------Arduino MEGA Pin Mapping-------------------------------------------------------------------------------------------------------------------------------------------
//#define       //tft_RST         0    // you can also connect this to the Arduino reset
// in which case, set this #define pin to 0!
#define        dsTemp         2     //DS18B20 temperature sensor                             
//#define      fanDetec         3     //molex1
#define      SDenable         4     //W5100
#define      radio2Tx         5     //433.92 TX
#define         siren        12     //siren contact
#define      radio2Rx         3     //433.92 RX
#define          buzz         7     //D13 Buzzer PIN
#define       Eenable        10     //W5100 
#define         simRx        14     //TX3 SIM800L TX
#define         simTx        15     //RX3 SIM800L RX
#define       radioRx        18     //TX1   -> (HC12 RX)
#define       radioTx        19     //RX1   -> (HC12 TX)  
#define      radioSET        20     //HC12 SET 

#define          FAN1        34     //Fan ON/OFF                      
//#define       //tft_LED        45     //PWM

//#define        //tft_DC        48     ////tft A0
//#define        //tft_CS        47     //22
#define           SS         53     //MEGA SS pin

#define          Gpin        61     //A7 Grid Voltage detect
//#define          Vpin        62     //A2 Accum Voltage Detect
//#define          Cpin        54     //A0 Grid Current detect
//#define          Jpin        58     //A4 Generator Voltage detect
//#define          Kpin        59     //A5 Generator Current detect
//#define          Lpin        60     //A6 Analog Reseved 1
//#define          Mpin        61     //A7 Analog Reseved 2
//#define          keyb        67     //A13 keyboard

// Fixed code remote sensors:
// 4 button keyfob values:
#define kfb1   21808   //top left button
#define kfb2   21772   //top right button
#define kfb3   12345   //bottom left button
#define kfb4   12345   //bottom right button


// pins interfaced to switches
     // const byte sw_arr[] = {6, 7, 8, 9, 11, 12, 13, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46};
//-------------------------------R1      R2   R3    R4    R5    R6     R7*   R8      R9      R10     R11     R12        R13     R14    R15     R16  R17  R18  R19  R20  R21  R22  R23  R24  R25  R26  R27  R28  R29  R30  R31  R32
          const byte sw_arr[] = {26,     24,  22,   25,   27,   29,    33,   35,     37,     39,     41,     43,        32,     30,    28,     21,  42,  40,  38,  36,   8,   9,  11,  45,  16,  17,  44,  46,  31,  23,  49,  13};  //Relays,  Change 45 to 6 for propper shield!!!
//if for particular relay ON is logic signal 0, then put 1
   const boolean invert_arr[] = { 0,      0,   0,    0,    0,    0,     0,    0,      0,      0,      0,      0,         0,      0,     0,      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0};

        const byte curr_arr[] = {64,    63,   60,   59,   58,   57,    54,   65,     66,     67,     68,     69,        62,     56,     55};                                                                     //Current sensors of first 15 relays.
                    //Currents  A10,    A9,   A6,   A5,   A4,   A3,    A0*,  A11,    A12,    A13,    A14,    A15**,     A8,     A2,     A1
          float curr_coef[] = {0.03,  0.03, 0.03, 0.03, 0.03, 0.03,  0.03, 0.03,   0.03,   0.03,    0.03,    0.03,    0.03,   0.03,   0.03};                                                           //Current sensor's res

//*  A0 Grid Current detect!
//** A15 Power Supply Voltage detecting if J23 is inserted, Relay 12 will not work!
 

//---------------------------------------------------------Analog pins-------------------------------
const byte anal_arr[] = {61, 54, 58, 57};                                                                          //61(A7) - voltage detect, 54(A0) - current detect, 58(A4) - generator current, 57(A3) Solar Panels current

boolean LED_state[33];                                                                                             // stores the states of the LEDs

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*-------------------------------------------INFO-------------------------------------------------------------
   Not all pins on the Mega and Mega 2560 support change interrupts, so only the following
   can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),
   A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).
-------------------------------------------------------------------------------------------------------------*/
//--------------------------------------PHONE FUNCTIONS VARIABLES------------------------------------------------------------
byte gsmCode = 0; //Reply from GSM


//-------------------------------------Current measurement variables---------------------------------------------------------
const unsigned long sampleTime = 10000UL;                                       // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 25UL;                                          // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
//const unsigned long sampleInterval = sampleTime / numSamples;                   // the sampling interval, must be longer than then ADC conversion time
//const int adc_zero = 522;                                                     // relative digital zero of the arudino input from ACS712 (could make this a variable and auto-adjust it)
int adc_zero[16];                                                               //autoadjusted relative digital zero array
float cSense[16];                                                               //Current array

//------------------------------------Arduino voltage measurement variables---------------------------------------------------
const float VccCorrection = 5 / 5;                                              // Measured Vcc by multimeter divided by reported Vcc
float ardV;
Vcc vcc(VccCorrection);
const float Vcrit = 3.5;                                                          //critical battery voltage
const float Vmin = 3.7;                                                           //critical battery voltage
const float Vfull = 4.9;                                                          //critical battery voltage
//----------------------------------------------Keeloq Variables -------------------------------------------------------------
Keeloq k(0x015B442A, 0x636E37A8);                                              //keeloq keys, change them for your iHouse!!!
unsigned int keeloqC = 27740;                                                  // unsigned long can't make more than that, sync this with receiver!


//-------------------------------------------------RCSWITCH-------------------------------------------------------------------
RCSwitch mySwitch = RCSwitch();

#define DevQ  10

int Tup[DevQ];
int Volt[DevQ];
int gVolt[DevQ];
int grVolt[DevQ];
int Temp[DevQ];
int TempD[DevQ];
byte Lit[DevQ];
byte Gaslev[DevQ];
byte Curr[DevQ];
byte Vstat[DevQ];                                                              //valve, curtain, dc motor
byte Gstat[DevQ];
byte Sw1[DevQ];
byte Sw2[DevQ];
byte Sw3[DevQ];
byte Sw4[DevQ];
byte Sw5[DevQ];
byte Sw6[DevQ];
byte Sw7[DevQ];
byte Sw8[DevQ];
byte Hum[DevQ];
byte Press[DevQ];
byte Gyro[DevQ];
byte Alarm[DevQ];
byte rgrd[DevQ];
byte wLev[DevQ];

long FCSdetect[DevQ];    //Detecting 10 simultaneous fixed code signals 

//-----------------------------------------------------------SIM800L--------------------------------------------------------------------------------------------

String currStr = "";                                                                                                                                                       // String to store receivedSMS
boolean isStringMessage = false;                                                                                                                                           // received is message indicator
boolean switchStateSms;                                                                                                                                                    // Switch state operated by SMS
byte sigqua;                                                                                                                                                               //calculated signal strength in % change to int if not working properly!

//------------------------------------------------------TFT SCREEN----------------------------------------------------------------------------------------------

//Adafruit_ST7735 //tft = Adafruit_ST7735(//tft_CS,  //tft_DC, //tft_RST);                           //uncomment if used

//---------------------------------------------------GRID PARAMETERS VARIABLES----------------------------------------------------------------------------------
float gridV;                  //grid Voltage
float tpm;                    //total power meter
float spm;                    //stage power meter
const float Vcoef = 0.00482;        // Measure voltage by multimeter and divide to Read analog data (i.e. 4.14/835)
const float Vgcoef  = 589;          // Grid  Voltage coefficient
//const float Cgcoef  = 0;          // Grid  Current coefficient
const float SLVcoef = 0;            // Solar Voltage coefficient
const float SLCcoef = 0;            // Solar Current coefficient


const unsigned int deviceID = 10001;  //Unique Device ID
int destinationID; //Controling device.
 
#define maxSeqPhone  10
String seqPhone;                                                                  //String holding security phone number

#define maxAddrPhone  50                                                          //Maximum number of addresbook phone numbers

char lcd_buf_3[6] = {0};                                                          //remote device id
char lcd_buf_4[4] = {0};                                                          //remote device iHome number up to 254 devices
char smsphnum[15] = {0};                                                          //sms phone number
 
 String alertStr = "1";                                                           //Alert message sent to web interface, "1" means show nothing
 String alarmString;
//-----------------------------------------------------------------

//OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)


byte devm = 0;
byte clr = 20;   //Clear memory timer

//Ethernet----------------------------
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 128);

//---------------------Ariadne settings------------------------
//IPAddress  gateway(192, 168, 1, 1);
//IPAddress  subnet(255, 255, 255, 0);
//Ariadne port:
//word port = 46969;
//Ariadne reset password:
//String password = "parol";
//-------------------------------------------------------------

char rootFileName[] = "index.htm";

EthernetServer server(80);

File myFile;
//requests buufer, if less - might be delay problems processing xml requests!
#define BUFSIZ2 300
char clientline[BUFSIZ2];
char *filename;



boolean CLR_state[1] = {0}; // stores the states of the LEDs
boolean MET_state;          //stores meter state

unsigned long previousMillis = 0;
const int interval = 500;

boolean z;    //trigger for alarm sound



//SECURITY VARIABLES------------------------------------------------------
byte alarmK;          //Alarm sound
byte alarmSS = 1;     //Arm/Disarm Security System

String SeqSensor = "0";     //Activated sensor value
int alarmC = 0;       //Security code
byte sirenVol = 0;    //Siren Volume
byte sirenOn = 0;     //Siren On/Off
//------------------------------------------------------------------------

boolean fcr;    //Sequrity sensor registration intiation trigger
boolean fcrf;   //Keyfob registration intiation trigger
const byte frtr = 15;
byte frt = 15;

byte printK;
byte req = 0;
byte gsms = 0;         //send sms reply trigger
byte rgs;
boolean rdd;          //receive data soft interrupt



//Time----------------------------------------------------
unsigned long previousMillis2 = 0;
unsigned long previousMillis4 = 0;
unsigned long currentMillis;
const int t1 = 1000;
const int t4 = 500;    //reset receive softinterrupt

//System Running Time
String uptime;
String timeString;

////-----------------.....optimizing
//--------------------------------------------------About Variables---------------------------------------------------------------------------------------
String pcbVer;

//--------------------------------------------------EasyTransfer------------------------------------------------------------------------------------------

EasyTransfer ET;
struct SEND_DATA_STRUCTURE {  //data structure, same for all iHome devices, shouldn't exceed 26 bite!
  unsigned int device_id;
  unsigned int destination_id;
  unsigned long packet_id;      //encrypted data
  byte command;
  int data;
};
SEND_DATA_STRUCTURE mydata;

//time servers--------------------------------
// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
const int timeZone = +4;     // Central European Time
EthernetUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets


//--------------------------------------------------------------------------------------SETUP-----------------------------------------------------------------------------------------------
void setup() {
  delay(1000);
  Serial.begin(19200);                   // Debugging only
  pcbVer = F("iHome MEGA shield sv_1.8");
  Serial.println(pcbVer);

//-------------------------------------SETUP Ethernet-------------------------------------------------------------------
  // disable Ethernet chip
  pinMode(Eenable, OUTPUT);
  digitalWrite(Eenable, HIGH);

  pinMode(SDenable, OUTPUT);
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH);
  byte sdd = 0;
  // initialize SD card----------------------
  Serial.println(F("Initializing SD card..."));
  if (!SD.begin(SDenable)) {
    tone(buzz, 1000, 200);
    Serial.println(F("ERROR!"));
    sdd = 1;
    noTone(buzz);
    return;    // init failed

  }
  Serial.println(F("SUCCESS"));
  // check for index.htm file

  if (!SD.exists("index.htm")) {
    Serial.println(F("ERROR - Can't find index.htm file!"));
    sdd = 2;
    return;  // can't find index file
  }
//---------------------------Set Ariadne Network Settings---------------------------------------
  /* Write the new settings values to EEPROM */
  //NetEEPROM.writeNet(mac, ip, gateway, subnet);
  /* Set the TFTP data transfer port in EEPROM. Change it only if you need to */
  //NetEEPROM.writePort(port);
  /* Write Reset Server password in EEPROM */
  //NetEEPROM.writePass(password);
  
//----------------------------------------------------------------------------------------------  
  //Serial.println("SUCCESS - Found index.htm file.");
  Ethernet.begin(mac, ip);  // initialize Ethernet device
  server.begin();           // start to listen for clients
  Serial.print(F("server is at: "));
  Serial.println(Ethernet.localIP());

  delay(500);

//--------------------------------------RC-Switch----------------------------------------------

  mySwitch.enableReceive(radio2Rx - 2);  // Receiver on interrupt 0 => that is pin #2
  mySwitch.enableTransmit(radio2Tx);     // Transmitter on pin 5
  if (sdd == 1) {
    return;
  }
  if (sdd == 2) {
    return;
  }
  delay(300);

 //----------------------INTERNET Time----------------------------------
  Serial.println(F("TimeNTP"));
  Serial.print(F("IP number assigned by DHCP is "));
  Serial.println(Ethernet.localIP());
  Udp.begin(localPort);
  Serial.println(F("waiting for sync"));
  setSyncProvider(getNtpTime);

 //-----------------------------------SETUP GSM Module--------------------------------
  Serial3.begin(19200);
  gsmSignal();
  Serial3.print("AT+CMGDA=\"DEL ALL\"\n");  //Delete all SMSs from simcard memory
  delay(100);
  Serial3.print("AT+CMGF=1\r");            //SMS messages in text format
  delay(100);
  Serial3.print("AT+CLIP=1\r");           //Caller Identity 1-ON 0-OFF
  delay(100);
  Serial3.print("AT+CPBS=\"SM\"\r");      //Phonebook Memory Storage SM - SIM
  delay(100);
  digitalClockDisplay();
  //set time
  Serial3.print("AT+CCLK=" + timeString); //Set up time
  delay(300);

  //Radio module HC-12 begin
  Serial1.begin(2400);
  ET.begin(details(mydata), &Serial1);

deleteSMS();

//---------------------------------------------------RECALL DATA FROM EEPROM------------------------------------------------------------------
//-------------------------Recover Devices array stored in the memory (EEPROM starting from address 66 to 266)-----

  devDataRecover();
  
//-------------------------------------------------------SECURITY STATUS---------------------------------------------------
  //alarmSS = 1;                           //override security system   
  //EEPROM.put(612, alarmSS);
  
  alarmSS = EEPROM.get(612, alarmSS);
  if (alarmSS == 0) {
    alarmSS = 1;
  }
  if (alarmSS == 2) {
    Serial.println(F("Security is ARMED"));
    SSArm(1);
  } else if (alarmSS == 1){
    Serial.println(F("Security is DISARMED"));
    SSArm(0);
  }
  else if (alarmSS == 3){
    Serial.println(F("Security Siren Triggered!"));
    Siren(1);
  }  
//----------------------------------------------------------SECURITY CODE---------------------------------------------
    
    alarmC =  EEPROM.get(613, alarmC);
    String k = F("Security Code is: ");
    Serial.println(k + String(alarmC));
    
//------------------------------------------------------SECURITY PHONE NUMBERS------------------------------------
/*
for( byte i=0; i < maxSeqPhone; i++){
  int p = i*14+615;  
  for( byte z = 0; z < 15; z++){ 
      int n = p+z;
      char k;
      seqPhone[i][z] = EEPROM.get(n, k);        
    } 
    //Serial.println("Sequrity Phone Number#" + String(i+1) + ": " + seqPhone[i]); 
  }
*/
//------------------Siren Vol----------------------------------------//
sirenOn  = EEPROM.get(2568,sirenOn);
//------------------Siren Vol----------------------------------------//
sirenVol = EEPROM.get(2570,sirenVol);
 
//---------------------------------Keeloq counter setup (EEPROM 370,371)----------------------------------------------
  unsigned int cr;
  if (EEPROM.get(370, cr) > keeloqC || EEPROM.get(370, cr) == 0) {

    EEPROM.put(370, keeloqC);
  }

  EEPROM.get(370, keeloqC);  //get counter from the memory
  k = F("Counter: ");
  Serial.println(k + String(keeloqC));
  // Setting Up Device ID
  Serial.print(F("Device ID... "));
  
//-----------------------------------Unique Device ID:-----------------------------------------------
  //unique_device_id=EEPROMReadInt(0);
  unsigned int unique_device_id = EEPROM.get(64, unique_device_id);

  if (unique_device_id != deviceID) {
    Serial.print(F("N/A, updating... "));

    //unique_device_id=random(10000, 60000);
    unique_device_id = deviceID;
    //EEPROMWriteInt(64, unique_device_id);
    EEPROM.put(64, unique_device_id);
  }

  Serial.println(unique_device_id);

//-----------------------------------RECALL POWER METERS--------------------------------------------
  float tpm = EEPROM.get(405, tpm);
  float spm = EEPROM.get(409, spm);
  
//--------------------------------RECALL LOCAL SWITCH STATES (EEPROM 372-404):---------------------------------------
  for (byte kj = 0; kj < 32; kj++) {
    pinMode( sw_arr[kj], OUTPUT);
    boolean switchSTATE = EEPROM.get(372 + kj, switchSTATE);
    LED_state[kj] = switchSTATE;
    if (invert_arr[kj]) {
      digitalWrite(sw_arr[kj], !switchSTATE);
    } else {
      digitalWrite(sw_arr[kj], switchSTATE);
    }
    delay(30);
  }

//-------------------------------Average the Current Readings----------------------------------------
  for (byte cu = 0; cu < 15; cu++) {
    adc_zero[cu] = determineVQ(curr_arr[cu]); //Quiscent output voltage - the average voltage ACS712 shows with no load (0 A)
    k = F("Current Sensor's zero adc#");
    String l = F(": ");
    Serial.println(k + String(cu+1) + l + adc_zero[cu]);
  }
  wdt_enable(WDTO_8S);
  tone(buzz, 3400, 200);
  //reset.begin();   
  Serial.println(F("Ready."));
}

void loop()
{
  //reset.check();
  currentMillis = millis();

  if (rdd == 0) {

    if (currentMillis - previousMillis2 >= t1) {
      previousMillis2 = currentMillis;
      upTime();
      //datalog();
      arduinoVolt();
      //Serial.println("Arduino Voltage: " + String(ardV,3) + "V");
      gridV = analogRead(anal_arr[0]) * ardV / 1023 * Vgcoef;       // Grid Voltage
      //Serial.println("Grid Voltage: " + String(gridV,1) + "V");
      currA();

      //Fix Code Registration counter:
      if (fcr || fcrf) {
        //Serial.println("Register Fix Code Device within: " + String(frt) + "Sec.");
        frt--;
        if (frt == 0) {
          frt = frtr;
          //alertStr = "Didn't detect any FixCode device signal!";
          fcr = false;
          fcrf = false;
        }
      }
      //---------------
    }
    wdt_reset();
    etherNet();
    rcSwitch();
  }
  alarm();
  wdt_reset();
  receiveComd();
  receiveSMS();
  etherNet();

  if (currentMillis - previousMillis2 >= t4) {
    previousMillis4 = currentMillis;
    rdd = 0;
  }
  if (rgs >= 1) {
    RemGenStart();
  }

}

//Log the data:
void datalog() {
  String dstString = "";
  for (byte dst = 0; dst < 15; dst++) {
    dstString += "," + String(cSense[dst]);
  }
  String dataString = uptime + "," + (gridV / 10) + "," + dstString;
  WriteToLog("datalog.txt", dataString);
}

//current measurements
void currA() {
  for (byte ca = 0; ca < 15; ca++) {
    cSense[ca] = (readCurrent(curr_arr[ca], ca));
    //Serial.println("Current:" +String(cSense,3) + " Amps");
  }
}

int determineVQ(byte PIN) {
  //Serial.print("estimating avg. quiscent voltage:");
  long VQ = 0;
  //read 5000 samples to stabilise value
  for (int i = 0; i < 50; i++) {
    VQ += analogRead(PIN);
    delay(1);//depends on sampling (on filter capacitor), can be 1/80000 (80kHz) max.
  }
  VQ /= 50;
  //Serial.print(map(VQ, 0, 1023, 0, 5000));Serial.println(" mV");
  return int(VQ);
}

float readCurrent(byte PIN, byte arr)
{
  unsigned long currentAcc = 0;
  unsigned int count = 0;
  unsigned long sampleInterval = sampleTime / numSamples;
  unsigned long prevMicros = micros() - sampleInterval ;
  while (count < numSamples)
  {
    if (micros() - prevMicros >= sampleInterval)
    {
      int adc_raw = analogRead(PIN) - adc_zero[arr];
      currentAcc += (unsigned long)(adc_raw * adc_raw);
      ++count;
      prevMicros += sampleInterval;
    }
  }
  //float rms = sqrt((float)currentAcc/(float)numSamples) * ((ardV/curr_coef[arr]) / 1024.0);    // 0.03V for 130A ACS755 sensor x=ardV/0.03
  float rms = sqrt((float)currentAcc / (float)numSamples) * ((5 / curr_coef[arr]) / 1024.0); // 0.03V for 130A ACS755 sensor x=ardV/0.03
  return rms;
  //Serial.println(rms);
}
//System voltage
void arduinoVolt() {
  ardV = vcc.Read_Volts();
  //float p = vcc.Read_Perc(VccMin, VccMax);
}
//Keeloq
void keeloqSecure() {
  keeloqC--;                                       // substract counter number
  //Serial.println("Count:" +String(keeloqC));
  //Serial.println("ID:" +String(deviceID));
  unsigned long rid = keeloqC * 100000 + deviceID;
  //Serial.println("Count + ID:" +String(rid));
  mydata.packet_id = k.encrypt(rid);
  EEPROM.put(370, keeloqC);                          // сохраняем int в EEPROM
}

void rcSwitch() {
  if (mySwitch.available()) {

    long     value = mySwitch.getReceivedValue();
    byte bitlength = mySwitch.getReceivedBitlength();
    byte  protocol = mySwitch.getReceivedProtocol();
    if (value == 0) {
      //Serial.print("Unknown encoding");
    }
    else {
      /*
        //Serial.print("Received ");
        //Serial.print( value );
        //Serial.print(" / ");
        //Serial.print( bitlength );
        //Serial.print("bit ");
        //Serial.print("Protocol: ");
        //Serial.println( protocol );
      */
      if (protocol == 1) {
        if (bitlength == 24) {
          
//-----------------------------------------------------------------------------------Security Sensors Fix Code registration EEPROM(3108-3508) -------------------------------------------------------------------
          if (fcr == true && frt > 0) {
            for (byte count1 = 0; count1 < 100; count1++) {
              long fixcodereg = EEPROM.get(count1 * 4 + 3108, fixcodereg);
              if (fixcodereg == value) {
                //String seqStr = "Device already registered at EEPROM address: " + String(count1 * 4 + 3108) + ", value:" + fixcodereg + ", try different device!";
                //WriteToLog("seqlog.txt", seqStr);
                //alertStr = seqStr;
                fcr = false;
                frt = frtr;
                break;
              }
              if (fixcodereg == 0) {
                EEPROM.put(count1 * 4 + 3108, value);
                tone(buzz, 3500, 50);
                //Serial.println("Fix Code Device: " + String(value) + " At EEPROM ADDRESS: " + (count1 * 4 + 3108) + " Registered!");
                //String seqStr = "Fix Code Device: " + String(value) + " At EEPROM ADDRESS: " + (count1 * 4 + 3108) + " Registered!";
                //WriteToLog("seqlog.txt", seqStr);
                //alertStr = seqStr;
                fcr = false;
                frt = frtr;
                break;
              }
            }
          }

//-----------------------------------------------------------Remote Control Keyfob Code registration EEPROM(3610-4010) -----------------------------------------------------------------------
          if (fcrf == true && frt > 0) {
            for (byte countT = 0; countT < 100; countT++) {
              long fixcoderegf = EEPROM.get(countT * 4 + 3610, fixcoderegf);
              if (fixcoderegf == value) {
                //String roomStr = "Button already registered at EEPROM address: " + String(countT * 4 + 3610) + ", value:" + fixcoderegf + ", try different button!";
                //WriteToLog("roomlog.txt", roomStr);
                //alertStr = roomStr;
                fcrf = false;
                frt = frtr;
                break;
              }
              if (fixcoderegf == 0) {
                EEPROM.put(countT * 4 + 3610, value);
                tone(buzz, 3500, 50);
                //String roomStr = "Button Fix Code: " + String(value) + " At EEPROM ADDRESS: " + (countT * 4 + 3610) + " Registered!";
                //WriteToLog("roomlog.txt", roomStr);
                //alertStr = roomStr;
                fcrf = false;
                frt = frtr;
                break;
              }
            }
          }

//---------------------------------------------------------------Security System Fiixed code devices detect-------------------------------------------------------------------
          if (alarmSS == 2) {
            for (byte ifg = 0; ifg < 100; ifg++) {
              long ifgp = EEPROM.get(ifg * 4 + 3108, ifgp);
              if (value == ifgp) {
                //door sensor#1
                Siren(1);
                String k = F("Security Sensor: ");
                String l = F("Activated!"); 
                alarmString =  k + String(value) + l;
                WriteToLog("seqlog.txt", alarmString);
                //Serial.println(alarmString);
                SeqSensor = value;
                alertStr = alarmString;
                byte smsOn = EEPROM.get(2572,smsOn);
                if(smsOn == 1){
                sendSMS(alarmString);
                }
                break;
              }
            }
          }

//----------------------------------------------Start Generator: open valve RDRG 10, once it's open - go to start generator sequence----------------------------------------
          if (value == kfb1) {
            RemGenStart();
          }

          else if (value == kfb2) {
            RemGenShut();
          }
//------------------------------------------------------  Detect registered fixed code signals EEPROM(3108-3508 and 3610-4010) -----------------------------------------------

for(byte fcd=0; fcd < 100; fcd++){
  long fcdd;                                  //Search in security fixed code device stored in memory first
  EEPROM.get(fcd*4 + 3108, fcdd);
  if (value == fcdd){
    for(byte fcsd = 0; fcsd < 10;fcsd++){
      if(FCSdetect[fcsd] == 0){
        FCSdetect[fcsd] = fcdd;               //add it to FCSdetect int row to be send to the client.        
        //Serial.println(FCSdetect[fcsd]);
                String k = F("Registered fixed code device: ");
                String l = F(" Detected!");
                alarmString =  k + String(value) + l;
                //WriteToLog("roomlog.txt", alarmString);
                //alertStr = alarmString;
                //Serial.println(alarmString);
        break;
      } 
    }    
  }
  //if code not found in security device codes, search in keyfob buttons raw:
  long kfbr;
  EEPROM.get(fcd*4 + 3610, kfbr);
  if (value == kfbr){
    for(byte fcsd = 0; fcsd < 10; fcsd++){
      if(FCSdetect[fcsd] == 0){
        FCSdetect[fcsd] = kfbr;             //add it to FCSdetect int row to be send to the client.
        //Serial.println(FCSdetect[fcsd]);
        break;
      } 
    }    
  }
                                
}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                   
        }
      }
    }
    mySwitch.resetAvailable();
  }

}

//---------------------------------------------------------------Generator control--------------------------------------------------------------

void RemGenStart() {
  byte genid;
  if (rgs == 0) {

    for (byte ik = 0; ik < DevQ; ik++) {
      if (rgrd[ik] == 10) {
        destinationID = EEPROM.get(2*ik + 66,destinationID);
        break;
      }
    }
    //openValve();
    rgs = 1;
  }

  if ( rgs == 1) {
    rgs = 2;
    for (byte ik = 0; ik < DevQ; ik++) {
      if (rgrd[ik] == 7) {
        destinationID = EEPROM.get(2*ik + 66,destinationID);
        genid = ik;
        break;
      }
    }
    startGen();
  }
  if (Gstat[genid] == 1 && rgs == 2) {
    rgs = 0;
    //tft.print("Generator is Running! ");
  }
  if (Gstat[genid] == 3 && rgs == 2) {
    rgs = 0;
    //tft.fillRect(0,58,128,50, ST7735_BLACK);
    //tft.setCursor(0, 70);
    //tft.setTextColor(ST7735_BLUE);
    //tft.print("Generator Failed to Start! ");
  }

}

void RemGenShut() {
  rgs = 0;
  for (byte ik = 0; ik < DevQ; ik++) {
    if (rgrd[ik] == 7) {
      destinationID = EEPROM.get(2*ik + 66,destinationID);
      break;
    }
  }
  shutGen();
  for (byte ik = 0; ik < DevQ; ik++) {
    if (rgrd[ik] == 10) {
      destinationID = EEPROM.get(2*ik + 66,destinationID);
      break;
    }
  }
  closeValve();

}

void startGen() {

  mydata.command = 171;
  mydata.data = 1;
  transmitData();
  //Serial.println("Transmitting packet \"Generator ON\"");
  //Serial.println("DONE");
}

void shutGen() {

  mydata.command = 171;
  mydata.data = 2;
  transmitData();
  //Serial.println("Transmitting packet \"Generator OFF\"");
  //Serial.println("DONE");
}

//Operationg Gate
void gateOper(byte mzk) {

  for (byte ik = 0; ik < DevQ; ik++) {
    if (rgrd[ik] == 8) {
      destinationID = EEPROM.get(2*ik + 66,destinationID);
    }
  }
  switch (mzk) {
    case 1:
      mydata.command = 1;
      mydata.data = 1;
      transmitData();
      break;
    case 2:
      mydata.command = 2;
      mydata.data = 1;
      transmitData();
      break;
case3:
      mydata.command = 3;
      mydata.data = 1;
      transmitData();
      break;
  }
}

void lightOper(byte mzs) {
  switchStateSms = LED_state[mzs - 1];
  digitalWrite(sw_arr[mzs - 1], !switchStateSms);
  LED_state[mzs - 1] = !switchStateSms;
  EEPROM.put(372 + (mzs - 1), !switchStateSms);
}

EthernetClient client;


void etherNet()
{

  int index = 0;

  client = server.available();

  if (client) {
    //detachInterrupt(0);
    // an http request ends with a blank line

    boolean current_line_is_blank = true;

    // reset the input buffer

    index = 0;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();
        /*readString.toCharArray(clientline,BUFSIZ);*/
        // Сбросить соединение, если пришел непонятный символ от клиента.

        //Например, наблюдались зависания от браузера

        // Safary (IPad 2), который посылал "непонятные" символы

        if ( c == 0x0A || c == 0x0D ) goto aa;

        if ( c < 0x20 || c > 0x7E ) break;

aa:

        // Если символ от клиента правильный, записываем его в буфер

        // Если идет чтение не новой строки, то продолжаем ее символы записывать в буфер.

        if (c != '\n' && c != '\r') {

          clientline[index] = c;

          index++;

          // �дем на продолжение считывать новый символ.

          continue;

        }

        // Заканчиваем строку символом 0, если следующая строка новая (получили  \n или \r )

        clientline[index] = 0;

        filename = 0;

        // Распечатываем прочитанную строку.--------------------------------

//Serial.println(clientline);

        // Look for substring such as a request to get the root file

        if (strstr(clientline, "GET / ") != 0) {

          filename = rootFileName;

        }

        if (strstr(clientline, "ajax_inputs") != 0 && rdd != 1) {
          // send rest of HTTP header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/xml");
          client.println("Connection: keep-alive");
          client.println();
          SetDevs();
          // send XML file containing input states
          XML_response(client);
          //Serial.println("AJAX Responce sent");
        }

        else if (strstr(clientline, "GET /") != 0) {

          // this time no space after the /, so a sub-file

          if (!filename) filename = clientline + 5; // look after the "GET /" (5 chars)

          // a little trick, look for the " HTTP/1.1" string and

          // turn the first character of the substring into a 0 to clear it out.

          (strstr(clientline, " HTTP"))[0] = 0;

          // print the file we want

          //Serial.println(filename);

          myFile = SD.open(filename);


          if (!myFile) {

            client.println("HTTP/1.1 404 Not Found");

            client.println("Content-Type: text/html");

            client.println();

            client.println("

File Not Found!

"); break; } client.println("HTTP/1.1 200 OK"); //Serial.println("Opened!"); if (strstr(filename, ".htm") != 0) client.println("Content-Type: text/html"); else if (strstr(filename, ".css") != 0) client.println("Content-Type: text/css"); else if (strstr(filename, ".dic") != 0) client.println("Content-Type: text/css"); else if (strstr(filename, ".png") != 0) client.println("Content-Type: image/png"); else if (strstr(filename, ".txt") != 0) client.println("Content-Type: text/plain"); else if (strstr(filename, ".jpg") != 0) client.println("Content-Type: image/jpg"); else if (strstr(filename, ".jpeg") != 0) client.println("Content-Type: image/jpeg"); else if (strstr(filename, ".obj") != 0) client.println("Content-Type: application/octet-stream"); else if (strstr(filename, ".zip") != 0) client.println("Content-Type: application/x-zip-compressed"); else if (strstr(filename, ".mtl") != 0) client.println("Content-Type: application/octet-stream"); else if (strstr(filename, ".gif") != 0) client.println("Content-Type: image/gif"); else if (strstr(filename, ".svg") != 0) client.println("Content-Type: image/svg+xml"); else if (strstr(filename, ".ttf") != 0) client.println("Content-Type: application/x-font-ttf"); else if (strstr(filename, ".wof") != 0) client.println("Content-Type: application/x-font-woff"); else if (strstr(filename, ".3gp") != 0) client.println("Content-Type: video/mpeg"); else if (strstr(filename, ".pdf") != 0) client.println("Content-Type: application/pdf"); else if (strstr(filename, ".js") != 0) client.println("Content-Type: application/x-javascript"); else if (strstr(filename, ".xml") != 0) client.println("Content-Type: application/xml"); else client.println("Content-Type: text"); client.println(); //---------------------------------------------- if (myFile) { byte buf1[512]; //web buffer if working unstable reduce to 512! while (1) { wdt_reset(); //reset watchdog counter noTone(buzz); int n = myFile.read((char*)buf1, 512); if (n == 0){ break; } client.write(buf1, n); } } myFile.close(); } //if request is neither ajax nor webpage: else { // everything else is a 404 client.println("HTTP/1.1 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("

File Not Found!

"); } break; } } // give the web browser time to receive the data delay(1); client.stop(); //attachInterrupt(0, receiveComd, CHANGE); } } //---------------------------------------Find String in the AJAX request----------------------------/ boolean FindStringInAJAX(char *line1, int len, char *req) { boolean got_text = false; // text received flag char *str_begin; // pointer to start of text char *str_end; // pointer to end of text int str_len = 0; int txt_index = 0; char *current_line; current_line = line1; // get pointer to the beginning of the text str_begin = strstr(clientline, req); for (int j = 0; j < 1; j++) { // do for 1 lines of text if (str_begin != NULL) { str_begin = strstr(str_begin, "="); // skip to the = str_begin += 1; // skip over the = str_end = strstr(str_begin, "&"); if (str_end != NULL) { str_end[0] = 0; // terminate the string str_len = strlen(str_begin); // copy the string to the buffer and replace %20 with space ' ' for (int i = 0; i < str_len; i++) { if (str_begin[i] != '%') { if (str_begin[i] == 0) { // end of string break; } else { current_line[txt_index++] = str_begin[i]; if (txt_index >= (len - 1)) { // keep the output string within bounds break; } } } else { // replace %20 with a space if ((str_begin[i + 1] == '2') && (str_begin[i + 2] == '0')) { current_line[txt_index++] = ' '; i += 2; if (txt_index >= (len - 1)) { // keep the output string within bounds break; } } } } // end for i loop // terminate the string current_line[txt_index] = 0; got_text = true; } } } // end for j loop return got_text; } //----------------------------------------------------------------- void SetDevs(void) { //COMPARE SECURITY CODE: char lcd_buf_12[5] = {0}; if ( FindStringInAJAX(lcd_buf_12, 5, "&ULKC=")) { int unlockCode = atoi(lcd_buf_12); //Serial.println(unlockCode); alarmC = EEPROM.get(613, alarmC); //Serial.println(alarmC); if(unlockCode == alarmC){ SSArm(0); } else{ String k =F("Wrong Password!"); alertStr = k; } } //Function if only system is not armed: if(alarmSS == 1){ // Local Switches LED1-LED32 ------------------------------------------ for (byte dv = 1; dv < 33; dv++) { String swoff = {"LED" + (String)dv + "=" + "0"}; String swon = {"LED" + (String)dv + "=" + "1"}; char soff[9]; swoff.toCharArray(soff, 9); char* s1off = soff; char son[9]; swon.toCharArray(son, 9); char* s1on = son; byte switchSTATE; if (invert_arr[dv - 1] == true) { if (strstr(clientline, s1off) != 0) { digitalWrite(sw_arr[dv - 1], HIGH); LED_state[dv - 1] = 0; switchSTATE = 0; EEPROM.put(372 + (dv - 1), switchSTATE); } if (strstr(clientline, s1on) != 0) { digitalWrite(sw_arr[dv - 1], LOW); LED_state[dv - 1] = 1; switchSTATE = 1; EEPROM.put(372 + (dv - 1), switchSTATE); } } else { if (strstr(clientline, s1off) != 0) { digitalWrite(sw_arr[dv - 1], LOW); LED_state[dv - 1] = 0; switchSTATE = 0; EEPROM.put(372 + (dv - 1), switchSTATE); } if (strstr(clientline, s1on) != 0) { digitalWrite(sw_arr[dv - 1], HIGH); LED_state[dv - 1] = 1; switchSTATE = 1; EEPROM.put(372 + (dv - 1), switchSTATE); } } } //FailSafe Switch if (strstr(clientline, "&ALOF=1")) { //Serial.println("Switching all OFF"); for(byte dv=1; dv < 33; dv++){ digitalWrite(sw_arr[dv - 1], LOW); LED_state[dv - 1] = 0; byte switchSTATE = 0; EEPROM.put(372 + (dv - 1), switchSTATE); delay(200); } } //Security-------------------------------------------------- if (strstr(clientline, "&LOCK=1")) { //Serial.println("SS Armed"); SSArm(1); } //-------------------------Remote Control Button Registration-------------------------------------------------------- //Initiate Registration: if (strstr(clientline, "&FixRKB=1")) { //Serial.println("Keyfob Code Registration Active"); String roomStr = F("Keyfob Code Registration Active!"); WriteToLog("roomlog.txt", roomStr); fcrf = true; } //-------------------------Fix Code Keyfob Registration-------------------------------------------------------------- char lcd_buf_45[3] = {0}; if (FindStringInAJAX(lcd_buf_45, 3, "&FixARFB=")) { // print the received Device ID for register byte butNum = atoi(lcd_buf_45); Serial.println(butNum); tone(buzz,3500,200); long code = random(1000000,99999999); for(byte i=0;i iHome 3dmap number: "); //Serial.println(regdevid); for (byte dv = 0; dv < DevQ; dv++) { int DevID = EEPROM.get(2*dv + 66, DevID); if (rgrd[dv] == regdevid) { if (DevID != regdev ) { rgrd[dv] = 0; unsigned int ers = 0; EEPROM.put(268 + dv, ers); //EEPROM address 268, 269, 270 e.t.c. } } if (DevID == regdev ) { rgrd[dv] = regdevid; EEPROM.put(268 + dv, regdevid); //EEPROM address 268, 269, 270 e.t.c. } } } //Register New Phone Number in Security System char lcd_buf_10[14] = {0}; if(FindStringInAJAX(lcd_buf_10, 14, "&SSN=")){ for(byte spn=0; spn < maxSeqPhone; spn++){ int spnN = spn*14+615; char spnP[14]; String Str = EEPROM.get(spnN, spnP); String Str10 = lcd_buf_10; if(Str == Str10){ alertStr = F("Number already exist!"); break; } else if (Str == 0 && spn != maxSeqPhone){ //Serial.println("Writing: EEPROM Address#" + String(spnN) + "; Phone: " + Str10); EEPROM.put(spnN, lcd_buf_10); break; } if(spn == maxSeqPhone){ alertStr = F("Memory is full!"); } } } //------------------------------------------------------Register Phone Number in the EEPROM memory (EEPROM 756 - 2256) ------------------------------------------------ char lcd_buf_13[14] = {0}; if(FindStringInAJAX(lcd_buf_13, 14, "&RGNU=")){ for(byte spn=0; spn < maxAddrPhone; spn++){ int spnN = spn*14+756; char spnP[14]; String Str = EEPROM.get(spnN, spnP); String Str10 = lcd_buf_13; if(Str == Str10){ alertStr = F("Number already exist!"); break; } else if (Str == 0 && spn != maxAddrPhone){ //Serial.println("Writing: EEPROM Address#" + String(spnN) + "; Phone: " + Str10); EEPROM.put(spnN, lcd_buf_13); break; } if(spn == maxAddrPhone){ alertStr = F("Memory is full!"); } } } //------------------------------------------------------------------------------------------------------------------------------------------------ //Send SMS text message char lcd_buf_8[136] = {0}; if (FindStringInAJAX(lcd_buf_8, 136, "&SMS=")) { //find position of marker $ byte pos; for(byte z=0;z<=135;z++){ if(lcd_buf_8[z] == '$'){ pos = z; break; } } //figure out number: for (byte kh = 0; kh < pos ; kh++) { smsphnum[kh] = lcd_buf_8[kh]; } if(pos < 13){ for(byte jk = (pos); jk<=15; jk++){ smsphnum[jk] = 0; } } //find sms text: char temes[120]={0}; for(byte px=(pos+1); px<=135; px++){ temes[px-(pos+1)] = lcd_buf_8[px]; } //Serial.println("SMS Num: " + String(smsphnum)); //Serial.println("SMS Text: " + String(temes)); //send sms: sendPhoneSMS(temes, smsphnum); delay(100); } //Make Voice Call char lcd_buf_7[14] = {0}; if (FindStringInAJAX(lcd_buf_7, 14, "&PHO=")) { // print the received Phone Number //int regdev = atoi(lcd_buf_3); //Serial.println("Voice Call: " + String(lcd_buf_7)); Serial3.print("ATD" + String(lcd_buf_7) + ";\r"); delay(100); } //Hang the Phone if (strstr(clientline, "&HGP=1")) { //Serial.println("Hanging the phone"); Serial3.print("ATH\r"); delay(100); } //Clear Security Phone list if (strstr(clientline, "&CLSPL=1")) { for(byte spn=0; spn < maxSeqPhone; spn++){ int spnN = spn*14+615; char spnP[14] = {0}; char Str = EEPROM.put(spnN,spnP); } //alertStr = "Done!"; } //Read SIM Phonebook //Register New Device iHome device char lcd_buf_1[6] = {0}; if (FindStringInAJAX(lcd_buf_1, 6, "&RGR=")) { // print the received Device ID for reister tone(buzz,3500,200); int devid2 = atoi(lcd_buf_1); //Serial.println("Register iHome device ID: " + String(devid2)); if (devid2 != deviceID && devid2 > 10000) { //Serial.println("New Device Registered: " + (String)mydata.device_id); RegDev(devid2); } } //valve ------------------------------------------------ for (byte dv = 0; dv < DevQ ; dv++) { String swoff = {"Valve" + (String)dv + "=" + "0"}; String swon = {"Valve" + (String)dv + "=" + "1"}; char soff[9]; swoff.toCharArray(soff, 9); char* s1off = soff; char son[9]; swon.toCharArray(son, 9); char* s1on = son; int DevID = EEPROM.get(2*dv + 66, DevID); destinationID = DevID; if (strstr(clientline, s1off) != 0) { closeValve(); } if (strstr(clientline, s1on) != 0) { openValve(); } } //Generator ------------------------------------------------ for (byte dv = 0; dv < DevQ ; dv++) { String swoff = {"Gen" + (String)dv + "=" + "0"}; String swon = {"Gen" + (String)dv + "=" + "1"}; char soff[9]; swoff.toCharArray(soff, 9); char* s1off = soff; char son[9]; swon.toCharArray(son, 9); char* s1on = son; int DevID = EEPROM.get(2*dv + 66, DevID); destinationID = DevID; if (strstr(clientline, s1off) != 0) { shutGen(); } if (strstr(clientline, s1on) != 0) { startGen(); } } //-------------------------------------switch ------------------------------------------------ //switch device 0: for (byte sw = 1; sw <= 8; sw++) { String swoff = {"Switch" + (String)sw + "=" + "0"}; String swon = {"Switch" + (String)sw + "=" + "1"}; char soff[10]; swoff.toCharArray(soff, 10); char* s1off = soff; char son[10]; swon.toCharArray(son, 10); char* s1on = son; int DevID = EEPROM.get(2*0 + 66, DevID); destinationID = DevID; if (strstr(clientline, s1off) != 0) { switchOFF(sw); } if (strstr(clientline, s1on) != 0) { switchON(sw); } } //switch the rest devices: for (byte dv = 0; dv < DevQ ; dv++) { for (byte sw = 1; sw <= 8; sw++) { String swoff = {"Switch" + (String)dv + sw + "=" + "0"}; String swon = {"Switch" + (String)dv + sw + "=" + "1"}; char soff[11]; swoff.toCharArray(soff, 11); char* s1off = soff; char son[11]; swon.toCharArray(son, 11); char* s1on = son; int DevID = EEPROM.get(2*dv + 66, DevID); destinationID = DevID; if (strstr(clientline, s1off) != 0) { switchOFF(sw); } if (strstr(clientline, s1on) != 0) { switchON(sw); } } } } } //Clear SD File void ClearSDFile(String filename){ //char temp[filename.length()+1]; //SdFat lib uncomment //filename.toCharArray(temp, sizeof(filename)); //SdFat lib uncomment if(SD.exists(filename)){ // если файл с именем filename существует, то ... //Serial.println("Deleting " + filename); SD.remove(filename); File myFile; myFile = SD.open(filename, FILE_WRITE ); myFile.close(); }else{ // иначе ... //Serial.println("file doesn't exist"); } } //Write to SD card void WriteToLog(String filename, String text){ myFile = SD.open(filename, FILE_WRITE); // if the file opened okay, write to it: if (myFile) { //Serial.print("Writing to " + filename + "..."); myFile.println(timeString + " - " + text); // close the file: myFile.close(); //Serial.println("done."); } else { // if the file didn't open, print an error: //Serial.println("error opening " + filename); } } // send the XML file with analog values, switch status // and LED status void XML_response(EthernetClient cl) { wdt_reset(); noTone(buzz); int analog_val; // stores value read from analog inputs int count; // used by 'for' loops cl.print(""); cl.print(""); //GSM Signal: cl.print(""); cl.print(sigqua); cl.println(""); //uptime: cl.print(""); cl.print(uptime); cl.println(""); //VCC: cl.print(""); cl.print(ardV); cl.println(""); cl.print(""); //GSM cl.print(""); cl.print(gsmCode); cl.println(""); //Sequrity Phone Numbers--------------------------------------------------------- for(byte spn=0;spn<=9;spn++){ int spnN = spn*14+615; char spnP[14]; String Str = EEPROM.get(spnN,spnP); if(Str != 0){ cl.print(""); cl.print(String(spn+1) + ": " + Str); cl.println(""); } } //Phone Book Numbers ------------------------------------------------------------ for(byte spn=0;spn<=9;spn++){ int spnN = spn*14+756; char spnP[14]; String Str = EEPROM.get(spnN,spnP); if(Str != 0){ cl.print(""); cl.print(String(spn+1) + ": " + Str); cl.println(""); } } //------------------------------------------------------------------------------- // read device IDs for (byte countM = 0; countM < DevQ; countM++) { int DevID = EEPROM.get(countM*2 + 66,DevID); //DevID EEPROM ADDRESS: 66-266 if(DevID != 0){ cl.print(""); cl.print(DevID); cl.println(""); // read timeUp cl.print(""); cl.print(Tup[countM]); cl.println(""); // read battery voltages cl.print(""); cl.print(Volt[countM]); cl.println(""); // read generator voltages cl.print(""); cl.print(gVolt[countM]); cl.println(""); // read Grid voltages cl.print(""); cl.print(grVolt[countM]); cl.println(""); // read analog temperatures cl.print(""); cl.print(Temp[countM]); cl.println(""); // read digital temperatures cl.print(""); cl.print(TempD[countM]); cl.println(""); // read lits cl.print(""); cl.print(Lit[countM]); cl.println(""); // read currents cl.print(""); cl.print(Curr[countM]); cl.println(""); // read gas levels cl.print(""); cl.print(Gaslev[countM]); cl.println(""); // read valve statuses cl.print(""); cl.print(Vstat[countM]); cl.println(""); // read switch#1 status cl.print(""); cl.print(Sw1[countM]); cl.println(""); // read switch#2 status cl.print(""); cl.print(Sw2[countM]); cl.println(""); // read switch#3 status cl.print(""); cl.print(Sw3[countM]); cl.println(""); // read switch#4 status cl.print(""); cl.print(Sw4[countM]); cl.println(""); // read switch#5 status cl.print(""); cl.print(Sw5[countM]); cl.println(""); // read switch#6 status cl.print(""); cl.print(Sw6[countM]); cl.println(""); // read switch#7 status cl.print(""); cl.print(Sw7[countM]); cl.println(""); // read switch#8 status cl.print(""); cl.print(Sw8[countM]); cl.println(""); // read generator status cl.print(""); cl.print(Gstat[countM]); cl.println(""); // read water level cl.print(""); cl.print(wLev[countM]); cl.println(""); // read Registered Device ID: cl.print(""); cl.print(rgrd[countM]); cl.println(""); } } //Security: cl.print(""); cl.print(alarmSS); cl.println(""); cl.print(""); cl.print(SeqSensor); cl.println(""); cl.print(""); byte darm = EEPROM.get(2564,darm); cl.print(darm); cl.println(""); cl.print(""); byte ddrm = EEPROM.get(2566,ddrm); cl.print(ddrm); cl.println(""); cl.print(""); cl.print(sirenVol); cl.println(""); cl.print(""); cl.print(sirenOn); cl.println(""); cl.print(""); byte smsOn = EEPROM.get(2572,smsOn); cl.print(smsOn); cl.println(""); cl.print(""); cl.print(gridV); cl.println(""); cl.print(""); cl.print(analogRead(anal_arr[2]) * SLVcoef); cl.println(""); cl.print(""); cl.print(analogRead(anal_arr[3]) * SLCcoef); cl.println(""); for (byte countS = 0; countS <= 14; countS++) { // analog arry //Serial.println("Analog Input: " +String(anal_arr[countS]) + "Value - " + analog_val); cl.print(""); cl.print(cSense[countS] * 1000); cl.println(""); } //------------------------------------------------------ Fixed codes detected--------------------------------------------------------------------- for(byte fcd = 0; fcd < 10; fcd++){ cl.print(""); cl.print(FCSdetect[fcd]); cl.println(""); FCSdetect[fcd] = 0; } //------------------------------------------------------Send Light Switch Status (EEPROM 2980-3080)---------------------------------------------------------------------- /* for(byte fcd = 0; fcd < 100; fcd++){ cl.print(""); byte lss = EEPROM.get(fcd + 2980, lss); cl.print(lss); cl.println(""); } */ //-------------------------------------------------------------Alerts----------------------------------------------------------------------------- cl.print(""); cl.print(alertStr); cl.println(""); alertStr = "1"; //total power meter cl.print(""); tpm += cSense[0] * gridV / 1200000; //Serial.print("Total Power Meter: "); //Serial.println(tpm,6); cl.print(tpm); cl.println(""); //Stage Power Meter cl.print(""); spm += cSense[0] * gridV / 1200000; //Serial.print("Stage Power Meter: "); //Serial.println(spm,6); cl.print(spm); cl.println(""); //---------------------------------Sending XML Security Fixed Code Devices from EEPROM(3108-3608)(2258-2566)------------------------------------------------------- for (byte counts = 0; counts < 100; counts++) { long FixCodDev = EEPROM.get(counts * 4 + 3108, FixCodDev); //read fixed code (3108-3608) long byte FixCodZone = EEPROM.get(counts + 2258, FixCodZone); //read fixed code devices Zone from EEPROM (2258-2358) byte byte FixCodDesc = EEPROM.get(counts + 2360, FixCodDesc); //read fixed code devices Description from EEPROM (2360 - 2460) byte byte FixCodStat = EEPROM.get(counts + 2462, FixCodStat); //read fixed code devices Status from EEPROM (2462-2562) byte if (FixCodDev == 0 || FixCodDev == 255 || FixCodDev == 256){ continue; } cl.print(""); cl.print(FixCodDev); cl.println(""); cl.print(""); cl.print(FixCodZone); cl.println(""); cl.print(""); cl.print(FixCodDesc); cl.println(""); cl.print(""); cl.print(FixCodStat); cl.println(""); } //---------------------------------Sending XML Remote Control Keyfob Fixed Codes from EEPROM(3610-4010)------------------------------------------------------- for (byte counts = 0; counts < 100; counts++) { long FixCodDev = EEPROM.get(counts * 4 + 3610, FixCodDev); //read fixed code (3610-4010) byte FixCodZone = EEPROM.get(counts + 2776, FixCodZone); //read fixed code devices Zone from EEPROM (2776-2876) byte FixCodDesc = EEPROM.get(counts + 2878, FixCodDesc); //read fixed code devices Description from EEPROM (2878-2978) byte FixCodStat = EEPROM.get(counts + 2980, FixCodStat); //read fixed code devices Status from EEPROM (2980-3080) if (FixCodDev == 0 || FixCodDev == 255 || FixCodDev == 256){ continue; } cl.print(""); cl.print(FixCodDev); cl.println(""); cl.print(""); cl.print(FixCodZone); cl.println(""); cl.print(""); cl.print(FixCodDesc); cl.println(""); cl.print(""); cl.print(FixCodStat); cl.println(""); } //-------------------------------------------------------------------------------------------------------------------------------------------------------------- // checkbox LED states // LED1 cl.print(""); if (LED_state[0]) { cl.print("checked"); } else { cl.print("unchecked"); } cl.println(""); // LED2 cl.print(""); if (LED_state[1]) { cl.print("checked"); } else { cl.print("unchecked"); } cl.println(""); // button LED states // LED 1-33 for (byte led = 2; led <= 31; led++) { cl.print(""); if (LED_state[led]) { cl.print("on"); } else { cl.print("off"); } cl.println(""); } // Clear Mem cl.print(""); if ( CLR_state[0] == 1) { cl.print(CLR_state[0]); clr--; //Serial.println("clr = " +(String)clr); if (clr <= 0) { CLR_state[0] = 0; clr = 20; } } else { cl.print(CLR_state[0]); } cl.println(""); //Register FixCode Device cl.print(""); cl.print(frt); cl.println(""); // Clear Power Meter cl.print(""); if (MET_state) { cl.print(1); MET_state = 0; } else { cl.print(0); } cl.println(""); cl.print(""); } void upTime() { byte secS; byte minutesS; byte hoursS; unsigned int daysS; if (secS < 59) { secS++; //sysVolt(); digitalClockDisplay(); } else { secS = 0; datalog(); //Ask Devices 1ce in a minute: if (devm >= (DevQ - 1)) { devm = 0; } int DevID = EEPROM.get(2*devm + 66, DevID); if (DevID != 0) { askDevice(DevID); } devm++; //----------------------------- gsmSignal(); if (minutesS < 59) { minutesS++; } else { //record power usage once in an hour EEPROM.put(409, spm); EEPROM.put(405, tpm); if (hoursS < 23) { minutesS = 0; hoursS++; } else { minutesS = 0; hoursS = 0; daysS++; } } } uptime = (String)daysS + ":" + (String)hoursS + ":" + (String)minutesS + ":" + (String)secS; /* //Serial.print("uptime: "); //Serial.print(days); //Serial.print("days, "); //Serial.print(hours); //Serial.print("hrs, "); //Serial.print(minutes); //Serial.print("min, "); //Serial.print(sec); //Serial.println("sec. "); */ } void askDevice(int k) { destinationID = k; mydata.command = 198; mydata.data = 1; transmitData(); //Serial.println("Request sent to device# " +(String)k); } void receiveComd() { if (ET.receiveData()) { rdd = 1; if (mydata.destination_id == deviceID) { RegDev(mydata.device_id); //-----------------------------------------------------1-11----------------------------------------------------------------------- if (mydata.command == 1) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=5){ Sw1[m] = mydata.data - 2; break; } } } } if (mydata.command == 2) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=5){ Sw2[m] = mydata.data - 2; break; } } } } if (mydata.command == 3) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=5){ Sw3[m] = mydata.data - 2; break; } } } } if (mydata.command == 4) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=5){ Sw4[m] = mydata.data - 2; break; } } } } if (mydata.command == 5) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=4){ Sw5[m] = mydata.data - 2; break; } } } } if (mydata.command == 6) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=4){ Sw6[m] = mydata.data - 2; break; } } } } if (mydata.command == 7) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=4){ Sw7[m] = mydata.data - 2; break; } } } } if (mydata.command == 8) { for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { //------------------enter data to Sw[m] array---------------------------- if(mydata.data>=3 || mydata.data<=4){ Sw8[m] = mydata.data - 2; break; } } } } //----------------------------------------------------------------56 Valve Status------------------------------------------------------------------------------ if (mydata.command == 56) { if (mydata.data == 3) { String valveStat = F(" Valve Status: CLOSE "); if (gsms == 1) { sendSMS(valveStat); gsms = 0; } //Serial.println(valveStat); //enter data to Vstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Vstat[m] = 2; break; } } } if (mydata.data == 4) { String valveStat = F(" Valve Status: OPEN "); if (gsms == 1) { sendSMS(valveStat); gsms = 0; } //Serial.println(valveStat); //enter data to Vstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Vstat[m] = 1; break; } } } if (mydata.data == 5) { String valveStat = F(" Valve Status: HALF "); if (gsms == 1) { sendSMS(valveStat); gsms = 0; } //Serial.println(valveStat); //enter data to Vstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Vstat[m] = 3; break; } } } if (mydata.data == 6) { String valveStat = F(" Valve Status: NC "); if (gsms == 1) { sendSMS(valveStat); gsms = 0; } //Serial.println(valveStat); //enter data to Vstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Vstat[m] = 4; break; } } } } //71 Temperature ---------------------------------------------------------------------------------------------------------------- if (mydata.command == 71) { float temp = (float)mydata.data / 100; //Serial.print("Temperature: "); //Serial.print(temp); //Serial.println("*C "); //enter data to Temp[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Temp[m] = temp * 100; break; } } } if (mydata.command == 72) { float temp = (float)mydata.data / 100; //Serial.print("Temperature: "); //Serial.print(temp); //Serial.println("*C "); //enter data to Temp[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { TempD[m] = temp * 100; break; } } } //111 Light ---------------------------------------------------------------------------- if (mydata.command == 111) { int light = map(mydata.data, 0, 1023, 0, 100); //Serial.print("Lit: "); //Serial.print(light); //Serial.println("%"); //enter data to Lit[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Lit[m] = light; break; } } } //141 Battery Voltage ---------------------------------------------------------------------------------------------------------------- if (mydata.command == 141) { //Serial.print(" Battery Voltage: "); float volt = (float)mydata.data / 100; //Serial.print(volt); //Serial.println("V "); if (volt <= Vmin && volt > Vcrit) { //Serial.println("BATTERY VOLTAGE LOW! "); } if (volt <= Vcrit) { //Serial.println("BATTERY VOLTAGE CRITICAL! "); } if (volt >= Vfull) { //Serial.println("BATTERY IS FULL! "); } //enter data to Lit[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Volt[m] = volt * 100; break; } } } //142 Generator Voltage------------- if (mydata.command == 142) { //Serial.print(" Generator Voltage: "); float gvolt = (float)mydata.data * 16.2722 / 100; //Serial.print(Gvolt); //Serial.println("V "); //enter data to gVolt[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { gVolt[m] = gvolt * 100; break; } } } //142 Grid Voltage------------- if (mydata.command == 143) { //Serial.print(" Generator Voltage: "); float grvolt = (float)mydata.data / 100; //Serial.print(Gvolt); //Serial.println("V "); //enter data to gVolt[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { grVolt[m] = grvolt * 100; break; } } } //151 Current ------------------------------------------------------------------------------- if (mydata.command == 151) { float curr = (float)mydata.data / 1000; //Serial.print("Current: "); //Serial.print(curr); //Serial.println("Amper"); //enter data to Lit[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Curr[m] = curr * 1000; break; } } } //161 Gas Level------------------------------------------------------------------------------ if (mydata.command == 161) { int gasLev = mydata.data; //Serial.print("Gas level: "); //Serial.print(gasLev); //Serial.println(" % "); //enter data to Gaslev[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Gaslev[m] = gasLev; break; } } } //162 ----------------------------------------------------------------------------- if (mydata.command == 162 && mydata.data == 1) { //Serial.println("Battery is charging!"); } //163 RunTime -------------------------------------------------------------------------------------------------------------- if (mydata.command == 163) { //Serial.print("TimeUp: "); unsigned int daysD = mydata.data / (24 * 60); //Serial.print(day); //Serial.print("days,"); byte hoursD = (mydata.data - daysD * 24 * 60) / 60; //Serial.print(hour); //Serial.print("hours,"); byte minutesD = mydata.data - (daysD * 24 * 60 + hoursD * 60); //Serial.print(minute); //Serial.println("min"); //enter data to Tup[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Tup[m] = mydata.data; break; } } } //171 Gen Status ----------------------------------------------------------------------------- if (mydata.command == 171) { if (mydata.data == 4) { //send sms back if command came by sms----------- if (gsms == 1) { alertStr = F("GENERATOR IS ON!"); sendSMS(alertStr); gsms = 0; } //enter data to Gstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Gstat[m] = 1; break; } } } if (mydata.data == 3) { //send sms back if command came by sms----------- if (gsms == 1) { alertStr = F("GENERATOR IS OFF!"); sendSMS(alertStr); gsms = 0; } //enter data to Gstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Gstat[m] = 2; break; } } } if (mydata.data == 5) { //send sms back if command came by sms----------- if (gsms == 1) { alertStr = F("GENERATOR Startup Failure!"); sendSMS(alertStr); gsms = 0; } //enter data to Gstat[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { Gstat[m] = 3; break; } } } } //173 Water Level ----------------------------------------------------------------------------- if (mydata.command == 173) { byte wlev = mydata.data; //wlev ultrasonic sensor data, cocnvert centimeters from top of the tank to percentage, estimate data as tankshape is not taken to account! wlev = map(wlev, 0, 150, 100, 0); //change distance from top to percentage fill //Serial.print("Water level: "); //Serial.print(wLev); //Serial.println(" % "); //enter data to wLev[m] array---------------------------- for (byte m = 0; m < DevQ ; m++) { int DevID = EEPROM.get(2*m + 66, DevID); if ( DevID == mydata.device_id ) { wLev[m] = wlev; break; } } } //199 Alarm Codes--------------------------------------------------------------------------- if (mydata.command == 199) { alarmK = 1; //trigger alarmsound } //Serial.print("Got: "); //Serial.print("Device ID: "); //Serial.print(mydata.device_id); //Serial.print(" Destination ID: "); //Serial.print(mydata.destination_id); //Serial.print(" Packet ID: "); //Serial.print(mydata.packet_id); //Serial.print(" Command: "); //Serial.print(mydata.command); //Serial.print(" Data: "); //Serial.print(mydata.data); //Serial.println(); } else { /* //Serial.print("Got Foreign package: "); //Serial.print("Device ID: "); //Serial.print(mydata.device_id); //Serial.print(" Destination ID: "); //Serial.print(mydata.destination_id); //Serial.print(" Packet ID: "); //Serial.print(mydata.packet_id); //Serial.print(" Command: "); //Serial.print(mydata.command); //Serial.print(" Data: "); //Serial.print(mydata.data); //Serial.println(); */ } } } void reportDev() { mydata.command = 171; mydata.data = 3; transmitData(); //Serial.println("Transmitting packet \"REPORT GEN\""); //Serial.println("DONE"); } //Valve control-------------------------------------------------------------- void openValve() { mydata.command = 56; mydata.data = 1; transmitData(); //Serial.println("Transmitting packet \"OPEN\""); //Serial.println("DONE"); } void closeValve() { mydata.command = 56; mydata.data = 2; transmitData(); //Serial.println("Transmitting packet \"CLOSE\""); //Serial.println("DONE"); } //Switch controls------------------------------------------ void switchOFF(byte sd) { mydata.command = sd; mydata.data = 2; transmitData(); // //Serial.println("Transmitting packet \"Switch LED OFF\" to device:" +(String)destinationID + "Switch#" + (String)sd); } void switchON(byte sd) { mydata.command = sd; mydata.data = 1; transmitData(); //Serial.println("Transmitting packet \"Switch LED ON\" to device:" +(String)destinationID + "Switch#" + (String)sd); } void devDataRecover() { for (byte m = 0; m < DevQ; m++) { EEPROM.get((268 + m), rgrd[m]); //Get their registers from 268,269,...368 //Serial.print("Registered Devices:" + (String)(m) + " - "); //Serial.print(Dev[(m-1)]); //Serial.print(" - iHome ID: "); //Serial.println(rgrd[(m-1)]); delay(100); } } void transmitData() { keeloqSecure(); unsigned int unique_device_id = EEPROM.get(64, unique_device_id); mydata.device_id = unique_device_id; mydata.destination_id = destinationID; mydata.packet_id = mydata.packet_id; mydata.command = mydata.command; mydata.data = mydata.data; //Serial.print("Transmitting package: "); //Serial.print("Device ID: "); //Serial.print(mydata.device_id); //Serial.print(" Destination ID: "); //Serial.print(mydata.destination_id); //Serial.print(" Packet ID: "); //Serial.print(mydata.packet_id); //Serial.print(" Command: "); //Serial.print(mydata.command); //Serial.print(" Data: "); //Serial.print(mydata.data); //Serial.println(); ET.sendData(); rdd = 1; } void secPhone(byte k){ int hb = 615+(k*14); //0-615; 1-629 e.t.c. int hf = 615+((k+1)*14); //0-629; 1-643 e.t.c for(int i = hb;i < hf;i++){ char m; seqPhone += EEPROM.get(i, m); } } void sendSMS(String text) { for(byte h = 0; h < maxSeqPhone; h++){ secPhone(h); if(seqPhone == 0){ continue; } //Serial.println("Sending SMS to: " + String(seqPhone[h])); sendPhoneSMS(text, seqPhone); } } void sendPhoneSMS(String text, String phone) { // //Serial.println("SMS send started"); Serial3.print("AT+CMGF=1\r"); delay(100); Serial3.println("AT+CMGS=\"" + phone + "\""); delay(100); Serial3.println(text); delay(100); Serial3.println((char)26); //Serial.println("SMS send finish"); delay(100); deleteSMS(); } void deleteSMS() { //Serial.println("Delete All SMSs"); Serial3.print("AT+CMGDA=\"DEL ALL\"\n"); delay(100); } void receiveSMS() { if (!Serial3.available()) return; char currSymb = Serial3.read(); if ('\r' == currSymb) { if (isStringMessage) { tone(buzz, 3500, 200); for(byte sqp = 0; sqp < maxSeqPhone; sqp++){ secPhone(sqp); //String seqPhone = seqPhone; if (currStr.compareTo(seqPhone)) { //Serial.println("Phone number found!"); //--- if (!currStr.compareTo("Start gen")) { //Serial.println("\"Generator ON\" command received over GSM, executing..."); startGen(); gsms = 1; } else if (!currStr.compareTo("Stop gen")) { //Serial.println("\"Generator OFF\" command received over GSM, executing..."); shutGen(); gsms = 1; } else if (!currStr.compareTo("Report")) { //Serial.println("\"Report Sensors\" command received over GSM, executing..."); String report; for (byte dev = 0; dev < DevQ ; dev++) { int DevID = EEPROM.get(2*dev + 66, DevID); if (DevID != 0) { String k = F("DeviceID: "); String l = F(",Time Up [mins]: "); String m = F(",Battery Voltage [V]: "); String n = F(",Lit [%]: "); String o = F(",Current [Amps]: "); String p = F(",Gas Level [%]: "); String r = F(",Valve Status: "); String s = F(",Generator Status: "); report += k + (String)DevID + l + (String)Tup[dev] + m + (String)Volt[dev] + n + (String)Lit[dev] + o + (String)Curr[dev] + p + (String)Gaslev[dev] + r + (String)Vstat[dev] + s + (String)Gstat[dev]; } else { String s = F("No registered devices yet! Try Later..."); report = s; } } //Serial.println("Report: " + report); sendSMS(report); } else if (!currStr.compareTo("Gate operate")) { //Serial.println("\"Gate Open/Close\" command received over GSM, executing..."); gateOper(1); String s = F("GATE IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Gate door")) { //Serial.println("\"Gate Door\" command received over GSM, executing..."); gateOper(2); String s = F("GATE DOOR IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Gate curtecy light")) { //Serial.println("\"Gate Curtecy Light\" command received over GSM, executing..."); gateOper(3); String s = F("GATE CURTECY LIGHT IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Gate light")) { //Serial.println("\"Gate Light\" command received over GSM, executing..."); lightOper(1); String s = F("GATE LIGHT IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Front light")) { //Serial.println("\"Front Light\" command received over GSM, executing..."); lightOper(2); String s = F("FRONT LIGHT IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Entry light")) { //Serial.println("\"Entry Light\" command received over GSM, executing..."); lightOper(3); String s = F("ENTRY LIGHT IS OPERATED!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Valve open")) { //Serial.println("\"Valve Open\" command received over GSM, executing..."); destinationID = 10002; openValve(); gsms = 1; } else if (!currStr.compareTo("Valve close")) { //Serial.println("\"Valve Close\" command received over GSM, executing..."); destinationID = 10002; closeValve(); gsms = 1; } else if (!currStr.compareTo("Alarm on")) { //Serial.println("\"Alarm\" command received over GSM, executing..."); Siren(1); String s = F("Alarm is ON!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Alarm off")) { //Serial.println("\"Alarm\" command received over GSM, executing..."); noTone(buzz); alarmK = 0; Siren(0); SSArm(0); String s = F("Alarm is OFF!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("SS Arm")) { //Serial.println("\"SS Arm\" command received over GSM, executing..."); SSArm(1); String s = F("Security System Armed!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("SS Disarm")) { //Serial.println("\"SS Disarm\" command received over GSM, executing..."); noTone(buzz); SSArm(0); String s = F("Security System Disarmed!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("Ghost")) { //Serial.println("\"Ghost\" command received over GSM, executing..."); String s = F("GHOST MODE IS ON!"); sendPhoneSMS(s,seqPhone); } else if (!currStr.compareTo("All off")) { //Serial.println("\"All off\" command received over GSM, executing..."); //TBA String s = F("ALL OFF!"); sendPhoneSMS(s,seqPhone); } //-- break; }else{ continue; } //Serial.println("Phone number unknown!"); } //-- isStringMessage = false; //Delete SMS message Serial3.print("AT+CMGDA=\"DEL ALL\"\n"); delay(100); } else { if (currStr.startsWith("+CMT")) { isStringMessage = true; } if (currStr.startsWith("+CMGS")) { //Serial.println("SMS Delivered!"); gsmCode = 1; } if (currStr.startsWith("+CMS ERROR")) { //Serial.println("SMS Delivery ERROR!"); gsmCode = 2; } if (currStr.startsWith("NO CARRIER")) { //Serial.println("Hanged phone!"); gsmCode = 3; } } //Serial.println(currStr); //Log in the txt file String k =F("gsmlog.txt"); WriteToLog(k, currStr); currStr = ""; } else if ('\n' != currSymb) { currStr += String(currSymb); } } void SSArm(byte armStatus){ switch(armStatus){ case 0: alarmSS = 1; //Serial.println("Security System DISARMED!"); WriteToLog("seqlog.txt", "System Disarmed!"); Siren(0); SeqSensor = "0"; EEPROM.put(612, alarmSS); break; case 1: alarmSS = 2; //Serial.println("Security System ARMED!"); WriteToLog("seqlog.txt", "System Armed!"); EEPROM.put(612, alarmSS); break; } } void alarm() { if (alarmK == 1) { unsigned long currentMillis = millis(); int buz; if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; if (z != 1) { buz = 3200; z = 1; } else { buz = 1000; z = 0; } } tone(buzz, buz); } } void Siren(byte shoot){ if (shoot == 1) { alarmSS = 3; //siren triggered! byte sirenV = map(sirenVol,0,100,0,255); if(sirenOn == 1){ pinMode(siren,OUTPUT); analogWrite(siren,sirenV); //Serial.println("Siren ACTIVE!"); }else{ pinMode(siren,OUTPUT); digitalWrite(siren,LOW); //Serial.println("Siren MUTED!"); } } else{ pinMode(siren,OUTPUT); digitalWrite(siren,LOW); //Serial.println("Siren OFF!"); } } void digitalClockDisplay() { //Set timeString in the following format: "00/01/01,04:21:27+00" timeString = "\"" + (String)day() + "/" + month() + "/" + year() + "," + hour() + ":" + minute() + ":" + second() + "+" + "0" + timeZone + "\""; //Serial.println(timeString); } void printDigits(int digits) { // utility for digital clock display: prints preceding colon and leading 0 //Serial.print(":"); //if(digits < 10) //Serial.print('0'); // //Serial.print(digits); } /*-------- NTP code ----------*/ const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets time_t getNtpTime() { while (Udp.parsePacket() > 0) ; // discard any previously received packets //Serial.println("Transmit NTP Request"); sendNTPpacket(timeServer); uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = Udp.parsePacket(); if (size >= NTP_PACKET_SIZE) { //Serial.println("Receive NTP Response"); Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer unsigned long secsSince1900; // convert four bytes starting at location 40 to a long integer secsSince1900 = (unsigned long)packetBuffer[40] << 24; secsSince1900 |= (unsigned long)packetBuffer[41] << 16; secsSince1900 |= (unsigned long)packetBuffer[42] << 8; secsSince1900 |= (unsigned long)packetBuffer[43]; return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; } } //Serial.println("No NTP Response :-("); return 0; // return 0 if unable to get the time } // send an NTP request to the time server at the given address void sendNTPpacket(IPAddress &address) { // set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: Udp.beginPacket(address, 123); //NTP requests are to port 123 Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } /* void sysVolt(){ v = analogRead(Vpin); v = v*Vcoef; //747 - > 3.723V } */ void deleteDev(int devK) { for (byte r = 0; r < DevQ; r++) { int clearDev = EEPROM.get(2*r + 66,clearDev); if(clearDev == devK){ int ers = 0; EEPROM.put(r*2 + 66, ers); //clear DevID Tup[r] = 0; Volt[r] = 0; gVolt[r] = 0; grVolt[r] = 0; Temp[r] = 0; TempD[r] = 0; Lit[r] = 0; Gaslev[r] = 0; Curr[r] = 0; Vstat[r] = 0; Gstat[r] = 0; Sw1[r] = 0; Sw2[r] = 0; Sw3[r] = 0; Sw4[r] = 0; Sw5[r] = 0; Sw6[r] = 0; Sw7[r] = 0; Sw8[r] = 0; Hum[r] = 0; Press[r] = 0; Gyro[r] = 0; Alarm[r] = 0; rgrd[r] = 0; wLev[r] = 0; byte erz = 0; EEPROM.put(r + 268, erz); break; } } CLR_state[0] = 1; // save LED state //Serial.println("Device:" + devK + " Stored in EEPROM Cleared!"); devDataRecover(); } //Clear EEPROM void clearMEM(){ for(int i=0;i<= 4096;i++){ byte clearM = 0; EEPROM.put(i,clearM); } devDataRecover(); } //Clear power meter void clearMet() { //Serial.println("Stage Meter reset!"); spm = 0; EEPROM.put(103, spm); MET_state = 1; } void gsmSignal() { String simStr = ""; //simcard availability for (byte l = 0; l < 2; l++) { Serial3.print("AT+CSMINS?\r"); delay(1000); } do { char simSymb = Serial3.read(); simStr += String(simSymb); } while (Serial3.available()); String simAva = (String)simStr.charAt(24); byte gsmsim; //signal strength from sim800l gsmsim = simAva.toInt(); if (gsmsim == 1) { String csqStr = ""; //signal quality //Serial.println("Requesting GSM Signal Quality info"); for (byte l = 0; l < 2; l++) { Serial3.print("AT+CSQ\r"); delay(1000); } do { char csqSymb = Serial3.read(); csqStr += String(csqSymb); } while (Serial3.available()); String sigStr = (String)csqStr.charAt(15) + csqStr.charAt(16); byte gsmsig; //signal strength from sim800l gsmsig = sigStr.toInt(); int sigstr; //calculated signal strength in dBm if (gsmsig == 0) { sigstr = -115; } if (gsmsig == 1) { sigstr = -111; } if (gsmsig > 1 && gsmsig < 31) { sigstr = -110 + ((gsmsig - 2) * 2); } if (gsmsig > 30 && gsmsig < 99) { sigstr = -52 + (gsmsig - 31); } if (gsmsig == 99) { sigstr = 0; } sigqua = 2 * (sigstr + 100); if (sigqua > 0) { sigqua = sigqua; } else { sigqua = 0; } //Serial.println("Signal Strength: " + (String)gsmsig + " ; " + sigstr + "dBm" + " ; " + sigqua + "%"); } else { //Serial.println("Simcard is not inserted!"); sigqua = 200; //simcard is not inserted properly } } void RegDev(int regDevID) { //Register devices in array Div[m]---------------------------- for (byte m = 0; m < DevQ; m++) { int DevEID = EEPROM.get(2*m + 66, DevEID); if ( DevEID == 0 ) { EEPROM.put(m*2 + 66, regDevID); break; } if (DevEID == regDevID) { //alertStr = "Device already exist!"; break; } } //Serial.print("Registered! "); //Serial.println(mydata.device_id); } void mySwitchSend(long data, byte bits){ mySwitch.send(data, bits); }

Updated firmware and libraries:

UWS_v1.4_270417

This need to be decompressed into the root of the SD card:

iHome_SD_V001_28042017

To implement all the functions of the "iHome" intelligent management system  you will need to purchase a MEGASHIELD mainboard from my store  little later.

Shield is in the final stage of development and will be released very soon and distributed over this site.

Discussions here and lower in the comments section.....

 

Previous versions:

V1.5.6.beta

Smith_Tofig

11 thoughts on “Home Intelligent Management System “iHome”

  1. “Я не совсем розетку делаю, хочу перевезти сайт умного дома частично на ESP – http://www.voltrans.az/?page_id=1969
    Интересно!, a можно узнать зачем и почему частично, а не весь?
    Веб сервер разве не на MEGA 2560 реализован и там уже все 256кило заканчиваются?

  2. Пробовал, в моей сети грузиться очень медленно, работать с ней практически нереально.
    Не пробовали пропатченные библиотеки Ethernet как описано тут https://geektimes.ru/post/259898/
    Пример проекта с патченными библитотеками для IDE 1.6.5: https://hi-lab.ru/arduino-mega-server/details/download

    1. Пробовал, с пропатченными и по методу, который вы предложили грузится в 3 раза дольше. В моей сети главная страница грузится за 20секунд, самая емкая за 37 секунд, сложностей в работе не испытываю, но если у вас получится оптимизировать, то с радостьюприму вашу верию!
      На данный момент работаю над переходом с эзернет шилда на ESP8266, грузится за считанные секунды, ждите обновлений.

  3. У вас интересный проект. Что нового по переходу на esp8266? Планируется ли портирование на ESP32?

Leave a Reply

Your email address will not be published. Required fields are marked *

wp-puzzle.com logo