event serializer
This commit is contained in:
parent
6231e09a30
commit
ffa48f8031
|
@ -0,0 +1,2 @@
|
||||||
|
def helmet_test():
|
||||||
|
return True
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Generated by Django 3.2.12 on 2022-07-04 00:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('third', '0003_alter_tdevice_type'),
|
||||||
|
('ecm', '0007_auto_20220702_1327'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='event',
|
||||||
|
name='vchannel',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='third.tdevice', verbose_name='抓拍设备'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='eventcate',
|
||||||
|
name='filter_area_level',
|
||||||
|
field=models.PositiveSmallIntegerField(choices=[(10, '办公'), (20, '生产一般'), (30, '生产重点'), (40, '四级')], default=10, verbose_name='固定喇叭区域级别过滤'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='eventcate',
|
||||||
|
name='speaker_on',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='开启喇叭报警'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='eventcate',
|
||||||
|
name='speakers',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='ec_speakers', to='third.TDevice', verbose_name='固定喇叭'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -21,10 +21,10 @@ class EventCate(CommonAModel):
|
||||||
name = models.CharField('名称', max_length=20, unique=True)
|
name = models.CharField('名称', max_length=20, unique=True)
|
||||||
trigger = models.PositiveSmallIntegerField('触发方式', default=10, choices=EVENT_TRIGGER_CHOICES)
|
trigger = models.PositiveSmallIntegerField('触发方式', default=10, choices=EVENT_TRIGGER_CHOICES)
|
||||||
self_algo = models.BooleanField('识别算法', default=False)
|
self_algo = models.BooleanField('识别算法', default=False)
|
||||||
speaker_on = models.BooleanField('开启音响报警', default=True)
|
speaker_on = models.BooleanField('开启喇叭报警', default=True)
|
||||||
voice_person = models.PositiveSmallIntegerField('声音选择', default=0, help_text='0女声3男声')
|
voice_person = models.PositiveSmallIntegerField('声音选择', default=0, help_text='0女声3男声')
|
||||||
speakers = models.ManyToManyField(TDevice, verbose_name='固定音响', blank=True)
|
speakers = models.ManyToManyField(TDevice, verbose_name='固定喇叭', blank=True, related_name='ec_speakers')
|
||||||
filter_area_level = models.PositiveSmallIntegerField('固定音响区域级别过滤', choices=Area.AREA_LEVEL_CHOICES,
|
filter_area_level = models.PositiveSmallIntegerField('固定喇叭区域级别过滤', choices=Area.AREA_LEVEL_CHOICES,
|
||||||
default=Area.AREA_1)
|
default=Area.AREA_1)
|
||||||
hanle_minute = models.PositiveSmallIntegerField('处理时间', default=0, help_text='超过处理时间事件状态变为超时未处理,0代表未配置')
|
hanle_minute = models.PositiveSmallIntegerField('处理时间', default=0, help_text='超过处理时间事件状态变为超时未处理,0代表未配置')
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ class Event(CommonBModel):
|
||||||
face_img = models.CharField('人脸照', max_length=1000, null=True, blank=True)
|
face_img = models.CharField('人脸照', max_length=1000, null=True, blank=True)
|
||||||
global_img = models.CharField('全景照', max_length=1000, null=True, blank=True)
|
global_img = models.CharField('全景照', max_length=1000, null=True, blank=True)
|
||||||
area = models.ForeignKey(Area, verbose_name='发生区域', on_delete=models.CASCADE)
|
area = models.ForeignKey(Area, verbose_name='发生区域', on_delete=models.CASCADE)
|
||||||
|
vchannel = models.ForeignKey(TDevice, verbose_name='抓拍设备', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
location = models.JSONField('事件点位坐标', default=dict, null=False, blank=True)
|
location = models.JSONField('事件点位坐标', default=dict, null=False, blank=True)
|
||||||
obj_cate = models.CharField('发生对象', max_length=20, help_text='people(人员)/...')
|
obj_cate = models.CharField('发生对象', max_length=20, help_text='people(人员)/...')
|
||||||
employee = models.ForeignKey(Employee, verbose_name='当事人',
|
employee = models.ForeignKey(Employee, verbose_name='当事人',
|
||||||
|
|
|
@ -74,7 +74,7 @@ class NotifySettingsSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class EventSerializer(serializers.ModelSerializer):
|
class EventSerializer(serializers.ModelSerializer):
|
||||||
area_ = AreaSerializer(source='area', read_only=True)
|
area_ = AreaSerializer(source='area', read_only=True)
|
||||||
cate_ = EventCateSimpleSerializer(source='cate', read_only=True, many=True)
|
cates_ = EventCateSimpleSerializer(source='cate', read_only=True, many=True)
|
||||||
employee_ = EmployeeSerializer(source='employee', read_only=True)
|
employee_ = EmployeeSerializer(source='employee', read_only=True)
|
||||||
handle_user_name = serializers.CharField(source='handle_user.name', read_only=True)
|
handle_user_name = serializers.CharField(source='handle_user.name', read_only=True)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
from apps.ecm.algo import helmet_test
|
||||||
from apps.utils.sms import send_sms
|
from apps.utils.sms import send_sms
|
||||||
import requests
|
import requests
|
||||||
from apps.am.models import Access, Area
|
from apps.am.models import Access, Area
|
||||||
from apps.am.tasks import cache_areas_info
|
from apps.am.tasks import cache_areas_info
|
||||||
from apps.ecm.models import Event, EventCate, Eventdo
|
from apps.ecm.models import AlgoChannel, Event, EventCate, Eventdo
|
||||||
from apps.hrm.models import Employee
|
from apps.hrm.models import Employee
|
||||||
from apps.system.models import User
|
from apps.system.models import User
|
||||||
from apps.third.clients import xxClient
|
from apps.third.clients import xxClient
|
||||||
|
@ -24,19 +25,27 @@ requests.packages.urllib3.disable_warnings()
|
||||||
|
|
||||||
|
|
||||||
def get_area_info_from_cache(target: str, cache: list):
|
def get_area_info_from_cache(target: str, cache: list):
|
||||||
|
"""从区域信息缓存里匹配到所在区域
|
||||||
|
|
||||||
|
Args:
|
||||||
|
target (str): 区域ID
|
||||||
|
cache (list):
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
for i in cache:
|
for i in cache:
|
||||||
if i['id'] == target:
|
if i['id'] == target:
|
||||||
return i
|
return i
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def save_dahua_pic(pic: str):
|
def save_dahua_pic(pic_url: str):
|
||||||
"""保存大华报警图片到本地
|
"""保存大华报警图片到本地
|
||||||
返回本地路径
|
返回本地路径
|
||||||
"""
|
"""
|
||||||
file_name = pic.split('/')[-1]
|
file_name = pic_url.split('/')[-1].split('?')[-1]
|
||||||
full_url = dhClient.get_full_pic(pic)
|
res = requests.get(url=pic_url, verify=False)
|
||||||
res = requests.get(url=full_url, verify=False)
|
|
||||||
path = '/media/' + timezone.now().strftime('%Y/%m/%d/')
|
path = '/media/' + timezone.now().strftime('%Y/%m/%d/')
|
||||||
full_path = settings.BASE_DIR + path
|
full_path = settings.BASE_DIR + path
|
||||||
if not os.path.exists(full_path):
|
if not os.path.exists(full_path):
|
||||||
|
@ -46,242 +55,274 @@ def save_dahua_pic(pic: str):
|
||||||
return path + file_name
|
return path + file_name
|
||||||
|
|
||||||
|
|
||||||
class EcmService:
|
def get_ep_default():
|
||||||
"""事件处理服务
|
"""返回人员默认位置信息
|
||||||
"""
|
"""
|
||||||
|
return {
|
||||||
|
'area_fix_id': None, # 当前所在固定区域ID
|
||||||
|
'time0': None, # 定位首次出现时间戳
|
||||||
|
"time1": None, # 首次在该区域时间戳
|
||||||
|
"time2": int(time.time()), # 当前时间戳
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_ep_default(cls):
|
|
||||||
return {
|
|
||||||
'area_fix_id': None, # 当前所在固定区域ID
|
|
||||||
'time0': None, # 定位首次出现时间戳
|
|
||||||
"time1": None, # 首次在该区域时间戳
|
|
||||||
"time2": int(time.time()), # 当前时间戳
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
def algo_handle(codes: list, data: dict):
|
||||||
def create_remind_and_speak(cls, event: Event):
|
"""算法
|
||||||
"""
|
|
||||||
创建事件提醒并发送短信/微信/喇叭
|
|
||||||
"""
|
|
||||||
# 喇叭提醒
|
|
||||||
if event.voice:
|
|
||||||
sps = list(TDevice.objects.filter(area=event.area, type=TDevice.DEVICE_SPEAKER).values_list('code', flat=True))
|
|
||||||
if len(sps) == 0: # 找覆盖区的音响
|
|
||||||
sps = list(TDevice.objects.filter(areas=event.area,
|
|
||||||
type=TDevice.DEVICE_SPEAKER).values_list('code', flat=True))
|
|
||||||
if sps:
|
|
||||||
t = Thread(target=spClient.speak, args=(event.voice, sps), daemon=True)
|
|
||||||
t.start()
|
|
||||||
if event.employee and event.employee.phone:
|
|
||||||
t = Thread(target=send_sms, args=(event.employee.phone, '1001', {'code': '5678'}), daemon=True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
@classmethod
|
Args:
|
||||||
def dispatch_dahua_event(cls, data: dict):
|
code (str): 算法标识列表
|
||||||
"""分发大华事件进行处理
|
data (dict): 需要处理的内容
|
||||||
"""
|
"""
|
||||||
vchannel_code = data['info']['nodeCode']
|
return ['helmet']
|
||||||
alarm_type = data['info']['alarmType']
|
|
||||||
vchannel = TDevice.objects.filter(code=vchannel_code).first()
|
|
||||||
print(data)
|
def save_voice_and_speak(event: Event):
|
||||||
if alarm_type in [1001003, 1001000] and vchannel: # 内部人员/或陌生人报警
|
"""生成并保存语音地址并喇叭播放
|
||||||
# 加载算法逻辑
|
|
||||||
# 安全帽检测
|
Args:
|
||||||
ec = EventCate.objects.filter(code='helmet').first() # 模拟发生安全帽事件
|
event (Event): _description_
|
||||||
# 视频区域
|
"""
|
||||||
area = vchannel.area
|
_, event.voice, _ = generate_voice(event.voice_msg, event.cates[0].voice_person)
|
||||||
if ec and area:
|
event.save()
|
||||||
# 保存照片
|
sps = list(TDevice.objects.filter(area=event.area, type=TDevice.DEVICE_SPEAKER).values_list('code', flat=True))
|
||||||
face_img = save_dahua_pic(data['info']['alarmPicture'])
|
if len(sps) == 0: # 如果当前区域没有喇叭就找覆盖区的喇叭
|
||||||
global_img = save_dahua_pic(data['info']['extend']['globalScenePicUrl'])
|
sps = list(TDevice.objects.filter(areas=event.area,
|
||||||
|
type=TDevice.DEVICE_SPEAKER).values_list('code', flat=True))
|
||||||
|
# 固定喇叭
|
||||||
|
sps2 = list(TDevice.objects.filter(ec_speakers__in=event.cates).values_list('code', flat=True))
|
||||||
|
for i in sps2:
|
||||||
|
if i not in sps:
|
||||||
|
sps.append(i)
|
||||||
|
if sps:
|
||||||
|
spClient.speak(event.voice, sps)
|
||||||
|
|
||||||
|
|
||||||
|
def create_remind(event: Event):
|
||||||
|
"""
|
||||||
|
创建事件提醒并发送短信
|
||||||
|
"""
|
||||||
|
if event.employee and event.employee.phone:
|
||||||
|
t_sms = Thread(target=send_sms, args=(event.employee.phone, '1001', {'code': '5678'}), daemon=True)
|
||||||
|
t_sms.start()
|
||||||
|
|
||||||
|
|
||||||
|
def dispatch_dahua_event(data: dict):
|
||||||
|
"""分发大华事件进行处理
|
||||||
|
"""
|
||||||
|
vchannel_code = data['info']['nodeCode']
|
||||||
|
alarm_type = data['info']['alarmType']
|
||||||
|
vchannel = TDevice.objects.filter(code=vchannel_code).first()
|
||||||
|
event = None
|
||||||
|
print(data)
|
||||||
|
if alarm_type in [1001003, 1001000] and vchannel: # 内部人员/或陌生人报警
|
||||||
|
# 查看加载的算法
|
||||||
|
algo_codes = list(AlgoChannel.objects.filter(vchannel=vchannel).exclude(
|
||||||
|
algo__code=None).values_list('algo__code', flat=True))
|
||||||
|
area = vchannel.area # 视频所在区域
|
||||||
|
if algo_codes and area: # 如果加载了算法且视频通道绑定区域才继续
|
||||||
|
face_img_o = dhClient.get_full_pic(data['info']['alarmPicture'])
|
||||||
|
global_img_o = dhClient.get_full_pic(data['info']['extend']['globalScenePicUrl'])
|
||||||
|
obj_cate = 'people'
|
||||||
|
ep = None # 对应人员
|
||||||
|
if alarm_type == 1001003: # 内部人员
|
||||||
|
ep = Employee.objects.filter(id_number=data['info']['extend']['candidateInfo'][0]['id']).first()
|
||||||
|
ec_codes = algo_handle(algo_codes, data={}) # 算法处理
|
||||||
|
if ec_codes: # 如果触发事件
|
||||||
|
# 获取本次所有发生事件种类
|
||||||
|
ecs = EventCate.objects.filter(code__in=ec_codes)
|
||||||
|
# 创建事件
|
||||||
event = Event()
|
event = Event()
|
||||||
event.face_img = face_img
|
event.face_img = save_dahua_pic(face_img_o)
|
||||||
event.global_img = global_img
|
event.global_img = save_dahua_pic(global_img_o)
|
||||||
event.area = area
|
event.area = area
|
||||||
event.obj_cate = 'people'
|
event.obj_cate = obj_cate
|
||||||
ep = None # 找到人员
|
event.vchannel = vchannel
|
||||||
if alarm_type == 1001003:
|
voice_msg = ''
|
||||||
ep = Employee.objects.filter(id_number=data['info']['extend']['candidateInfo'][0]['id']).first()
|
|
||||||
if ep:
|
if ep:
|
||||||
voice_msg = '位于{}的{}{},您未佩戴安全帽,请及时处理'
|
|
||||||
ep_name = ep.name
|
ep_name = ep.name
|
||||||
ep_type = '员工'
|
ep_type = '员工'
|
||||||
if ep.type == 'rempoyee':
|
if ep.type == 'rempoyee':
|
||||||
ep_type = '相关方人员'
|
ep_type = '相关方人员'
|
||||||
elif ep.type == 'visitor':
|
elif ep.type == 'visitor':
|
||||||
ep_type = '访客'
|
ep_type = '访客'
|
||||||
event.voice_msg = voice_msg.format(area.name, ep_type, ep_name)
|
voice_msg = '位于{}的{}{},'.format(area.name, ep_type, ep_name)
|
||||||
else:
|
else:
|
||||||
event.voice_msg = '位于{}的未知人员,您未佩戴安全帽,请及时处理'.format(area.name)
|
voice_msg = '位于{}的未知人员,'.format(area.name)
|
||||||
|
for i in ecs:
|
||||||
|
voice_msg = voice_msg + i.name + ','
|
||||||
|
event.voice_msg = voice_msg + ',请及时处理'
|
||||||
event.employee = ep
|
event.employee = ep
|
||||||
_, event.voice, _ = generate_voice(event.voice_msg, ec.voice_person)
|
|
||||||
event.save()
|
event.save()
|
||||||
Eventdo.objects.get_or_create(cate=ec, event=event, defaults={
|
for i in ecs:
|
||||||
'cate': ec,
|
Eventdo.objects.get_or_create(cate=i, event=event, defaults={
|
||||||
'event': event
|
'cate': i,
|
||||||
})
|
'event': event
|
||||||
cls.create_remind_and_speak(event=event)
|
})
|
||||||
|
if event:
|
||||||
|
t_v = Thread(target=save_voice_and_speak, args=(event,), daemon=True)
|
||||||
|
t_v.start()
|
||||||
|
t_r = Thread(target=create_remind, args=(event,), daemon=True)
|
||||||
|
t_r.start()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def dispatch_xunxi_event(cls, data: dict):
|
|
||||||
"""分发寻息事件进行处理
|
|
||||||
"""
|
|
||||||
if data.type == 'rail':
|
|
||||||
if data.data.type == 1:
|
|
||||||
# 围栏进入
|
|
||||||
cls.rail_in(data=data.data)
|
|
||||||
elif data.data.type == 2:
|
|
||||||
# 围栏离开
|
|
||||||
cls.rail_out(data=data.data)
|
|
||||||
elif data.type == 'onKeyAlarm':
|
|
||||||
# 一键呼救
|
|
||||||
cls.one_key_alarm(data=data)
|
|
||||||
elif data.type == 'location':
|
|
||||||
# 定位信息
|
|
||||||
cls.loc_change(data=data)
|
|
||||||
elif data.type == 'onOffLine':
|
|
||||||
if data.data.online:
|
|
||||||
# 标签定位在线
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# 标签定位离线
|
|
||||||
pass
|
|
||||||
elif data.type == 'lowpower':
|
|
||||||
# 低电量
|
|
||||||
cls.low_power(data=data.data)
|
|
||||||
elif data.type == 'bltOnOffLineV2':
|
|
||||||
if data.data.online:
|
|
||||||
# 标签通信在线
|
|
||||||
cls.blt_online(data=data.data)
|
|
||||||
else:
|
|
||||||
# 标签通信离线
|
|
||||||
cls.blt_offline(data=data.data)
|
|
||||||
|
|
||||||
@classmethod
|
def dispatch_xunxi_event(data: dict):
|
||||||
def rail_in(cls, data):
|
"""分发寻息事件进行处理
|
||||||
"""围栏进入事件
|
"""
|
||||||
"""
|
if data.type == 'rail':
|
||||||
# 找到所在围栏
|
if data.data.type == 1:
|
||||||
area = Area.objects.filter(third_info__xx_rail__id=data['railId']).first()
|
# 围栏进入
|
||||||
# 找到进入对象
|
rail_in(data=data.data)
|
||||||
blts = TDevice.objects.filter(code=data['userId']).first()
|
elif data.data.type == 2:
|
||||||
if area and blts and blts.employee: # 如果是人
|
# 围栏离开
|
||||||
if area.type == Area.AREA_TYPE_FIX:
|
rail_out(data=data.data)
|
||||||
# 更新人员位置信息缓存
|
elif data.type == 'onKeyAlarm':
|
||||||
key_str = 'ep_{}'.format(blts.employee.id)
|
# 一键呼救
|
||||||
ep_loc_dict = cache.get_or_set(
|
one_key_alarm(data=data)
|
||||||
key_str, cls.get_ep_default(), timeout=None
|
elif data.type == 'location':
|
||||||
)
|
# 定位信息
|
||||||
if ep_loc_dict['area_fix_id'] != area.id: # 如果区域未变化则不动
|
loc_change(data=data)
|
||||||
ep_loc_dict['time1'] = ep_loc_dict['time2']
|
elif data.type == 'onOffLine':
|
||||||
ep_loc_dict['area_fix_id'] = area.id
|
if data.data.online:
|
||||||
cache.set(key_str, ep_loc_dict)
|
# 标签定位在线
|
||||||
ep_blt = blts.employee # 标签绑定人员
|
|
||||||
if ep_blt:
|
|
||||||
for i in Access.objects.filter(area=area).order_by('sort'):
|
|
||||||
# 优先自定义权限过滤
|
|
||||||
if i.post: # 如果是按岗位设定的
|
|
||||||
eps_access = Employee.objects.filter(user__posts=i.post)
|
|
||||||
if ep_blt in eps_access and i.type == Access.ACCESS_IN_YES:
|
|
||||||
return
|
|
||||||
elif ep_blt in eps_access and i.type == Access.ACCESS_IN_NO:
|
|
||||||
# 触发非法进入事件
|
|
||||||
pass
|
|
||||||
elif i.dept: # 如果是按部门设定的
|
|
||||||
if i.dept.type == 'dept': # 如果是内部部门
|
|
||||||
depts = get_child_queryset2(i.dept)
|
|
||||||
if ep_blt.belong_dept in depts and i.type == Access.ACCESS_IN_YES:
|
|
||||||
return
|
|
||||||
elif ep_blt.belong_dept in depts and i.type == Access.ACCESS_IN_NO:
|
|
||||||
# 触发非法进入事件
|
|
||||||
pass
|
|
||||||
elif i.dept.type == 'rparty': # 如果是相关方
|
|
||||||
if ep_blt.belong_dept == i.dept and i.type == Access.ACCESS_IN_YES:
|
|
||||||
return
|
|
||||||
elif ep_blt.belong_dept == i.dept and i.type == Access.ACCESS_IN_NO:
|
|
||||||
# 触发非法进入事件
|
|
||||||
pass
|
|
||||||
elif i.employee: # 如果是按人设定的
|
|
||||||
if ep_blt == i.employee and i.type == Access.ACCESS_IN_YES:
|
|
||||||
return
|
|
||||||
elif ep_blt == i.employee and i.type == Access.ACCESS_IN_NO:
|
|
||||||
# 触发非法进入事件
|
|
||||||
pass
|
|
||||||
# 通用权限设置过滤
|
|
||||||
if ep_blt.type == 'employee' and area.employee_yes:
|
|
||||||
return
|
|
||||||
elif ep_blt.type == 'remployee' and area.remployee_yes:
|
|
||||||
return
|
|
||||||
elif ep_blt.type == 'visitor' and area.visitor_yes:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
# 触发非法进入事件
|
|
||||||
pass
|
|
||||||
elif area and (not blts):
|
|
||||||
# 触发未知标签进入事件
|
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
@classmethod
|
# 标签定位离线
|
||||||
def rail_out(cls, data):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def low_power(cls, data):
|
|
||||||
# 有绑定对象再提示低电量
|
|
||||||
blts = TDevice.objects.filter(code=data['userId']).first()
|
|
||||||
if blts.employee:
|
|
||||||
# 触发低电量提醒事件
|
|
||||||
pass
|
pass
|
||||||
|
elif data.type == 'lowpower':
|
||||||
|
# 低电量
|
||||||
|
low_power(data=data.data)
|
||||||
|
elif data.type == 'bltOnOffLineV2':
|
||||||
|
if data.data.online:
|
||||||
|
# 标签通信在线
|
||||||
|
blt_online(data=data.data)
|
||||||
|
else:
|
||||||
|
# 标签通信离线
|
||||||
|
blt_offline(data=data.data)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def one_key_alarm(cls, data):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
def rail_in(data):
|
||||||
def loc_change(cls, data):
|
"""围栏进入事件
|
||||||
blts = TDevice.objects.filter(code=data['userId']).first()
|
"""
|
||||||
if blts.employee:
|
# 找到所在围栏
|
||||||
# 从缓存查询人员位置信息
|
area = Area.objects.filter(third_info__xx_rail__id=data['railId']).first()
|
||||||
time2 = int(time.time())
|
# 找到进入对象
|
||||||
|
blts = TDevice.objects.filter(code=data['userId']).first()
|
||||||
|
if area and blts and blts.employee: # 如果是人
|
||||||
|
if area.type == Area.AREA_TYPE_FIX: # 如果是固定区域
|
||||||
|
# 更新人员位置信息缓存
|
||||||
key_str = 'ep_{}'.format(blts.employee.id)
|
key_str = 'ep_{}'.format(blts.employee.id)
|
||||||
ep_loc_dict = cache.get_or_set(
|
ep_loc_dict = cache.get_or_set(
|
||||||
key_str, cls.get_ep_default(), timeout=None
|
key_str, get_ep_default(), timeout=None
|
||||||
)
|
)
|
||||||
ep_loc_dict['time2'] = time2
|
if ep_loc_dict['area_fix_id'] != area.id: # 如果区域未变化则不动
|
||||||
# 从缓存里获取固定区域列表信息
|
ep_loc_dict['time1'] = ep_loc_dict['time2']
|
||||||
area_fix_list = cache.get('area_fix_list', None)
|
ep_loc_dict['area_fix_id'] = area.id
|
||||||
if not area_fix_list:
|
cache.set(key_str, ep_loc_dict)
|
||||||
area_fix_list = cache_areas_info()
|
ep_blt = blts.employee # 标签绑定人员
|
||||||
if ep_loc_dict.get('area_fix_id', None):
|
if ep_blt:
|
||||||
# 如果存在所在固定区域
|
for i in Access.objects.filter(area=area).order_by('sort'):
|
||||||
area_info = get_area_info_from_cache(ep_loc_dict['area_fix_id'], area_fix_list)
|
# 优先自定义权限过滤
|
||||||
if area_info:
|
if i.post: # 如果是按岗位设定的
|
||||||
# 在该固定区域停留时间(分钟)
|
eps_access = Employee.objects.filter(user__posts=i.post)
|
||||||
stay_minute = int((ep_loc_dict['time2']-ep_loc_dict['time1'])/60)
|
if ep_blt in eps_access and i.type == Access.ACCESS_IN_YES:
|
||||||
# 判断停留时间是否合理
|
|
||||||
# 先通过自定义权限过滤(暂未做)
|
|
||||||
# 再经过通用设置过滤
|
|
||||||
if 0 < stay_minute < area_info['stay_minute_min']:
|
|
||||||
# 触发离岗事件
|
|
||||||
return
|
return
|
||||||
elif area_info['stay_minute_max'] < stay_minute:
|
elif ep_blt in eps_access and i.type == Access.ACCESS_IN_NO:
|
||||||
# 触发超时滞留事件
|
# 触发非法进入事件
|
||||||
|
pass
|
||||||
|
elif i.dept: # 如果是按部门设定的
|
||||||
|
if i.dept.type == 'dept': # 如果是内部部门
|
||||||
|
depts = get_child_queryset2(i.dept)
|
||||||
|
if ep_blt.belong_dept in depts and i.type == Access.ACCESS_IN_YES:
|
||||||
|
return
|
||||||
|
elif ep_blt.belong_dept in depts and i.type == Access.ACCESS_IN_NO:
|
||||||
|
# 触发非法进入事件
|
||||||
|
pass
|
||||||
|
elif i.dept.type == 'rparty': # 如果是相关方
|
||||||
|
if ep_blt.belong_dept == i.dept and i.type == Access.ACCESS_IN_YES:
|
||||||
|
return
|
||||||
|
elif ep_blt.belong_dept == i.dept and i.type == Access.ACCESS_IN_NO:
|
||||||
|
# 触发非法进入事件
|
||||||
|
pass
|
||||||
|
elif i.employee: # 如果是按人设定的
|
||||||
|
if ep_blt == i.employee and i.type == Access.ACCESS_IN_YES:
|
||||||
return
|
return
|
||||||
|
elif ep_blt == i.employee and i.type == Access.ACCESS_IN_NO:
|
||||||
|
# 触发非法进入事件
|
||||||
|
pass
|
||||||
|
# 通用权限设置过滤
|
||||||
|
if ep_blt.type == 'employee' and area.employee_yes:
|
||||||
|
return
|
||||||
|
elif ep_blt.type == 'remployee' and area.remployee_yes:
|
||||||
|
return
|
||||||
|
elif ep_blt.type == 'visitor' and area.visitor_yes:
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
for i in area_fix_list:
|
# 触发非法进入事件
|
||||||
if data['floorNo'] == i['floor_no']:
|
pass
|
||||||
point = shapely.geometry.Point(data['xMillimeter'], data['yMillimeter'])
|
elif area and (not blts):
|
||||||
if i['poly_shape'].intersects(point): # 如果点在多边形中
|
# 触发未知标签进入事件
|
||||||
ep_loc_dict['time1'] = time2
|
|
||||||
ep_loc_dict['are_id'] = i['area_fix_id']
|
|
||||||
ep_loc_dict['time2'] = time2
|
|
||||||
cache.set(key_str, ep_loc_dict)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def blt_online(cls, data):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def blt_offline(cls, data):
|
def rail_out(data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def low_power(data):
|
||||||
|
# 有绑定对象再提示低电量
|
||||||
|
blts = TDevice.objects.filter(code=data['userId']).first()
|
||||||
|
if blts.employee:
|
||||||
|
# 触发低电量提醒事件
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def one_key_alarm(data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def loc_change(data):
|
||||||
|
blts = TDevice.objects.filter(code=data['userId']).first()
|
||||||
|
if blts.employee:
|
||||||
|
# 从缓存查询人员位置信息
|
||||||
|
time2 = int(time.time())
|
||||||
|
key_str = 'ep_{}'.format(blts.employee.id)
|
||||||
|
ep_loc_dict = cache.get_or_set(
|
||||||
|
key_str, get_ep_default(), timeout=None
|
||||||
|
)
|
||||||
|
ep_loc_dict['time2'] = time2
|
||||||
|
# 从缓存里获取固定区域列表信息
|
||||||
|
area_fix_list = cache.get('area_fix_list', None)
|
||||||
|
if not area_fix_list:
|
||||||
|
area_fix_list = cache_areas_info()
|
||||||
|
if ep_loc_dict.get('area_fix_id', None):
|
||||||
|
# 如果存在所在固定区域
|
||||||
|
area_info = get_area_info_from_cache(ep_loc_dict['area_fix_id'], area_fix_list)
|
||||||
|
if area_info:
|
||||||
|
# 在该固定区域停留时间(分钟)
|
||||||
|
stay_minute = int((ep_loc_dict['time2']-ep_loc_dict['time1'])/60)
|
||||||
|
# 判断停留时间是否合理
|
||||||
|
# 先通过自定义权限过滤(暂未做)
|
||||||
|
# 再经过通用设置过滤
|
||||||
|
if 0 < stay_minute < area_info['stay_minute_min']:
|
||||||
|
# 触发离岗事件
|
||||||
|
return
|
||||||
|
elif area_info['stay_minute_max'] < stay_minute:
|
||||||
|
# 触发超时滞留事件
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
for i in area_fix_list:
|
||||||
|
if data['floorNo'] == i['floor_no']:
|
||||||
|
point = shapely.geometry.Point(data['xMillimeter'], data['yMillimeter'])
|
||||||
|
if i['poly_shape'].intersects(point): # 如果点在多边形中
|
||||||
|
ep_loc_dict['time1'] = time2
|
||||||
|
ep_loc_dict['are_id'] = i['area_fix_id']
|
||||||
|
ep_loc_dict['time2'] = time2
|
||||||
|
cache.set(key_str, ep_loc_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def blt_online(data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def blt_offline(data):
|
||||||
|
pass
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
from email.mime import base
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from apps.third.views import DahuaTestView, DhCommonViewSet, SpTestView, XxCommonViewSet, XxTestView
|
from apps.third.views import DahuaTestView, DhCommonViewSet, SpTestView, XxCommonViewSet, XxTestView
|
||||||
from apps.third.views_d import TDeviceViewSet, TlogViewSet
|
from apps.third.views_d import BltViewSet, TDeviceViewSet, TlogViewSet
|
||||||
|
|
||||||
API_BASE_URL = 'api/third/'
|
API_BASE_URL = 'api/third/'
|
||||||
HTML_BASE_URL = 'third/'
|
HTML_BASE_URL = 'third/'
|
||||||
|
@ -11,6 +12,7 @@ router.register('xunxi', XxCommonViewSet, basename='api_xunxi')
|
||||||
router.register('dahua', DhCommonViewSet, basename='api_dahua')
|
router.register('dahua', DhCommonViewSet, basename='api_dahua')
|
||||||
router.register('tdevice', TDeviceViewSet, basename='tdevice')
|
router.register('tdevice', TDeviceViewSet, basename='tdevice')
|
||||||
router.register('tlog', TlogViewSet, basename='tlog')
|
router.register('tlog', TlogViewSet, basename='tlog')
|
||||||
|
router.register('tdevice/blt', BltViewSet, basename='blt')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(API_BASE_URL, include(router.urls)),
|
path(API_BASE_URL, include(router.urls)),
|
||||||
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
from rest_framework.exceptions import ParseError, APIException
|
from rest_framework.exceptions import ParseError, APIException
|
||||||
from apps.ecm.service import EcmService
|
from apps.ecm.service import dispatch_dahua_event, dispatch_xunxi_event
|
||||||
from apps.hrm.services import HrmService
|
from apps.hrm.services import HrmService
|
||||||
from apps.third.tapis import dhapis, xxapis, spapis
|
from apps.third.tapis import dhapis, xxapis, spapis
|
||||||
from apps.third.errors import TAPI_CODE_WRONG
|
from apps.third.errors import TAPI_CODE_WRONG
|
||||||
|
@ -75,7 +75,7 @@ class XxListener(stomp.ConnectionListener):
|
||||||
|
|
||||||
def on_message(self, frame):
|
def on_message(self, frame):
|
||||||
data = json.loads(frame.body)
|
data = json.loads(frame.body)
|
||||||
EcmService.dispatch_xunxi_event(data)
|
dispatch_xunxi_event(data)
|
||||||
print('received a message "%s"' % frame.body)
|
print('received a message "%s"' % frame.body)
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,5 +260,5 @@ class DhCommonViewSet(CreateModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
其他报警转到事件派发
|
其他报警转到事件派发
|
||||||
"""
|
"""
|
||||||
EcmService.dispatch_dahua_event(data=data)
|
dispatch_dahua_event(data=data)
|
||||||
return Response()
|
return Response()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from apps.third.models import TDevice, Tlog
|
from apps.third.models import TDevice, Tlog
|
||||||
from apps.third.serializers import BindAreaSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
|
from apps.third.serializers import BindAreaSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
|
||||||
from apps.utils.viewsets import CustomGenericViewSet
|
from apps.utils.viewsets import CustomGenericViewSet
|
||||||
from rest_framework.mixins import ListModelMixin
|
from rest_framework.mixins import ListModelMixin, CreateModelMixin
|
||||||
from apps.third.clients import xxClient, dhClient, spClient
|
from apps.third.clients import xxClient, dhClient, spClient
|
||||||
from apps.third.tapis import xxapis, dhapis, spapis
|
from apps.third.tapis import xxapis, dhapis, spapis
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -11,6 +11,17 @@ from apps.am.models import Area
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
|
||||||
|
class BltViewSet(CreateModelMixin, CustomGenericViewSet):
|
||||||
|
"""定位标签列表
|
||||||
|
|
||||||
|
定位标签列表
|
||||||
|
"""
|
||||||
|
queryset = TDevice.objects.filter(type=TDevice.DEVICE_BLT)
|
||||||
|
serializer_class = TDeviceSerializer
|
||||||
|
select_related_fields = ['employee']
|
||||||
|
ordering = ['-create_time']
|
||||||
|
|
||||||
|
|
||||||
class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
三方设备接口
|
三方设备接口
|
||||||
|
|
|
@ -29,7 +29,7 @@ def send_sms(phone: str, template_code: str, template_param: dict):
|
||||||
request.add_query_param('TemplateParam', json.dumps(template_param))
|
request.add_query_param('TemplateParam', json.dumps(template_param))
|
||||||
res = client.do_action(request)
|
res = client.do_action(request)
|
||||||
res_dict = json.loads(str(res, encoding='utf-8'))
|
res_dict = json.loads(str(res, encoding='utf-8'))
|
||||||
print(phone, template_code, template_param, res_dict)
|
# print(phone, template_code, template_param, res_dict)
|
||||||
if res_dict['result'] == 0:
|
if res_dict['result'] == 0:
|
||||||
|
|
||||||
return True, res_dict
|
return True, res_dict
|
||||||
|
|
Loading…
Reference in New Issue