Delete pi-server.py
This commit is contained in:
parent
d36099db37
commit
e4682e8aac
1 changed files with 0 additions and 477 deletions
477
pi-server.py
477
pi-server.py
|
|
@ -1,477 +0,0 @@
|
|||
#! /usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
"""
|
||||
Handle UDP packets from the cosmic pi and log then
|
||||
julian.lewis lewis.julian@gmail.com 26/Feb/2016
|
||||
"""
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import select
|
||||
import serial
|
||||
import time
|
||||
import traceback
|
||||
import os
|
||||
import termios
|
||||
import fcntl
|
||||
import re
|
||||
import ast
|
||||
from optparse import OptionParser
|
||||
import httplib, urllib
|
||||
|
||||
# Handle keyboard input
|
||||
|
||||
class KeyBoard(object):
|
||||
|
||||
def __init__(self):
|
||||
self.fd = sys.stdin.fileno()
|
||||
|
||||
def echo_off(self):
|
||||
self.oldterm = termios.tcgetattr(self.fd)
|
||||
self.newattr = termios.tcgetattr(self.fd)
|
||||
self.newattr[3] = self.newattr[3] & ~termios.ICANON & ~termios.ECHO
|
||||
termios.tcsetattr(self.fd, termios.TCSANOW, self.newattr)
|
||||
self.oldflags = fcntl.fcntl(self.fd, fcntl.F_GETFL)
|
||||
fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK)
|
||||
|
||||
def echo_on(self):
|
||||
termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.oldterm)
|
||||
fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags)
|
||||
|
||||
def test_input(self):
|
||||
res = False
|
||||
|
||||
try:
|
||||
c = sys.stdin.read(1)
|
||||
if c == '>':
|
||||
res = True
|
||||
except IOError: pass
|
||||
return res
|
||||
|
||||
class Socket_io(object):
|
||||
|
||||
def __init__(self,ipport):
|
||||
try:
|
||||
self.sik = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.sik.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||
self.sik.setblocking(0)
|
||||
self.sik.bind(("",ipport))
|
||||
|
||||
except Exception, e:
|
||||
msg = "Exception: Can't open Socket: %s" % (e)
|
||||
print msg
|
||||
sys.exit(1)
|
||||
|
||||
def recv_event_pkt(self):
|
||||
try:
|
||||
available = select.select([self.sik], [], [], 1)
|
||||
if available[0]:
|
||||
recv = self.sik.recvfrom(2048)
|
||||
return recv
|
||||
|
||||
except Exception, e:
|
||||
msg = "Exception: Can't recvfrom: %s" % (e)
|
||||
print msg
|
||||
|
||||
return ["",""]
|
||||
|
||||
def close(self):
|
||||
self.sik.close()
|
||||
|
||||
# Send notifications to registered mobile phones
|
||||
# Currently I am using pushover and the client has to install the
|
||||
# pushover app and register a user and application token.
|
||||
# The client supplies the keys on the cosmic pi client launch command line
|
||||
|
||||
class Notifications(object):
|
||||
|
||||
def send_ntf(self,kyp,msg):
|
||||
|
||||
nstr = kyp.split('-')
|
||||
|
||||
self.conn = httplib.HTTPSConnection("api.pushover.net:443")
|
||||
|
||||
self.conn.request( "POST", "/1/messages.json",
|
||||
urllib.urlencode({ "token" : nstr[1],
|
||||
"user" : nstr[0],
|
||||
"sound" : "Cosmic",
|
||||
"message": msg}),
|
||||
{ "Content-type": "application/x-www-form-urlencoded" })
|
||||
|
||||
self.conn.getresponse()
|
||||
|
||||
# Each cosmic pi client can register with the server
|
||||
# We check package sequence numbers, hardware status
|
||||
|
||||
class Registrations(object):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.reg = {"Ipa":"s","Sqn":0,"Pat":"s","Ntf":False,"Htu":"0","Bmp":"0","Acl":"0","Mag":"0"}
|
||||
self.regs = []
|
||||
|
||||
def get_len(self):
|
||||
return len(self.regs)
|
||||
|
||||
def get_index_by_value(self,knam,kval):
|
||||
if self.reg.has_key(knam):
|
||||
for i in range(0,len(self.regs)):
|
||||
if self.regs[i][knam] == kval:
|
||||
return i
|
||||
return False
|
||||
|
||||
def get_reg_by_value(self,knam,kval):
|
||||
if self.reg.has_key(knam):
|
||||
for i in range(0,len(self.regs)):
|
||||
if self.regs[i][knam] == kval:
|
||||
return self.regs[i]
|
||||
return False
|
||||
|
||||
def get_reg_by_index(self,indx):
|
||||
if indx in range(0,len(self.regs)):
|
||||
return self.regs[indx]
|
||||
return False
|
||||
|
||||
def get_create_reg(self,knam,kval):
|
||||
r = self.get_reg_by_value(knam,kval)
|
||||
if r == False:
|
||||
i = len(self.regs)
|
||||
self.regs.append(self.reg.copy())
|
||||
self.regs[i][knam] = kval
|
||||
return self.regs[i]
|
||||
else:
|
||||
return r
|
||||
|
||||
def set_reg(self,r):
|
||||
i = self.get_index_by_value("Ipa",r["Ipa"])
|
||||
if i == False:
|
||||
return False
|
||||
self.regs[i] = r.copy()
|
||||
return True
|
||||
|
||||
# This is the event object, it builds a dictionary from incomming json strings
|
||||
# and provides access to the dictionary entries containing the data for each field.
|
||||
|
||||
class Event(object):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# These are the UDP packets containing json strings we are expecting
|
||||
|
||||
self.HTU = { "Tmh":"0.0","Hum":"0.0" }
|
||||
self.BMP = { "Tmb":"0.0","Prs":"0.0","Alb":"0.0" }
|
||||
self.VIB = { "Vax":"0","Vcn":"0" }
|
||||
self.MAG = { "Mgx":"0.0","Mgy":"0.0","Mgz":"0.0" }
|
||||
self.MOG = { "Mox":"0.0","Moy":"0.0","Moz":"0.0" }
|
||||
self.ACL = { "Acx":"0.0","Acy":"0.0","Acz":"0.0" }
|
||||
self.AOL = { "Aox":"0.0","Aoy":"0.0","Aoz":"0.0" }
|
||||
self.LOC = { "Lat":"0.0","Lon":"0.0","Alt":"0.0" }
|
||||
self.TIM = { "Upt":"0","Frq":"0","Sec":"0" }
|
||||
self.STS = { "Qsz":"0","Mis":"0","Ter":"0","Htu":"0","Bmp":"0","Acl":"0","Mag":"0","Gps":"0" }
|
||||
self.EVT = { "Evt":"0","Frq":"0","Tks":"0","Etm":"0.0","Adc":"[[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0]]" }
|
||||
self.DAT = { "Dat":"s" }
|
||||
|
||||
# Add ons
|
||||
|
||||
self.DAT = { "Dat":"s" } # Date
|
||||
self.SQN = { "Sqn":"0" } # Sequence number
|
||||
self.PAT = { "Pat":"s","Ntf":"0" } # Pushover application token
|
||||
|
||||
# Now build the main dictionary with one entry for each json string we will process
|
||||
|
||||
self.recd = { "HTU":self.HTU, "BMP":self.BMP, "VIB":self.VIB, "MAG":self.MAG, "MOG":self.MOG,
|
||||
"ACL":self.ACL, "AOL":self.AOL, "LOC":self.LOC, "TIM":self.TIM, "STS":self.STS,
|
||||
"EVT":self.EVT, "DAT":self.DAT, "SQN":self.SQN, "PAT":self.PAT }
|
||||
|
||||
self.newpat = False
|
||||
self.newsqn = False
|
||||
|
||||
# Convert the incomming json strings into entries in the dictionary
|
||||
|
||||
def parse(self, line): # parse the incomming json strings from arduino
|
||||
nstr = line.replace('\n','') # Throw away <crtn>, we dont want them
|
||||
try:
|
||||
dic = ast.literal_eval(nstr) # Build a dictionary entry
|
||||
kys = dic.keys() # Get key names, the first is the address
|
||||
if self.recd.has_key(kys[0]): # Check we know about records with this key
|
||||
self.recd[kys[0]] = dic[kys[0]] # and put it in the dictionary at that address
|
||||
|
||||
if kys[0] == "PAT":
|
||||
self.newpat = True
|
||||
|
||||
if kys[0] == "SQN":
|
||||
self.newsqn = True
|
||||
|
||||
except Exception, e:
|
||||
pass # Didnt understand, throw it away
|
||||
|
||||
# Here we just return dictionaries
|
||||
|
||||
def get_vib(self):
|
||||
return self.recd["VIB"]
|
||||
|
||||
def get_tim(self):
|
||||
return self.recd["TIM"]
|
||||
|
||||
def get_loc(self):
|
||||
return self.recd["LOC"]
|
||||
|
||||
def get_sts(self):
|
||||
return self.recd["STS"]
|
||||
|
||||
def get_bmp(self):
|
||||
return self.recd["BMP"]
|
||||
|
||||
def get_acl(self):
|
||||
return self.recd["ACL"]
|
||||
|
||||
def get_mag(self):
|
||||
return self.recd["MAG"]
|
||||
|
||||
def get_htu(self):
|
||||
return self.recd["HTU"]
|
||||
|
||||
def get_evt(self):
|
||||
return self.recd["EVT"]
|
||||
|
||||
def get_dat(self):
|
||||
return self.recd["DAT"]
|
||||
|
||||
def get_sqn(self):
|
||||
return self.recd["SQN"]
|
||||
|
||||
def get_pat(self):
|
||||
return self.recd["PAT"]
|
||||
|
||||
|
||||
def main():
|
||||
use = "Usage: %prog [--port=4901 --odir=/tmp]"
|
||||
parser = OptionParser(usage=use, version="cosmic_pi_server version 1.0")
|
||||
parser.add_option("-p", "--port", help="Server portnumber", dest="ipport", type="int", default="15443")
|
||||
parser.add_option("-d", "--debug", help="Debug Option", dest="debug", default=False, action="store_true")
|
||||
parser.add_option("-o", "--odir", help="Path to log directory", dest="logdir", default="/tmp")
|
||||
parser.add_option("-n", "--nolog", help="Event Logging", dest="logflg", default=True, action="store_false")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
ipport = options.ipport
|
||||
logdir = options.logdir
|
||||
debug = options.debug
|
||||
logflg = options.logflg
|
||||
|
||||
print ""
|
||||
print "cosmic_pi server running, hit '>' for commands\n"
|
||||
|
||||
print "options (Server Port number) port:%d" % ipport
|
||||
print "options (Logging directory) odir:%s" % logdir
|
||||
print "options (Event logging) log: %s" % logflg
|
||||
|
||||
file_name = "/tmp/pi-server-lock"
|
||||
fp = open(file_name, 'w')
|
||||
try:
|
||||
fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except Exception, e:
|
||||
print "Lock file:%s is in use" % (file_name)
|
||||
print "Only one instance of the server can run at any one time"
|
||||
print "Please kill the other instance or remove the lock file"
|
||||
sys.exit(1)
|
||||
|
||||
ts = time.strftime("%d-%b-%Y-%H-%M-%S",time.gmtime(time.time()))
|
||||
lgf = "%s/cosmicpi-logs/%s.log" % (logdir,ts)
|
||||
dir = os.path.dirname(lgf)
|
||||
if not os.path.exists(dir):
|
||||
os.makedirs(dir)
|
||||
try:
|
||||
log = open(lgf, "w");
|
||||
except Exception, e:
|
||||
msg = "Exception: Cant open log file: %s" % (e)
|
||||
print "Fatal: %s" % msg
|
||||
sys.exit(1)
|
||||
|
||||
if options.debug:
|
||||
print "\n"
|
||||
print "Log file is: %s" % lgf
|
||||
|
||||
kbrd = KeyBoard()
|
||||
kbrd.echo_off()
|
||||
|
||||
sio = Socket_io(ipport)
|
||||
|
||||
evt = Event()
|
||||
|
||||
nfs = Notifications()
|
||||
|
||||
reg = Registrations()
|
||||
|
||||
newsqn = False
|
||||
badhard = False
|
||||
|
||||
try:
|
||||
while(True):
|
||||
|
||||
recv = sio.recv_event_pkt()
|
||||
if len(recv[0]):
|
||||
|
||||
print "FromIP:%s" % (str(recv[1]))
|
||||
|
||||
nstr = recv[0].split('*')
|
||||
for i in range(0,len(nstr)):
|
||||
nstr[i] = nstr[i].replace('\n','')
|
||||
#print "Parse:%s" % nstr[i]
|
||||
evt.parse(nstr[i])
|
||||
|
||||
if nstr[0].find("EVT") != -1:
|
||||
newsqn = True
|
||||
evd = evt.get_evt()
|
||||
tim = evt.get_tim()
|
||||
dat = evt.get_dat()
|
||||
print
|
||||
print "Cosmic Event..: Evt:%s Frq:%s Tks:%s Etm:%s" % (evd["Evt"],evd["Frq"],evd["Tks"],evd["Etm"])
|
||||
print "Adc[[Ch0][Ch1]: Adc:%s" % (str(evd["Adc"]))
|
||||
print "Time..........: Upt:%s Sec:%s" % (tim["Upt"],tim["Sec"])
|
||||
print "Date..........: Dat:%s" % (dat["Dat"])
|
||||
|
||||
elif nstr[0].find("VIB") != -1:
|
||||
newsqn = True
|
||||
mag = evt.get_mag()
|
||||
vib = evt.get_vib()
|
||||
tim = evt.get_tim()
|
||||
acl = evt.get_acl()
|
||||
sqn = evt.get_sqn()
|
||||
print
|
||||
print "Vibration.....: Vax:%s Vcn:%s Sqn:%d" % (vib["Vax"],vib["Vcn"],sqn["Sqn"])
|
||||
print "Time..........: Sec:%s" % (tim["Sec"])
|
||||
print "Accelarometer.: Acx:%s Acy:%s Acz:%s" % (acl["Acx"],acl["Acy"],acl["Acz"])
|
||||
print "Magnatometer..: Mgx:%s Mgy:%s Mgz:%s" % (mag["Mgx"],mag["Mgy"],mag["Mgz"])
|
||||
|
||||
elif nstr[0].find("HTU") != -1:
|
||||
newsqn = True
|
||||
tim = evt.get_tim()
|
||||
bmp = evt.get_bmp()
|
||||
htu = evt.get_htu()
|
||||
loc = evt.get_loc()
|
||||
print
|
||||
print "Barometer.....: Tmb:%s Prs:%s Alb:%s" % (bmp["Tmb"],bmp["Prs"],bmp["Alb"])
|
||||
print "Humidity......: Tmh:%s Hum:%s Alt:%s" % (htu["Tmh"],htu["Hum"],loc["Alt"])
|
||||
print "Time..........: Sec:%s\n" % (tim["Sec"])
|
||||
|
||||
elif nstr[0].find("PAT") != -1:
|
||||
pat = evt.get_pat()
|
||||
print
|
||||
print "Notification..: Pat:%s Ntf:%s" % (pat["Pat"],pat["Ntf"])
|
||||
if pat["Ntf"] == True:
|
||||
msg = "Your are now registered to recieve pi server notifications"
|
||||
else:
|
||||
msg = "You will no longer recieve pi server notifications"
|
||||
|
||||
nfs.send_ntf(pat["Pat"],msg)
|
||||
|
||||
r = reg.get_create_reg("Ipa",str(recv[1]))
|
||||
r["Pat"] = pat["Pat"]
|
||||
r["Ntf"] = pat["Ntf"]
|
||||
reg.set_reg(r)
|
||||
|
||||
elif nstr[0].find("STS") != -1:
|
||||
sts = evt.get_sts()
|
||||
r = reg.get_create_reg("Ipa",str(recv[1]))
|
||||
r["Htu"] = sts["Htu"]
|
||||
r["Bmp"] = sts["Bmp"]
|
||||
r["Acl"] = sts["Acl"]
|
||||
r["Mag"] = sts["Mag"]
|
||||
r["Gps"] = sts["Gps"]
|
||||
reg.set_reg(r)
|
||||
|
||||
msg = ""
|
||||
if int(r["Htu"]) == 0:
|
||||
msg = msg + "Htu down: "
|
||||
if int(r["Bmp"]) == 0:
|
||||
msg = msg + "Bmp down: "
|
||||
if int(r["Acl"]) == 0:
|
||||
msg = msg + "Acl down: "
|
||||
if int(r["Mag"]) == 0:
|
||||
msg = msg + "Mag down: "
|
||||
if int(r["Gps"]) == 0:
|
||||
msg = msg + "Gps down: "
|
||||
|
||||
if len(msg) > 0:
|
||||
if badhard == False:
|
||||
badhard = True
|
||||
if r["Ntf"]:
|
||||
nfs.send_ntf(pat["Pat"],msg)
|
||||
print "Hardware error:%s %s" % (str(recv[1],msg))
|
||||
else:
|
||||
if badhard == True:
|
||||
badhard = False
|
||||
msg = "Hardware OK again"
|
||||
if r["Ntf"]:
|
||||
nfs.send_ntf(pat["Pat"],msg)
|
||||
print "%s:%s" % (msg,str(recv[1]))
|
||||
if newsqn:
|
||||
newsqn = False
|
||||
sqn = evt.get_sqn()
|
||||
r = reg.get_create_reg("Ipa",str(recv[1]))
|
||||
j = int(r["Sqn"])
|
||||
i = int(sqn["Sqn"])
|
||||
if i != j+1 and j != 0:
|
||||
msg = "Sequence error: %s %d-%d" % (str(recv[1],i,j))
|
||||
print msg
|
||||
if r["Ntf"]:
|
||||
nfs.send_ntf(pat["Pat"],msg)
|
||||
|
||||
r["Sqn"] = i
|
||||
reg.set_reg(r)
|
||||
|
||||
if logflg:
|
||||
line = "%s - %s" % (str(recv[0]),str(recv[1]))
|
||||
log.write(line)
|
||||
log.write("\n\n")
|
||||
|
||||
if kbrd.test_input():
|
||||
kbrd.echo_on()
|
||||
print "\n"
|
||||
cmd = raw_input(">")
|
||||
|
||||
if cmd.find("h") != -1:
|
||||
print "Commands: h=help, r=registrations, s=status q=quit"
|
||||
|
||||
if cmd.find("q") != -1:
|
||||
break
|
||||
|
||||
if cmd.find("s") != -1:
|
||||
print "Server Status"
|
||||
print "Log file......:%s" % (lgf)
|
||||
print "Registrations.:%d" % (reg.get_len())
|
||||
|
||||
if cmd.find("r") != -1:
|
||||
k = reg.get_len()
|
||||
if k>0:
|
||||
print "Client registrations and status"
|
||||
for i in range(0,k):
|
||||
r = reg.get_reg_by_index(i)
|
||||
print "Idx:%d Ipa:%s Pat:%s Sqn:%d Ntf:%d" % (i,r["Ipa"],r["Pat"],r["Sqn"],r["Ntf"])
|
||||
print "Idx:%d Htu:%s Bmp:%s Acl:%s Mag:%s Gps:%s" % (i,r["Htu"],r["Bmp"],r["Acl"],r["Mag"],r["Gps"])
|
||||
print ""
|
||||
kbrd.echo_off()
|
||||
|
||||
ts = time.strftime("%d/%b/%Y %H:%M:%S",time.gmtime(time.time()))
|
||||
s = "cosmic_pi_server:[%s]\r" % (ts)
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
|
||||
except Exception, e:
|
||||
msg = "Exception: main: %s" % (e)
|
||||
print "Fatal: %s" % msg
|
||||
|
||||
finally:
|
||||
kbrd.echo_on()
|
||||
print "Quitting ..."
|
||||
log.close()
|
||||
sio.close()
|
||||
time.sleep(1)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
main()
|
||||
|
||||
Loading…
Reference in a new issue