Weekend project : smart Power Distribution Unit

Posted: 7 Januari 2018 in Otomasi dan Robotika, programming

Assalamu’alaikum Wr. Wb.

mau nulis nih. project yang lama terbengkalai yaitu ketika server cctv saya di pabrik ngehang dan butuh restart power manual sehingga butuh waktu sampai senin datang ke pabrik buat restart. bayangkan berapa jam downtime nya kalau down sejak jum’at malam ? kadang2 downnya sabtu sih. dan memang server yang cctv kadang butuh restart manual power source nya. hal ini yang melatar belakangi saya bikin smart PDU / Power Distribution Unit. oke di pasaran sudah ada sih.. yap merk APC. bisa merestart dengan meremote IP APC tersebut.

fiture remote restart

fiture remote restart.

saya mau  bikin hal yang sama atau lebih baik sedikit dalam segi feature. kalau pdu ini harus di restart dengan mengaksesnya terlebih dahulu. saya mau biki smart PDU dengan fitur

1. autoreset power bila target IP tidak merespon

2. kirim email notifikasi bila target IP telah direset power relaynya

3. simpan log untuk mengentahui catatan PDU restart dan responnya untuk investigasi kemudian hari

 

detailnya sepertinya dalam skema dan code. mungkin kurang menarik ya. tapi buat dokumentasi.

 

notif email

notif email

 

coding arduino node mcu

untuk detail instalasi dll bisa merefer ke node mcu weather logger saya kemarin

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>


WiFiUDP Udp;
byte localUdpPort = 80;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char  replyPacket[255];



//untuk server
const char* ssid = "tarecha";
const char* ssid2 = "aiocyber";
const byte buzzerPin = D8;
const byte relayPin1 = D1;
const byte relayPin2 = D2;
const byte inputPin = D7;
const char* password = "12345678a";
const String aHostname = "N3";
boolean relayStatus1 = HIGH;
boolean relayStatus2 = HIGH;
String infoNode = "";

void setup()
{
  
  pinMode(LED_BUILTIN, OUTPUT);   
  pinMode(relayPin1, OUTPUT);   
  pinMode(relayPin2, OUTPUT); 
  pinMode(buzzerPin, OUTPUT); 
  pinMode(inputPin, INPUT);
  digitalWrite(relayPin1,HIGH);
  digitalWrite(relayPin2,HIGH);
  
  Serial.begin(9600);
  
  Serial.println("start");
  WiFi.begin(ssid, password);
  //WiFi.begin(ssid2);
  //bagian setup wifi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.mode(WIFI_STA);
  WiFi.hostname(aHostname);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");

  }
  Serial.println(" connected");
  Udp.begin(localUdpPort);
  infoNode = (String)"Restart reason : " + ESP.getResetReason().c_str() + "\n MAC : " + WiFi.macAddress().c_str() + "\n Hostname : " + WiFi.hostname().c_str() + "\n Signal Stringth : " + WiFi.RSSI() +
             "\n Local IP : " + WiFi.localIP().toString().c_str() + "\n Port : " + localUdpPort + "\n CPU Freq : " + String(ESP.getCpuFreqMHz()) + " MHz\n Sketch Size : " + ESP.getSketchSize()
             + "\n Free Space Sketch Size : " + ESP.getFreeSketchSpace();



  Serial.println(infoNode);


  buzzerlampu();
}
void lampu()
{
   digitalWrite(LED_BUILTIN, LOW); 
   delay(500);  
   digitalWrite(LED_BUILTIN, HIGH); 
   delay(5); 
}
void buzzerlampu()
{
  digitalWrite(LED_BUILTIN, LOW); 
  digitalWrite(buzzerPin, HIGH);   
  delay(500);                      
  digitalWrite(LED_BUILTIN, HIGH);  
  digitalWrite(buzzerPin, LOW); 
  delay(500);   
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(buzzerPin, HIGH);
  delay(500);                   
  digitalWrite(LED_BUILTIN, HIGH);  
  digitalWrite(buzzerPin, LOW);
  delay(500);
                     
}




void loop()
{

  
 if (relayStatus1)
 {
   digitalWrite(relayPin1,HIGH);
 }
 else
 {
   digitalWrite(relayPin1,LOW);
 }
 if (relayStatus2)
 {
   digitalWrite(relayPin2,HIGH);
 }
 else
 {
   digitalWrite(relayPin2,LOW);
 }
 requestHandler();

}

void resetR1()
{
  digitalWrite(relayPin1,HIGH);
  delay(1000);
   digitalWrite(relayPin1,LOW);
  delay(10000);
  digitalWrite(relayPin1,HIGH);
  delay(1000);
  
}
void resetR2()
{
   digitalWrite(relayPin2,HIGH);
  delay(1000);
   digitalWrite(relayPin2,LOW);
  delay(10000);
  digitalWrite(relayPin2,HIGH);
  delay(1000);
}

void requestHandler()
{
  int packetSize = Udp.parsePacket();
  String perintah = "";
  if (packetSize)
  {
    // receive incoming UDP packets
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 255);
    if (len > 0)
    {
       incomingPacket[len] = 0;
    }
    Serial.printf("UDP packet contents: %s\n", incomingPacket);
    if (incomingPacket[0] == 'a') //get data
    {
      relayStatus1 = LOW;
      perintah = "Matikan Relay 1";
        
    }
    else if (incomingPacket[0] == 'b') //get info sensor
    {
      relayStatus1 = HIGH;
      perintah = "Hidupkan Relay 1";
        
    }
     else if (incomingPacket[0] == 'd') //get info sensor
    {
      relayStatus2 = LOW;
      perintah = "Matikan Relay 2";
        
    }
     else if (incomingPacket[0] == 'e') //get info sensor
    {
      relayStatus2 = HIGH;
      perintah = "Hidupkan Relay 2";
        
    }
         else if (incomingPacket[0] == 'c') //get info sensor
    {
       resetR1();
       perintah = "Reset Relay 1";
        
    }
         else if (incomingPacket[0] == 'f') //get info sensor
    {
      resetR2();
       perintah = "Reset Relay 2";
        
    }
    else if (incomingPacket[0] == 'r') //perintah restart
    {
      perintah = (String)"Terima udp perintah restart dari "+ Udp.remoteIP().toString().c_str();
      perintah.toCharArray(replyPacket, 255);
      Serial.println(perintah);
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.write(replyPacket);
      Udp.endPacket();
      digitalWrite(buzzerPin, HIGH);    
      digitalWrite(LED_BUILTIN, LOW);    
      delay(10000); 
      ESP.restart();
    }
     else if (incomingPacket[0] == 'i') //get info sensor
    {
      perintah = infoNode;
    }
    else
    {
      perintah = "masuk else";
      
    }
    perintah.toCharArray(replyPacket, 255);
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(replyPacket);
    Udp.endPacket();
    Serial.printf("isi reply packet %s\n", replyPacket);
    buzzerlampu(); //nyalakan lampu biru setiap kirim data

  }


}
<span style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" data-mce-type="bookmark" class="mce_SELRES_start"></span>

untuk pythonnya berikut. oh ya install dlu pyping ya. silahkan cari cara installnya. habis download packagenya. exstrak. masuk foldernya pakai cmd.
python setup.py install

import socket
import sys
import datetime
import time
import urllib2
import urllib
import math
import smtplib
import pyping
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

fromaddr = "email@gmail.com"
password = "coba ya"
port = 587
#toaddr = ['mtarecha@aio.co.id','mwibowo@aio.co.id']
toaddr = ['mtarecha@aio.co.id']
mailserver ='smtp.gmail.com'

# a matikan relay 1
# b hidupkan relay 1
# c reset relay 1
# d matikan relay 2
# e hidupkan relay 2
# f reset relay 2
emailalertenable = True
batasPacketLost = 60 #batas berapa kali time out baru restart
timeoutset = 100 #1000 ms / 1 detik
pingCount = 100
targetIP1 = "192.168.3.199"
targetIP2 = "192.168.3.199"
UDP_IP = "192.168.3.180"
UDP_PORT = 80
pingeveryseconds = 600 #ping tiap 600 detik atau 5 menit memberi kesempatan server ready untuk
#ping lagi setelah 5 menit. kalau terlalu cepat nanti sebelum siap restart terus



print "Power Relay IP :"+ UDP_IP
print "Power Relay Port :", UDP_PORT
print "Target IP 1 : "+ targetIP1
print "Target IP 2 : "+ targetIP2
statusResetPower1 = False
statusResetPower2 = False
statusNodeNotConnected = False
lastseennode = datetime.datetime.now()   

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.settimeout(20) #dalam 10 detik setelah kirim tunggu data, kalau lewat bypass

def kirimPerintah(pesan):     
        sock.sendto(pesan, (UDP_IP, UDP_PORT))
        reply = sock.recvfrom(1024)[0]
        lastseennode = datetime.datetime.now()            
        return 'Nodesensor reply : ' + str(reply) +' at '+curtime

def kirimEmail(isiemail,subject):
        if emailalertenable :
                try :
                        msg = MIMEMultipart()
                        msg['From'] = fromaddr
                        msg['To'] = ", ".join(toaddr)
                        msg['Subject'] = subject
                        server = smtplib.SMTP(mailserver,port)                                        
                        server.login(fromaddr,password)
                        body = isiemail
                        msg.attach(MIMEText(body, 'plain'))
                        text = msg.as_string()
                        pesan = str(server.sendmail(fromaddr, toaddr, text))
                        if pesan=='{}' :
                                 print 'berhasil kirim email : '+isiemail
                        else : 
                                 print 'gagal kirim email'
                        server.quit()
                except Exception as e:
                        print 'Error Message '+ str(e)
                        print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
                        print "General Error Unexpected error:", sys.exc_info()[0]

def saveLog(data):
        with open('logsmartpdu.txt','a') as file:
                file.writelines(data+'\n')
        print 'Berhasil save log : '+data
                               

while True:
         
        try :
                curmin = datetime.datetime.now().time().minute
                cursec = datetime.datetime.now().time().second
                curtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    
                print '--------------------------------------------------------'
                print curtime
                print 'Mulai ping Relay 1 dengan IP : '+targetIP1
                lostIP1 = pyping.ping(targetIP1, timeout=timeoutset, count=pingCount).packet_lost        
                if lostIP1 > batasPacketLost:
                        print kirimPerintah('c')
                        #reset
                        #sleep 300 detik / menit untuk ulang ping lagi dan nunggu waktu server cctv ready                        
                        statusResetPower1 = True
                        emailtext = 'Relay 1 dengan IP '+str(targetIP1)+' ping timeout sebanyak '+str(lostIP1)+' dari '+str(pingCount)+ ' pada '+ curtime +' telah di reset'
                        kirimEmail(emailtext,'Smart PDU - Reset Relay 1')
                        print 'Reset Relay 1'
                        saveLog(emailtext)
                        #time.sleep(300)
                        
                else:
                        #print kirimPerintah('b')
                        print 'Ping IP 1 : '+targetIP1+' OK'
                        #hidupkan
                        if statusResetPower1:
                                emailtext = 'Relay 1 dengan IP '+str(targetIP1)+' sudah aktif normal pada '+curtime
                                kirimEmail(emailtext,'Smart PDU - Relay 1 back to normal')
                                statusResetPower1 = False
                                saveLog(emailtext)
                print 'Mulai ping Relay 2 dengan IP : '+targetIP2
                lostIP2 = pyping.ping(targetIP1, timeout=timeoutset, count=pingCount).packet_lost               
                if lostIP2 > batasPacketLost:
                        print kirimPerintah('f')
                        #reset
                        #sleep 300 detik / menit untuk ulang ping lagi dan nunggu waktu server cctv ready                        
                        statusResetPower2 = True
                        emailtext = 'Relay 2 dengan IP '+str(targetIP2)+' ping timeout sebanyak '+str(lostIP2)+' dari '+str(pingCount)+ ' pada '+ curtime +' telah di reset'
                        kirimEmail(emailtext,'Smart PDU - Reset Relay 2')
                        print 'Reset Relay 2'
                        saveLog(emailtext)
                        #time.sleep(300)
                else:
                        #print kirimPerintah('e')
                        print 'Ping IP 2 : '+targetIP2+' OK'
                        #hidupkan
                        if statusResetPower2:
                                emailtext = 'Relay 2 dengan IP '+str(targetIP2)+' sudah aktif normal pada '+curtime
                                kirimEmail(emailtext,'Smart PDU - Relay 2 back to normal')
                                statusResetPower2 = False
                                saveLog(emailtext)
                                
                if statusNodeNotConnected :
                        emailtext = 'Node Konek Pada '+curtime
                        kirimEmail(emailtext,'Smart PDU - Node back to normal connected')
                        statusNodeNotConnected = False
                        saveLog(emailtext)
                        print emailtext
          
        except urllib2.HTTPError:
                print 'Tidak konek server'
        except urllib2.URLError:
                print 'URL Salah'
                
        except socket.error as a:
                print 'Tidak konek node '+str(a)
                statusNodeNotConnected = True 
                curmin = datetime.datetime.now().time().minute
                cursec = datetime.datetime.now().time().second
                #curhour = datetime.datetime.now().time().hour
                curtimelastseen = datetime.datetime.now()
                lastseensience = curtimelastseen - lastseennode                               
                print 'Lastseen Node '+str(lastseennode.strftime('%Y-%m-%d %H:%M:%S'))+ ' is '+str(lastseensience)[:-7]+' ago'
                if (curmin < 10) :
                
                        try :
                                if emailalertenable :                                        
                                        msg = MIMEMultipart()
                                        msg['From'] = fromaddr
                                        msg['To'] = ", ".join(toaddr)
                                        msg['Subject'] = "Smart Reset PDU - Disconnected Node"
                                        server = smtplib.SMTP(mailserver,port)                                        
                                        server.login(fromaddr,password)
                                        body = "Node "+UDP_IP+" tidak konek, Lastseen "+str(lastseennode.strftime('%Y-%m-%d %H:%M:%S'))+ ' is '+str(lastseensience)[:-7]+' ago'
                                                           
                                        msg.attach(MIMEText(body, 'plain'))
                                        text = msg.as_string()
                                        pesan = str(server.sendmail(fromaddr, toaddr, text))
                                        if pesan=='{}' :
                                                print 'berhasil kirim email : '+body
                                        else : 
                                                print 'gagal kirim email'
                                        server.quit()
                                        saveLog(body)
                        except Exception as e:
                                print 'Error Message '+ str(e)
                                print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
                                print "General Error Unexpected error:", sys.exc_info()[0]
                                #tidak pernah exit karena kalau tidak konek dilewati dan ngulang
                                #5 detik kemudian
                                #sys.exit()
        except Exception as e:
                print 'Error Message '+ str(e)
                print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
                print "General Error Unexpected error:", sys.exc_info()[0]
        time.sleep(pingeveryseconds)

Tinggalkan Balasan

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Foto Google+

You are commenting using your Google+ account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s