From 460f83589f94229f3148941472e9c3aaa450a305 Mon Sep 17 00:00:00 2001 From: nfa Date: Thu, 23 Dec 2021 13:47:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20'env'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env/__init__.py | Bin 0 -> 1024 bytes env/admin.py | 48 +++++++++ env/apps.py | 6 ++ env/envpost.py | 265 ++++++++++++++++++++++++++++++++++++++++++++++++ env/mail.py | 28 +++++ 5 files changed, 347 insertions(+) create mode 100644 env/__init__.py create mode 100644 env/admin.py create mode 100644 env/apps.py create mode 100644 env/envpost.py create mode 100644 env/mail.py diff --git a/env/__init__.py b/env/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..06d7405020018ddf3cacee90fd4af10487da3d20 GIT binary patch literal 1024 ScmZQz7zLvtFd70QH3R?z00031 literal 0 HcmV?d00001 diff --git a/env/admin.py b/env/admin.py new file mode 100644 index 0000000..e62888e --- /dev/null +++ b/env/admin.py @@ -0,0 +1,48 @@ +from django.contrib import admin +from .models import * +from .views import * + +class EnvdataAdmin(admin.ModelAdmin): + admin.site.site_header = "ENV后台管理" + list_display = ('spot', 'errcode', 'rectime') + list_filter = ('spot', 'errcode') + fields = ('spot', 'errcode', 'electricity', 'fire', 'water', 'temperature', 'humidity', 'rectime') + readonly_fields = ('spot', 'errcode', 'electricity', 'fire', 'water', 'temperature', 'humidity', 'rectime') + list_per_page = 30 + +class AlarmAdmin(admin.ModelAdmin): + list_display = ('spot', 'almname', 'almtime') + list_filter = ('spot', 'almname') + fields = ('spot', 'errcode', 'almname', 'almvalue', 'almtime') + readonly_fields = ('spot', 'errcode', 'almname', 'almvalue', 'almtime') + list_per_page = 30 + +class SpotAdmin(admin.ModelAdmin): + list_display = ('name', 'ip') + +class AlarmsetAdmin(admin.ModelAdmin): + list_display = ('spot',) + +class SmsAdmin(admin.ModelAdmin): + list_display = ('name',) + +class SendlogAdmin(admin.ModelAdmin): + list_display = ('sendtype', 'sendresult', 'sendtime') + readonly_fields = ('sendtype', 'sendresult', 'sendtime', 'sendto') + +class ChartAdmin(admin.ModelAdmin): + def changelist_view(self, request, extra_content=None): + return chart_index(request) + +class SysAdmin(admin.ModelAdmin): + def changelist_view(self, request, extra_content=None): + return sys_cmd(request) + +admin.site.register(Spot, SpotAdmin) +admin.site.register(Envdata, EnvdataAdmin) +admin.site.register(Alarm, AlarmAdmin) +admin.site.register(Alarmset, AlarmsetAdmin) +admin.site.register(Sms, SmsAdmin) +admin.site.register(Sendlog, SendlogAdmin) +admin.site.register(Envchart, ChartAdmin) +admin.site.register(Sysmanager, SysAdmin) diff --git a/env/apps.py b/env/apps.py new file mode 100644 index 0000000..46645fb --- /dev/null +++ b/env/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class EnvConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'env' diff --git a/env/envpost.py b/env/envpost.py new file mode 100644 index 0000000..2d33494 --- /dev/null +++ b/env/envpost.py @@ -0,0 +1,265 @@ +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 \ No newline at end of file diff --git a/env/mail.py b/env/mail.py new file mode 100644 index 0000000..591e738 --- /dev/null +++ b/env/mail.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +import smtplib +from email.mime.text import MIMEText +import urllib.request + +def sendmail(receiver, subject, content): + try: + email_host = 'smtp.sina.com' # 发送者是sina邮箱 + email_user = 'xxxxx@sina.com' # 发送者账号 + email_pwd = 'Wj12345' # 发送者密码 + # maillist = 'test123@yeah.net' # 接收者账号,本来想写成[]list的,但是报错,还没解决! + + # 三个参数:第一个为文本内容,第二个 html 设置文本格式,第三个 utf-8 设置编码 + msg = MIMEText(content, 'html', 'utf-8') # 邮件内容 + msg['Subject'] = subject # 邮件主题 + msg['From'] = email_user # 发送者账号 + msg['To'] = ','.join(receiver) # 接收者账号列表(列表没实现) + + smtp = smtplib.SMTP(email_host) # 如上变量定义的,是163邮箱 + smtp.login(email_user, email_pwd) # 发送者的邮箱账号,密码 + smtp.sendmail(email_user, receiver, msg.as_string()) # 参数分别是发送者,接收者,第三个不知道 + smtp.quit() # 发送完毕后退出smtp + return True + except: + return False + +if __name__ == '__main__': + sendmail(['abc123@yeah.net','xxxxx@163.com','abc123@cz.gov.cn'],'测试邮件','测试邮件,以下是测试内容!')