|
# -*- coding: utf-8 -*-
from __future__ import division
import json
from django.conf import settings
from django.db.models import Max, Q
from django_logit import logit
from django_query import get_query_value
from django_response import response
from paginator import pagination
from TimeConvert import TimeConvert as tc
from equipment.models import (IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo,
ThermometerMeasureLogInfo)
from utils.error.errno_utils import IsolationPointStatusCode, ThermometerEquipmentStatusCode
from utils.redis.rcharging import get_charging_delta_stamp, set_charging_stamp
from utils.redis.rfever import del_fever_stamp, get_fever_delta_stamp, set_fever_stamp
from utils.redis.rscreen import get_screen_info, set_screen_info
@logit
def eqpt_bind(request):
point_id = request.POST.get('point_id', '')
macid = request.POST.get('macid', '')
sn = request.POST.get('sn', '')
macidsns = get_query_value(request, 'macidsns', val_cast_type='listjson')
macidsns = macidsns or [{'macid': macid, 'sn': sn}]
for macidsn in macidsns:
macid, sn = macidsn.get('macid'), macidsn.get('sn')
ThermometerEquipmentInfo.objects.update_or_create(macid=macid, defaults={
'point_id': point_id,
'sn': sn,
})
return response()
@logit
def eqpt_onoff(request):
macid = request.POST.get('macid', '')
active = int(request.POST.get('active', 0))
try:
eqpt = ThermometerEquipmentInfo.objects.get(macid=macid)
except ThermometerEquipmentInfo.DoesNotExist:
return response(ThermometerEquipmentStatusCode.THERMOMETER_EQUIPMENT_NOT_FOUND)
if active == 0:
try:
ipui = IsolationPointUserInfo.objects.get(pk=eqpt.ipui_pk)
except IsolationPointUserInfo.DoesNotExist:
ipui = None
if ipui:
ipui.leave_at = tc.utc_datetime()
ipui.status = False
ipui.save()
eqpt.active_status = active
eqpt.ipui_pk = 0
eqpt.save()
return response()
@logit
def eqpt_remark(request):
macid = request.POST.get('macid', '')
remark = request.POST.get('remark', '')
try:
eqpt = ThermometerEquipmentInfo.objects.get(macid=macid)
except ThermometerEquipmentInfo.DoesNotExist:
return response(ThermometerEquipmentStatusCode.THERMOMETER_EQUIPMENT_NOT_FOUND)
eqpt.remark = remark
eqpt.save()
# 存放历史备注记录
try:
ipui = IsolationPointUserInfo.objects.get(pk=eqpt.ipui_pk)
except IsolationPointUserInfo.DoesNotExist:
ipui = None
if ipui:
ipui.remark = remark
ipui.remarks += [remark]
ipui.save()
return response()
@logit(body=True)
def eqpt_list(request):
point_id = request.POST.get('point_id', '')
macid = request.POST.get('macid', '')
page = request.POST.get('page', 1)
num = request.POST.get('num', 20)
eqpts = ThermometerEquipmentInfo.objects.filter(point_id=point_id, status=True)
if macid:
eqpts = eqpts.filter(macid=macid)
total_num = eqpts.count()
active_num = eqpts.filter(active_status=ThermometerEquipmentInfo.ONLINE).count()
eqpts, left = pagination(eqpts, page, num)
eqpts = [eqpt.data for eqpt in eqpts]
return response(data={
'eqpts': eqpts,
'left': left,
'total_num': total_num,
'active_num': active_num,
'unactive_num': total_num - active_num,
})
@logit
def eqpt_result(request):
point_id = request.POST.get('point_id', '')
kw = request.POST.get('kw', '')
page = request.POST.get('page', 1)
num = request.POST.get('num', 20)
try:
point = IsolationPointInfo.objects.get(point_id=point_id, status=True)
except IsolationPointInfo.DoesNotExist:
return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND)
eqpts = ThermometerEquipmentInfo.objects.filter(point_id=point_id, active_status=ThermometerEquipmentInfo.ONLINE, status=True)
ipuis = IsolationPointUserInfo.objects.filter(point_id=point.point_id, status=True)
ipuis = [ipui.data for ipui in ipuis]
total_active_eqpt_num = eqpts.count()
has_upload_temperature_num = len([1 for ipui in ipuis if ipui.get('temperature_has_upload', '') == IsolationPointUserInfo.HAS_YET_UPLOAD])
fever_num = len([1 for ipui in ipuis if ipui.get('temperature', 0) > settings.FEVER_TEMPERATURE])
ipuis = {ipui.get('pk'): {
'fields': ipui.get('fields', []),
'observed_days': ipui.get('observed_days', 0),
'temperature_has_upload': ipui.get('temperature_has_upload', ''),
'temperature': ipui.get('temperature', 0),
'last_submit_at': ipui.get('last_submit_at', ''),
'remark': ipui.get('remark', ''),
} for ipui in ipuis}
if kw:
eqpts = eqpts.filter(Q(name__icontains=kw) | Q(phone__icontains=kw))
eqpts, left = pagination(eqpts, page, num)
eqpts = [{**eqpt.data, **{
'has_upload': ipuis.get(eqpt.ipui_pk, {}).get('temperature_has_upload', ''),
'temperature': ipuis.get(eqpt.ipui_pk, {}).get('temperature', 0),
'observed_days': ipuis.get(eqpt.ipui_pk, {}).get('observed_days', 0),
'last_submit_at': ipuis.get(eqpt.ipui_pk, {}).get('last_submit_at', ''),
'remark': ipuis.get(eqpt.ipui_pk, {}).get('remark', ''),
'fields': ipuis.get(eqpt.ipui_pk, {}).get('fields', []),
}} for eqpt in eqpts]
return response(data={
'eqpts': eqpts,
'left': left,
'total_active_eqpt_num': total_active_eqpt_num,
'has_upload_temperature_num': has_upload_temperature_num,
'not_upload_temperature_num': total_active_eqpt_num - has_upload_temperature_num,
'fever_num': fever_num,
})
def protect_user_privacy(field):
if (field.get('key', '') == 'phone'):
phone = list(field.get('value', ''))
phone[3:7] = '****'
return ''.join(phone)
elif (field.get('key', '') == 'name'):
name = list(field.get('value', ''))
name[1] = '*'
return ''.join(name)
return field.get('value', '')
def get_screen_data(point=None, point_id=None):
if not point:
try:
point = IsolationPointInfo.objects.get(point_id=point_id, status=True)
except IsolationPointInfo.DoesNotExist:
return {}
# eqpts = ThermometerEquipmentInfo.objects.filter(point_id=point.point_id, active_status=ThermometerEquipmentInfo.ONLINE, status=True)
ipuis = IsolationPointUserInfo.objects.filter(point_id=point.point_id, status=True).order_by('-last_submit_at')
total_active_eqpt_num = ipuis.count()
if point.temperature_measure_type == IsolationPointInfo.SINGLE:
start_dt, end_dt = point.match_upload_period
ipuis = ipuis.exclude(last_submit_at__range=(start_dt, end_dt), temperature__gt=0.0, temperature__lte=settings.FEVER_TEMPERATURE)
ipuis = [{**ipui.data, **{
field.get('key', ''): protect_user_privacy(field) for field in ipui.fields }} for ipui in ipuis]
reminds = [{
'name': ipui.get('name'),
'room': ipui.get('room'),
'content': ipui.get('remark'),
} for ipui in ipuis if ipui.get('remark')]
ipuis_fever = []
ipuis_not_upload = []
ipuis_unused = []
for ipui in ipuis:
temperature = ipui.get('temperature', 0.0)
last_submit_at = ipui.get('last_submit_at', '')
if not last_submit_at:
ipui['temperature'] = '-'
ipui['last_report_time'] = '-'
ipui['status'] = '未使用'
ipuis_unused.append(ipui)
continue
last_submit_at = tc.make_naive(last_submit_at)
if (start_dt < last_submit_at < end_dt) and temperature > settings.FEVER_TEMPERATURE:
ipui['status'] = '已上报'
ipuis_fever.append(ipui)
else:
ipui['temperature'] = '-'
ipui['status'] = '未测温'
ipuis_not_upload.append(ipui)
not_upload_temperature_num = len(ipuis_unused) + len(ipuis_not_upload)
has_upload_temperature_num = total_active_eqpt_num - not_upload_temperature_num
normal_num = has_upload_temperature_num - len(ipuis_fever)
return {
'eqpts': ipuis_fever + ipuis_unused + ipuis_not_upload,
'reminds': reminds,
'total_active_eqpt_num': total_active_eqpt_num,
'has_upload_temperature_num': has_upload_temperature_num,
'not_upload_temperature_num': not_upload_temperature_num,
'normal_num': normal_num,
'fever_num': len(ipuis_fever),
'update_time': tc.local_string(),
}
has_upload_temperature_num = len([1 for ipui in ipuis if ipui.get('temperature_has_upload', '') == IsolationPointUserInfo.HAS_YET_UPLOAD])
fever_num = len([1 for ipui in ipuis if ipui.get('temperature', 0) > settings.FEVER_TEMPERATURE and ipui.get('temperature_has_upload') == IsolationPointUserInfo.HAS_YET_UPLOAD])
# ipuis = {ipui.get('pk'): {
# 'fields': ipui.get('fields', []),
# 'observed_days': ipui.get('observed_days', 0),
# 'user_status': ipui.get('user_status', ''),
# 'temperature': ipui.get('temperature', 0),
# 'last_submit_at': ipui.get('last_submit_at', ''),
# 'remark': ipui.get('remark', ''),
# } for ipui in ipuis}
eqpts = ipuis
# eqpts = [{**{
# 'user_status': ipuis.get(eqpt.ipui_pk, {}).get('user_status', ''),
# 'temperature': ipuis.get(eqpt.ipui_pk, {}).get('temperature', 0),
# 'observed_days': ipuis.get(eqpt.ipui_pk, {}).get('observed_days', 0),
# 'last_submit_at': ipuis.get(eqpt.ipui_pk, {}).get('last_submit_at', ''),
# 'remark': ipuis.get(eqpt.ipui_pk, {}).get('remark', ''),
# }, **{
# field.get('key', ''): field.get('value', '') for field in ipuis.get(eqpt.ipui_pk, {}).get('fields', [])
# }} for eqpt in eqpts]
# eqpts = [{
# 'name': eqpt.get('name', ''),
# 'room': eqpt.get('room', ''),
# 'phone': eqpt.get('phone', ''),
# 'sex': eqpt.get('sex', ''),
# 'age': eqpt.get('age', ''),
# 'status': eqpt.get('user_status'),
# 'last_report_time': eqpt.get('last_submit_at', ''),
# 'temperature': eqpt.get('temperature', 0),
# 'observed_days': eqpt.get('observed_days', 0),
# } for eqpt in eqpts]
# 排序:发烧 > 未联网 > 关机 > 未佩戴 > 充电中 > 时间
eqpts_fever = []
# eqpts_not_upload = []
eqpts_not_connected = []
eqpts_shutdown = []
eqpts_not_worn = []
eqpts_chg = []
eqpts_other = []
for eqpt in eqpts:
status = eqpt.get('status')
temperature = eqpt.get('temperature')
if status == IsolationPointUserInfo.HAS_YET_UPLOAD and temperature > settings.FEVER_TEMPERATURE:
eqpts_fever.append(eqpt)
elif status == IsolationPointUserInfo.HAS_NOT_CONNECTED:
eqpt['temperature'] = '-'
eqpts_not_connected.append(eqpt)
elif status == IsolationPointUserInfo.HAS_SHUTDOWN:
eqpt['temperature'] = '-'
eqpts_shutdown.append(eqpt)
elif status == IsolationPointUserInfo.HAS_NOT_WORN:
eqpt['temperature'] = '-'
eqpts_not_worn.append(eqpt)
elif status == IsolationPointUserInfo.CHG_STA_CHARGING:
eqpt['temperature'] = '-'
eqpts_chg.append(eqpt)
else:
eqpts_other.append(eqpt)
return {
'eqpts': eqpts_fever + eqpts_not_connected + eqpts_shutdown + eqpts_not_worn + eqpts_chg + eqpts_other,
'reminds': reminds,
'total_active_eqpt_num': total_active_eqpt_num,
'has_upload_temperature_num': has_upload_temperature_num,
'not_upload_temperature_num': total_active_eqpt_num - has_upload_temperature_num,
'normal_num': has_upload_temperature_num - fever_num,
'fever_num': fever_num,
'update_time': tc.local_string(),
}
@logit
def screen_eqpt_result(request):
point_id = request.POST.get('point_id', '')
screen_info = get_screen_info(point_id)
if screen_info:
return response(data=screen_info)
try:
point = IsolationPointInfo.objects.get(point_id=point_id, status=True)
except IsolationPointInfo.DoesNotExist:
return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND)
screen_data = get_screen_data(point)
return response(data=screen_data)
@logit
def upload_temperature(request):
return response()
def mqtt_upload_temperature(payload):
# Received `{"mac":"A4DA324E7A63","pkt":"215","chg_sta":true,"bat":"100","raw_temp":"4697,4696,4697","sta":"0","alg_temp":"4697,4696,4697","alg_gstr":0,"ble_rssi":-21,"wifi_rssi":-68,"current_time":"2021-08-08 15:22:59"}` from `esp/240AC4D3C1AC` topic
#
# {
# "mac": "A4DA324E7A63", # 体温贴 mac,固定 6 个字节,12 个字符
# "pkt": "215", # 广播包包序为 85,有效包序范围[1, 255]
# "chg_sta": true, # 充电状态,true 充电,false 未充电
# "bat": "100", # 电量剩余 65%,有效电量范围[0, 100]
# "raw_temp": "4697,4696,4697", # 三个原始温度数
# "sta": "0", # 算法返回状态
# "alg_temp": "4697,4696,4697", # 算法返回三个温度
# "alg_gstr": 0, # 算法手臂姿态
# "ble_rssi": -21, # 体温贴相对于底座的信号强度
# "wifi_rssi": -68, # 底座网络信号强度
# "current_time": "2021-08-08 15:22:59" # 底座接收到体温贴信息的实时时间
# }
try:
payload = json.loads(payload)
except Exception:
return
alg_temp = payload.get('alg_temp', '')
temp = alg_temp.split(',')
temp = [int(t) for t in temp if t]
if not temp:
return
temperature = max(temp) / 100
# 充电状态,true 充电,false 未充电
chg_sta = payload.get('chg_sta', False)
# 电量剩余 65%,有效电量范围[0, 100]
bat = int(payload.get('bat', 0))
# 体温贴 mac,固定 6 个字节,12 个字符
macid = payload.get('mac', '')
macid = f'{macid[:2]}:{macid[2:4]}:{macid[4:6]}:{macid[6:8]}:{macid[8:10]}:{macid[10:12]}'
# 充电状态 or (电量剩余 100% + 温度超过 37 度),温度忽略
ignore_temperature = False
if chg_sta or (bat == 100 and temperature > 37):
ignore_temperature = True
chg_sta = True
set_charging_stamp(macid)
# 过去半小时内如果有充电记录的,当前温度大于37度的过滤掉
if temperature > 37 and get_charging_delta_stamp(macid) < 1800:
ignore_temperature = True
# 过去10分钟连续大于37.3度再取最高温度
ignore_fever_temperature = False
if not ignore_temperature and temperature > settings.FEVER_TEMPERATURE:
delta_stamp = get_fever_delta_stamp(macid)
# 首次超过37.3
if not delta_stamp:
set_fever_stamp(macid)
ignore_fever_temperature = True
# 连续10分钟超过37.3
elif delta_stamp > 600:
pass
else:
ignore_fever_temperature = True
else:
del_fever_stamp(macid)
current_time = payload.get('current_time', '')
start_stamp = end_stamp = tc.string_to_timestamp(current_time)
try:
eqpt = ThermometerEquipmentInfo.objects.get(macid=macid, status=True)
except ThermometerEquipmentInfo.DoesNotExist:
# ThermometerMeasureLogInfo.objects.create(macid=macid, start_stamp=start_stamp, end_stamp=end_stamp, temperature=temperature, temperature_src=ThermometerMeasureLogInfo.MQTT, upload_temperature_info=payload, status=False)
return
try:
point = IsolationPointInfo.objects.get(point_id=eqpt.point_id, status=True)
except IsolationPointInfo.DoesNotExist:
return
# # 非配置的隔离点上报时间内
# if not point.match_upload_period:
# return
ThermometerMeasureLogInfo.objects.create(point_id=eqpt.point_id, macid=macid, start_stamp=start_stamp, end_stamp=end_stamp, temperature=temperature, temperature_src=ThermometerMeasureLogInfo.MQTT, chg_sta=chg_sta, ignore_temperature=ignore_temperature, ignore_fever_temperature=ignore_fever_temperature, upload_temperature_info=payload)
try:
ipui = IsolationPointUserInfo.objects.get(pk=eqpt.ipui_pk)
except IsolationPointUserInfo.DoesNotExist:
ipui = None
if ipui:
if not ignore_temperature:
temperature__max = ThermometerMeasureLogInfo.objects.filter(
point_id=eqpt.point_id,
macid=macid,
chg_sta=False,
ignore_temperature=False,
ignore_fever_temperature=False,
created_at__gte=tc.utc_datetime(hours=-1),
).aggregate(Max('temperature')).get('temperature__max') or 0
ipui.observed_ymds = list(set(ipui.observed_ymds + [tc.local_string(format='%Y-%m-%d')]))
ipui.observed_days = len(ipui.observed_ymds)
ipui.temperature = temperature__max or ipui.temperature
ipui.last_submit_at = tc.utc_datetime()
ipui.chg_sta = chg_sta
ipui.save()
set_screen_info(point.point_id, get_screen_data(point))
|