机房环境监测服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
9.5 KiB

from .models import Spot, Envdata, Alarm, Alarmset, Sms, Sendlog, Device
from django.db.models.aggregates import Count
from datetime import datetime, timedelta
from hashlib import sha1
from .sms import sendSMS
from .mail import sendmail
SECRET_KEY = '@This is a Secret $tr!'
SEND_TIMES = {}
FIRST_ALM_TIME = {}
COMMAND_QUEUE = []
def deal_post(postdata):
spot = None
try:
sn = postdata['sn']
spot = Spot.objects.get(sn=sn)
errcode = int(postdata['errcode'])
if postdata['electricity'] == 'True':
electricity = 1
else:
electricity = 0
fire = int(postdata['fire'])
if postdata['water'] == 'True':
water = 1
else:
water = 0
temperature = float(postdata['temperature'])
humidity = float(postdata['humidity'])
save_data(spot,errcode,electricity,fire,water,temperature,humidity)
except:
# record data fail
return None
if errcode > 0:
errvalue = 0
errname = ''
if errcode == 2:
errvalue = int(temperature)
errname = '高温'
elif errcode == 3:
errvalue = int(humidity)
errname = '高湿'
elif errcode == 4:
errvalue = 0
errname = '断电'
elif errcode == 5:
errvalue = 1
errname = '漏水'
elif errcode == 6:
errvalue = fire
errname = '火情'
elif errcode == 7:
errvalue = 0 # network failure 1-online 0-offline
errname = '离线'
save_alarm(spot, errcode, errname, errvalue)
envdata = {'electricity':electricity, 'fire':fire, 'water':water, 'temperature':temperature, 'humidity':humidity}
send_alm_message(spot, errcode, errname, errvalue, **envdata)
def check_spot(sn):
# Check if the spot has recent(within 2 sec) record and return spot id
r = True
spt = Spot.objects.get(sn=sn)
if spt:
env = Envdata.objects.filter(spot=spt).order_by('-rectime')
if env.exists():
if datetime.now() - env[0].rectime < timedelta(seconds=3):
r = False
return r
def check_token(tkstr):
global SECRET_KEY
r = False
dt = datetime.now()
stamp = str(dt.year) + '##' + str(dt.hour%10)
m = sha1()
m.update((SECRET_KEY + stamp).encode('utf-8'))
token = m.hexdigest()
# print(token)
# print(tkstr)
# print(token == tkstr)
if token == tkstr:
r = True
return r
def save_data(spot, errcode, electricity, fire, water, temperature, humidity):
if spot:
Envdata.objects.create(spot=spot,errcode=errcode,electricity=electricity,fire=fire,water=water,temperature=temperature,humidity=humidity,rectime=datetime.now())
return True
def save_alarm(spot, errcode, errname, errvalue):
if spot:
Alarm.objects.create(spot=spot, errcode=errcode, almname=errname, almvalue=errvalue, almtime=datetime.now())
return True
def send_alm_message(spot, errcode, errname, errvalue, **envdata):
global SEND_TIMES, FIRST_ALM_TIME
if not spot:
return False
if not SEND_TIMES.get(spot.sn):
SEND_TIMES[spot.sn] = 0
if not FIRST_ALM_TIME.get(spot.sn):
FIRST_ALM_TIME[spot.sn] = datetime.now()
triglist = [] # to compare the errcode
almset = Alarmset.objects.get(spot=spot)
if almset:
if almset.connection:
triglist.append(7)
if almset.fire:
triglist.append(6)
if almset.water:
triglist.append(5)
if almset.electricity:
triglist.append(4)
if almset.temperature:
triglist.append(2)
if almset.humidity:
triglist.append(3)
if errcode in triglist and SEND_TIMES[spot.sn] < 3:
if SEND_TIMES[spot.sn] == 0:
FIRST_ALM_TIME[spot.sn] = datetime.now()
elif SEND_TIMES[spot.sn] > 0 and datetime.now() - FIRST_ALM_TIME[spot.sn] < timedelta(seconds=10):
return None
# get alert person's maillist & phonelist
smslist = Sms.objects.all().values_list('phone', flat=True)
maillist = Sms.objects.all().values_list('email', flat=True)
smstext = '%s机房%s报警,请及时处理。报警代码:%s,报警参数:%s' % (spot.name, errname, str(errcode), str(errvalue))
mailtext = smstext
if envdata:
mailtext = mailtext + '\n详细监测参数:漏水-%s 供电-%s 火情-%s 温度-%s 湿度-%s' % (envdata['water'], envdata['electricity'], envdata['fire'], envdata['temperature'], envdata['humidity'])
try:
if sendSMS(smstext.encode('gb2312'), ','.join(list(smslist))):
Sendlog.objects.create(sendtype='sms', sendresult=True, sendtime=datetime.now(), sendto=','.join(list(smslist)))
else:
Sendlog.objects.create(sendtype='sms', sendresult=False, sendtime=datetime.now(), sendto=','.join(list(smslist)))
if sendmail(list(maillist), '机房环境监测报警', mailtext):
Sendlog.objects.create(sendtype='mail', sendresult=True, sendtime=datetime.now(), sendto=','.join(list(maillist)))
else:
Sendlog.objects.create(sendtype='mail', sendresult=False, sendtime=datetime.now(), sendto=','.join(list(maillist)))
SEND_TIMES[spot.sn] += 1
except:
Sendlog.objects.create(sendtype='sms', sendresult=False, sendtime=datetime.now(), sendto=','.join(list(smslist)))
Sendlog.objects.create(sendtype='mail', sendresult=False, sendtime=datetime.now(), sendto=','.join(list(maillist)))
if datetime.now() - FIRST_ALM_TIME[spot.sn] > timedelta(hours=1) and SEND_TIMES[spot.sn] >= 3:
SEND_TIMES[spot.sn] = 0
return True
def get_spots():
spots = Spot.objects.all()
return spots
def alarm_statics(spot, starttime, endtime):
res = Alarm.objects.filter(spot__name=spot,almtime__range=[starttime,endtime]).values('almname').annotate(in_times=Count('almname'))
return res
def env_statics(spot, tp, starttime, endtime):
if not tp:
return []
tpdict = {'温度数据':'temperature', '湿度数据':'humidity', '火情数据':'fire', '漏水数据':'water', '断电数据':'electricity'}
envdata = Envdata.objects.exclude(temperature=0).exclude(humidity=0)
res = envdata.filter(spot__name=spot,rectime__range=[starttime,endtime]).values(tpdict[tp], 'rectime')
return res
def compre_statics(starttime, endtime):
res = Envdata.objects.filter(rectime__range=[starttime,endtime]).values('errcode').annotate(in_times=Count('errcode')).order_by('spot','errcode').values('spot__name','in_times','errcode')
# envtag = {'0':'正常', '2':'高温', '3':'高湿', '4':'断电', '5':'漏水', '6':'火情'}
spotslist = list(Spot.objects.all().order_by('pk').values_list('name', flat=True))
rlist = []
for spot in spotslist:
rlist.append({'spot':spot,'data':[0,0,0,0,0,0,0]})
for spdata in rlist:
for rdata in res:
if spdata['spot'] == rdata['spot__name']:
spdata['data'][rdata['errcode']] = rdata['in_times']
spdata['data'].pop(1)
return rlist
def parse_spots(spots):
lst = []
if spots:
for spt in spots:
lst.append(spt.name)
return lst
def get_cmdlist():
# 查询所有未执行的命令列表
global COMMAND_QUEUE
return COMMAND_QUEUE
def store_cmd(spot, cmd, param):
global COMMAND_QUEUE
device = Device.objects.filter(spot=spot).first()
if cmd!='REBOOT':
try:
float(param)
except:
return False
if device and cmd != 'REBOOT':
# 保持设备的最新状态
# if cmd == 'SERVER_URL':
# device.servaddr = param
if cmd == 'TIMESPAN':
device.timespan = param
elif cmd == 'A_FIRE':
device.afire = param
elif cmd == 'A_TEMP':
device.atemp = param
elif cmd == 'A_HUM':
device.ahum = param
device.save()
elif not device and cmd != 'REBOOT':
dev = Device()
if cmd == 'SERVER_URL':
dev.servaddr = param
elif cmd == 'TIMESPAN':
dev.timespan = param
elif cmd == 'A_FIRE':
dev.afire = param
elif cmd == 'A_TEMP':
dev.atemp = param
elif cmd == 'A_HUM':
dev.ahum = param
dev.save()
COMMAND_QUEUE.append(spot+'$'+cmd+'$'+param)
def pop_cmd(spot):
global COMMAND_QUEUE
c = 'nocmd'
if not spot:
return c
for idx,val in enumerate(COMMAND_QUEUE):
if spot in val:
c = COMMAND_QUEUE.pop(idx)
c = c.replace(spot+'$', '')
return c
return c
def save_deviceinfo(spot, timespan, afire, atemp, ahum):
if not spot:
return False
try:
device = Device.objects.filter(spot=spot).first()
if not device:
device = Device()
device.spot = spot
# device.servaddr = servaddr
device.timespan = timespan
device.afire = afire
device.atemp = atemp
device.ahum = ahum
device.save()
return True
except:
return False
def get_deviceinfo(spot):
deviceinfo = {"TIMESPAN":"","A_FIRE":"","A_TEMP":"","A_HUM":""}
if not spot:
return deviceinfo
dinfo = Device.objects.filter(spot=spot).first()
if dinfo:
deviceinfo['TIMESPAN'] = str(dinfo.timespan)
deviceinfo['A_FIRE'] = str(dinfo.afire)
deviceinfo['A_TEMP'] = str(dinfo.atemp)
deviceinfo['A_HUM'] = str(dinfo.ahum)
return deviceinfo