package com.sptg.device.biz.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sptg.ad.api.entity.DeviceAdvert;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.UserFlagConstant;
import com.sptg.common.core.entity.DispatchTask;
import com.sptg.common.core.enums.Instruct;
import com.sptg.common.core.enums.InstructDH;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.device.api.constant.DeviceConstants;
import com.sptg.device.api.dto.*;
import com.sptg.device.api.entity.Device;
import com.sptg.device.api.entity.DeviceRemoteInfo;
import com.sptg.device.api.entity.MqConf;
import com.sptg.device.api.feigns.DeviceFeign;
import com.sptg.device.api.feigns.DeviceTemplateFeign;
import com.sptg.device.api.vo.DeviceVO;
import com.sptg.device.api.vo.ManualPushDevicesTask;
import com.sptg.device.biz.service.DeviceServiceInterface;
import com.sptg.device.biz.service.MqConfServiceInterface;
import com.sptg.device.biz.service.MsgPublishService;
import com.sptg.device.biz.stream.DeviceAddProduceInterface;
import com.sptg.estate.api.dto.*;
import com.sptg.estate.api.entity.*;
import com.sptg.estate.api.feigns.*;
import com.sptg.permissions.api.entity.AppPackage;
import com.sptg.permissions.api.entity.Conf;
import com.sptg.permissions.api.feigns.AppPackageFeign;
import com.sptg.permissions.api.feigns.ConfFeign;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * title: DeviceController
 * package: com.sptg.device.biz.controller
 * description: 设备控制器
 *
 *
 *
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class DeviceController implements DeviceFeign {

    private final VideoCallAccountFeign videoCallAccountFeign;
    private final MsgPublishService msgPublishService;
    private final MqConfServiceInterface mqConfServiceInterface;
    private final DeviceServiceInterface deviceServiceInterface;
    private final ResidentialFeign residentialFeign;
    private final DeviceAddProduceInterface deviceAddProduceInterface;
    private final AccessCardPushRecordsFeign accessCardPushRecordsFeign;
    private final AccessFacePushRecordsFeign accessFacePushRecordsFeign;
    private final ConfFeign confFeign;
    private final AppPackageFeign appPackageFeign;

    @Override
    @PostMapping(value = "/device/heartbeat")
    public void heartbeat(@RequestBody Device device) {
        //  获取设备信息
        Device dbDevice = this.deviceServiceInterface.selectBySerialNumber(device.getSerialNumber());
        if (null != dbDevice){
            dbDevice.setLastHeartbeat(System.currentTimeMillis());
            dbDevice.setNetworkType(device.getNetworkType());
            dbDevice.setNetworkSignal(device.getNetworkSignal());
            dbDevice.setVersionNumber(device.getVersionNumber());
            this.deviceServiceInterface.updateById(dbDevice);
        }
    }

    /**
     * 功能描述: 分页查询设备信息
     * @param pageBean 设备数据传输对象
     * @return ResultBean<Page>
     *
     *
     */
    @Override
    @PostMapping(value = "/device/pagingQuery")
    public ResultBean<Page<Device>> pagingQuery(@RequestBody PageBean<Device,DeviceDto> pageBean) {
        Page<Device> devicePage = this.deviceServiceInterface.pagingQuery(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS,devicePage);
    }

    @Override
    @PostMapping(value = "/device/pagingByResidentialIds")
    public ResultBean<Page<Device>> pagingByResidentialIds(@RequestBody DeviceDto deviceDto) {
        return this.deviceServiceInterface.pagingByResidentialIds(deviceDto);
    }

    @Override
    @PostMapping(value = "/device/addEntity")
    public ResultBean<Boolean> addEntity(@RequestBody DeviceDto dto) {
        //  获取此小区下的设备最大排序值
        Integer max = this.deviceServiceInterface.selectMaxXqSort(dto.getXqId());
        dto.setName(dto.getName() + max);
        dto.setXqSort(max);
        dto.setTimeStrategyIsEnable(1);
        //  判断设备序列号是否已经存在
        Device device = this.deviceServiceInterface.selectBySerialNumber(dto.getSerialNumber());
        boolean result;
        if (null == device){
            if (null == dto.getId()){
                dto.setId(IdWorker.getId());
            }
            //  获取可用的队列服务Id
            MqConf conf = this.mqConfServiceInterface.selectUsableServer();
            Assert.notNull(conf,"没有可用的队列服务器");
            dto.setMqId(conf.getId());
            result = this.deviceServiceInterface.insert(dto);
            conf.setThreads(conf.getThreads() + 1);
            this.mqConfServiceInterface.updateById(conf);
        }else {
            dto.setId(device.getId());
            dto.setCreateDate(new Date());
            dto.setMqId(device.getMqId());
            dto.setDeviceFactory(device.getDeviceFactory());
            dto.setVersionNumber(device.getVersionNumber());
            dto.setDeviceModelNumber(device.getDeviceModelNumber());
            dto.setStatus(0);
            result = this.deviceServiceInterface.updateAllColumnById(dto);
        }
        if (result){
            //  通知队列,新增了设备
            Message<DeviceDto> build = MessageBuilder.withPayload(dto).build();
            this.deviceAddProduceInterface.output().send(build);
            if(dto.getHaveCall() != null && dto.getHaveCall().equals(OperationConstant.ONE)){
                VideoCallAccount account = new VideoCallAccount();
                account.setDevice(dto);
                this.videoCallAccountFeign.addEntityByDevice(account);
            }
            Map<String,String> map = new HashMap<>();
            //小区
            if (!StringUtils.isEmpty(dto.getXqName())){
                map.put("xqName",dto.getXqName());
            }else {
                map.put("xqName",null);
            }
            //单元
            if (!StringUtils.isEmpty(dto.getDyName())){
                map.put("unitName",dto.getDyName());
            }else {
                map.put("unitName",null);
            }
            switch (dto.getDeviceFactory()){
                case "JVT":
                    //  通知设备去获取数据
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    //  通知设备基本信息被修改，基本信息就不下发设备了，修改设备配置信息才去下发
//                    this.msgPublishService.asyncPublish(dto,dto,Instruct.update_device_info,map);
                    break;
                default:
                    //  通知设备去获取数据
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    //  通知设备基本信息被修改，基本信息就不下发设备了，修改设备配置信息才去下发
//                    this.msgPublishService.asyncPublish(dto,dto,Instruct.update_device_info,map);
                    break;
            }
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @PostMapping(value = "/device/third/addEntity")
    public ResultBean<Boolean> addThirdEntity(@RequestBody DeviceDto dto) {
        //  获取此小区下的设备最大排序值
        Integer max = this.deviceServiceInterface.selectMaxXqSort(dto.getXqId());
        dto.setName(dto.getName() + max);
        dto.setXqSort(max);
        dto.setTimeStrategyIsEnable(1);
        //  判断设备序列号是否已经存在
        Device device = this.deviceServiceInterface.selectBySerialNumber(dto.getSerialNumber());
        boolean result;
        if (null == device){
            if (null == dto.getId()){
                dto.setId(IdWorker.getId());
            }
            result = this.deviceServiceInterface.insert(dto);
        }else {
            dto.setId(device.getId());
            dto.setCreateDate(new Date());
            dto.setDeviceFactory(device.getDeviceFactory());
            dto.setVersionNumber(device.getVersionNumber());
            dto.setDeviceModelNumber(device.getDeviceModelNumber());
            dto.setStatus(0);
            result = this.deviceServiceInterface.updateAllColumnById(dto);
        }
        if (result){
            //  通知队列,新增了设备
            Message<DeviceDto> build = MessageBuilder.withPayload(dto).build();
            this.deviceAddProduceInterface.output().send(build);
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @PostMapping(value = "/device/completeEntity")
    public ResultBean<Boolean> completeEntity(@RequestBody DeviceDto dto) {
        Integer max = this.deviceServiceInterface.selectMaxXqSort(dto.getXqId());
        dto.setName(dto.getName() + max);
        dto.setXqSort(max);
        Device device = this.deviceServiceInterface.selectBySerialNumber(dto.getSerialNumber());
        boolean result;
        dto.setId(device.getId());
        dto.setMqId(device.getMqId());
        dto.setDeviceFactory(device.getDeviceFactory());
        dto.setVersionNumber(device.getVersionNumber());
        dto.setDeviceModelNumber(device.getDeviceModelNumber());
        dto.setCreateDate(device.getCreateDate());
        dto.setStatus(0);
        result = this.deviceServiceInterface.complete(dto);
        if (result){
            Map<String,String> map = new HashMap<>();
            if (!StringUtils.isEmpty(dto.getXqName())){
                map.put("xqName",dto.getXqName());
            }else {
                map.put("xqName",null);
            }
            if (!StringUtils.isEmpty(dto.getDyName())){
                map.put("unitName",dto.getDyName());
            }else {
                map.put("unitName",null);
            }
            switch (dto.getDeviceFactory()){
                case "dh":
                    break;
                case "qst":
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    break;
                case "sjs":
                    //  通知设备去获取数据
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    break;
                case "JVT":
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    break;
                default:
                    this.msgPublishService.asyncPublish(null,dto,Instruct.pull_data,map);
                    break;
            }
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @GetMapping(value = "/device/get/{id}")
    public Device getEntityById(@PathVariable(value = "id") Long id) {
        return this.deviceServiceInterface.selectById(id);
    }

    @Override
    @GetMapping(value = "/device/getBySerialNumber")
    public Device getEntityBySerialNumber(@RequestParam(value = "serialNumber")String serialNumber) {
        return this.deviceServiceInterface.selectBySerialNumber(serialNumber);
    }

    @Override
    @GetMapping(value = "/device/getByFactory")
    public Device getEntityByFactory(@RequestParam(value = "factory") String factory) {
        return this.deviceServiceInterface.selectByFactory(factory);
    }

    @Override
    @PostMapping(value = "/device/editEntity")
    public ResultBean<Boolean> editEntity(@RequestBody DeviceDto dto) {
        Device dbDevice = this.deviceServiceInterface.selectById(dto.getId());
        Assert.notNull(dbDevice,"设备不存在");
        //  权限校验
        if (!dbDevice.getOrgPosition().startsWith(dto.getOrgPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
//        BeanUtils.copyProperties(dto,dbDevice); 該方法要小心使用，因為很容易覆蓋掉不需要修改的字段
        this.copyProperties(dbDevice, dto);
        if (this.deviceServiceInterface.updateById(dbDevice)){
            Map<String,String> map = new HashMap<>();
            //小区
            if (!StringUtils.isEmpty(dto.getXqName())){
                map.put("xqName",dto.getXqName());
            }else {
                map.put("xqName",null);
            }
            //单元
            if (!StringUtils.isEmpty(dto.getDyName())){
                map.put("unitName",dto.getDyName());
            }else {
                map.put("unitName",null);
            }
            //  通知设备信息被修改
//            this.msgPublishService.asyncPublish(dbDevice,dbDevice,Instruct.update_device_info,map);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }else {
            log.warn("----------设备没有更新数据--------");
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    /**
     * 设备字段更新
     * @param source
     * @param target
     */
    private void copyProperties(Device source, Device target){
        //设备别名修改
        source.setAlias(target.getAlias() != null ? target.getAlias() : source.getAlias());
        //设备尺寸修改
        source.setSize(target.getSize() != null ? target.getSize() : source.getSize());
        //设备屏幕亮度修改
        source.setScreenBrightness(target.getScreenBrightness() != null ? target.getScreenBrightness() : source.getScreenBrightness());
        //设备通话音量修改
        source.setCallVolume(target.getCallVolume() != null ? target.getCallVolume() : source.getCallVolume());
        //设备开门时长修改
        source.setDelay(target.getDelay() != null ? target.getDelay() : source.getDelay());
        //设备管理密码修改
        source.setAdminPwd(target.getAdminPwd() != null ? target.getAdminPwd() : source.getAdminPwd());
        //设置旧紧急开门密码
        source.setOldOpenDoorPwd(source.getOpenDoorPwd() != null ? source.getOpenDoorPwd() : target.getOpenDoorPwd());
        //设备开门密码修改
        source.setOpenDoorPwd(target.getOpenDoorPwd() != null ? target.getOpenDoorPwd() : source.getOpenDoorPwd());
        //是否启用时间策略
        source.setTimeStrategyIsEnable(target.getTimeStrategyIsEnable() != null ? target.getTimeStrategyIsEnable() : source.getTimeStrategyIsEnable());
        //设备朝向修改
        source.setIsOut(target.getIsOut() != null ? target.getIsOut() : source.getIsOut());
        //广告音量修改
        source.setAdVolume(target.getAdVolume() != null ? target.getAdVolume() : source.getAdVolume());
        //广告播放模式修改
        source.setPlayModel(target.getPlayModel() != null ? target.getPlayModel() : source.getPlayModel());
        //是否支持门禁卡功能
        source.setHaveCard(target.getHaveCard() != null ? target.getHaveCard() : source.getHaveCard());
        //是否支持人脸识别功能
        source.setHaveFace(target.getHaveFace() != null ? target.getHaveFace() : source.getHaveFace());
        //是否支持视频通话功能
        source.setHaveCall(target.getHaveCall() != null ? target.getHaveCall() : source.getHaveCall());
        //是否支持一键重启功能
        source.setReboot(target.getReboot() != null ? target.getReboot() : source.getReboot());
        //设备补光灯亮度修改
        source.setFillLight(target.getFillLight() != null ? target.getFillLight() : source.getFillLight());
        //设备识别框位置修改
        source.setDiscernBoxPosition(target.getDiscernBoxPosition() != null ? target.getDiscernBoxPosition() : source.getDiscernBoxPosition());
        //设备人脸识别度修改
        source.setFaceResolution(target.getFaceResolution() != null ? target.getFaceResolution() : source.getFaceResolution());
        //设备是否开启活体检测
        source.setLiveDetect(target.getLiveDetect() != null ? target.getLiveDetect() : source.getLiveDetect());
        //设备备注修改
        source.setRemark(target.getRemark() != null ? target.getRemark() : source.getRemark());
    }

    @Override
    @PostMapping(value = "/device/batchEditEntity")
    public ResultBean<Boolean> batchEditEntity(@RequestBody DeviceDto dto) {
        String position = dto.getOrgPosition();
        Wrapper<Device> wrapper = new EntityWrapper<>();
        wrapper.in("l_id",dto.getIdList());
        wrapper.like("s_org_position",position, SqlLike.RIGHT);
        dto.setOrgPosition(null);
        if (this.deviceServiceInterface.update(dto,wrapper)){
            this.msgPublishService.batchEditDevice(wrapper);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    @Override
    @GetMapping(value = "/device/getListByXqId/{xqId}")
    public List<Device> getListByXqId(@PathVariable(value = "xqId") Long xqId) {
        return this.deviceServiceInterface.selectListByXqId(xqId);
    }

    @Override
    @PostMapping(value = "/device/getListByIds")
    public List<Device> getListByIds(@RequestBody List<Long> idList) {
        List<Device> deviceList = new ArrayList<>(idList.size());
        idList.forEach(id -> {
            Device device = this.deviceServiceInterface.selectById(id);
            if(null!=device){
                deviceList.add(device);
            }
        });
        return deviceList;
    }

    @Override
    @PostMapping(value = "/device/openDoor")
    public ResultBean<Boolean> openDoor(@RequestBody Device device) {
        return pushInstruct(device,Instruct.open_door);
    }

    @Override
    @PostMapping(value = "/device/formatData")
    public ResultBean<Boolean> formatData(@RequestBody DeviceDto deviceDto) {
//        return pushInstruct(deviceDto,Instruct.format_data);
        //  获取设备信息
        Device dbDevice = this.deviceServiceInterface.selectById(deviceDto.getId());
        Assert.notNull(dbDevice,"设备不存在");
        Instruct instruct;
        switch (deviceDto.getSyncMethod()){
            case 0:
                instruct = Instruct.format_data;
                break;
            case 1:
                instruct = Instruct.format_face_advert;
                break;
            case 2:
                instruct = Instruct.format_leisure_advert;
                break;
            case 3:
                instruct = Instruct.format_notice_data;
                break;
            case 4:
                instruct = Instruct.format_user_face;
                break;
            case 5:
                instruct = Instruct.format_server_face;
                break;
            case 6:
                instruct = Instruct.format_card_data;
                break;
            case 7:
                instruct = Instruct.format_open_pwd;
                break;
            default:
                return new ResultBean<>(ResultEnum.ERROR,false);
        }
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(dbDevice.getXqName())){
            map.put("xqName",dbDevice.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(dbDevice.getDyName())){
            map.put("unitName",dbDevice.getDyName());
        }else {
            map.put("unitName",null);
        }
        this.msgPublishService.asyncPublish(null,dbDevice,instruct,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     * 大豪设备格式化指令，清空卡号
     * @param device { id:设备Id,必填 }
     * @return
     */
    @Override
    @PostMapping(value = "/device/dh/formatData")
    public ResultBean<Boolean> dhFormatData(@RequestBody Device device) {
        Instruct instruct = Instruct.format_data;
        InstructDH instructDH = new InstructDH();
        instructDH.setCode(instruct.getCode());
        instructDH.setExchangeName(instructDH.getDHExchange(instruct.getExchangeName()));
        instructDH.setDescribe(instruct.getDescribe());
        AccessCard accessCard = new AccessCard();
        accessCard.setCardNo("00000000"); //8个0表示清空设备上的所有卡号
        Device dbDevice = this.deviceServiceInterface.selectById(device.getId());
        Assert.notNull(dbDevice, "设备不存在");
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(dbDevice.getXqName())){
            map.put("xqName",dbDevice.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(dbDevice.getDyName())){
            map.put("unitName",dbDevice.getDyName());
        }else if (!StringUtils.isEmpty(accessCard.getUnitName())){
            map.put("unitName",accessCard.getUnitName());
        }else {
            map.put("unitName",null);
        }
        //房间
        if (!StringUtils.isEmpty(accessCard.getRoomName())){
            map.put("roomName",accessCard.getRoomName());
        }else {
            map.put("roomName",null);
        }
        //用户名
        if (!StringUtils.isEmpty(accessCard.getUserName())){
            map.put("userName",accessCard.getUserName());
        }else {
            map.put("userName",null);
        }
        //卡号
        if (!StringUtils.isEmpty(accessCard.getCardNo())){
            map.put("cardNo",accessCard.getCardNo());
        }else {
            map.put("cardNo",null);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != accessCard.getBeginDate()){
            map.put("beginTime",format.format(accessCard.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (null != accessCard.getEndDate()){
            map.put("endTime",format.format(accessCard.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        this.msgPublishService.topicMsgAsyncPublish(accessCard, dbDevice, instructDH, map);
        return ResultBean.ok(true);
    }

    @Override
    @PostMapping(value = "/device/restart")
    public ResultBean<Boolean> restart(@RequestBody Device device) {
        return pushInstruct(device,Instruct.restart);
    }

    @Override
    @PostMapping(value = "/device/checkOnline")
    public ResultBean<Boolean> checkOnline(@RequestBody Device device) {
        return checkOnline(device,Instruct.check_online);
    }

    @Override
    @PostMapping(value = "/device/restore")
    public ResultBean<Boolean> restore(@RequestBody Device device) {
        Device dbDevice = this.deviceServiceInterface.selectById(device.getId());
        AppPackage restorePkg = this.appPackageFeign.getRestore(dbDevice.getDeviceModelNumber(), dbDevice.getDeviceFactory());
        Assert.isNull(restorePkg, "当前版本已经是恢复版，无需恢复");
        return pushInstruct(device,Instruct.restore);
    }

    @Override
    public ResultBean<Boolean> syncData(@RequestBody DeviceDto dto) {
        //  获取设备信息
        Device dbDevice = this.deviceServiceInterface.selectById(dto.getId());
        Assert.notNull(dbDevice,"设备不存在");
        Instruct instruct;
        switch (dto.getSyncMethod()){
            case 0:
                instruct = Instruct.pull_data;
                break;
            case 1:
                instruct = Instruct.sync_face_advert;
                break;
            case 2:
                instruct = Instruct.sync_leisure_advert;
                break;
            case 3:
                instruct = Instruct.sync_notice_data;
                break;
            case 4:
                instruct = Instruct.sync_user_face;
                break;
            case 5:
                instruct = Instruct.sync_server_face;
                break;
            case 6:
                instruct = Instruct.sync_card_data;
                break;
            case 7:
                instruct = Instruct.sync_open_pwd;
                break;
            default:
                return new ResultBean<>(ResultEnum.ERROR,false);
        }
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(dbDevice.getXqName())){
            map.put("xqName",dbDevice.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(dbDevice.getDyName())){
            map.put("unitName",dbDevice.getDyName());
        }else {
            map.put("unitName",null);
        }
        this.msgPublishService.asyncPublish(null,dbDevice,instruct,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    public ResultBean<Boolean> dhSyncData(DeviceDto dto) {
        return null;
    }

    @Override
    @PostMapping(value = "/device/pushOpenDoorPwd")
    public ResultBean<Boolean> pushOpenDoorPwd(@RequestBody DispatchTask task,@RequestParam Map<String,String> map) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getUnitId(),"单元Id不能为空");
        Assert.notNull(task.getData(),"开门密码不能为空");
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_pwd,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushTestOpenDoorPwd")
    public ResultBean<Boolean> pushTestOpenDoorPwd(@RequestBody DispatchTask task,@RequestParam Map<String,String> map) {
        Assert.hasText(task.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(task.getData(),"开门密码不能为空");
        //  获取设备信息
        Device device = this.deviceServiceInterface.selectBySerialNumber(task.getSerialNumber());
        //小区
        if (!StringUtils.isEmpty(device.getXqName())){
            map.put("xqName",device.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(device.getDyName())){
            map.put("unitName",device.getDyName());
        }else {
            map.put("unitName",null);
        }
        this.msgPublishService.asyncPublish(task.getData(),device,Instruct.add_open_door_pwd,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/removeOpenDoorPwd")
    public ResultBean<Boolean> removeOpenDoorPwd(@RequestBody DispatchTask task,@RequestParam Map<String,String> map) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getUnitId(),"单元Id不能为空");
        Assert.notNull(task.getData(),"开门密码不能为空");
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_pwd,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushUserFace")
    public ResultBean<Boolean> pushUserFace(@RequestBody DispatchTask task, @RequestParam Map<String,String> map) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"人脸信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfoDto userInfoDto = objectMapper.convertValue(task.getData(), UserInfoDto.class);
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != userInfoDto.getBeginDate()){
            map.put("beginTime",format.format(userInfoDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (null != userInfoDto.getEndDate()){
            map.put("endTime",format.format(userInfoDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        //人脸
        if (userInfoDto.getFaceCodeList().size() > 0){
            List<String> list = new ArrayList<>();
            for (Map m : userInfoDto.getFaceCodeList()) {
                if (m.containsKey("imgSrc")){
                    list.add(m.get("imgSrc").toString());
                }
            }
            map.put("imgSrc", JsonUtils.listToString(list));
        }else {
            map.put("imgSrc",null);
        }
        List<Map<String, Object>> faceCodeList = userInfoDto.getFaceCodeList();
        if(faceCodeList == null || faceCodeList.size() == 0){
            String deleteUser = map.get("deleteUser");
            if(deleteUser != null && deleteUser.equals("true")){
                this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.delete_user,map);
            }else{
                this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.delete_user_face,map);
            }
        }else{
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_user_face,map);
        }
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/deleteUserFaceBatch")
    public ResultBean<Boolean> deleteUserFaceBatch(@RequestBody List<FaceInfoDto> faceInfoDtoList) {
        ResultBean<Boolean> resultBean = this.handleIssueUserFaceBatch(faceInfoDtoList, Instruct.delete_user_face_batch);
        return resultBean;
    }

    @Override
    @PostMapping(value = "/device/issueUserFaceBatch")
    public ResultBean<Boolean> issueUserFaceBatch(@RequestBody List<FaceInfoDto> faceInfoDtoList) {
        ResultBean<Boolean> resultBean = this.handleIssueUserFaceBatch(faceInfoDtoList, Instruct.add_user_face_batch);
        return resultBean;
    }

    /**
     * 批量处理人脸下发指令
     * @param faceInfoDtoList
     * @param instruct
     * @return
     */
    private ResultBean<Boolean> handleIssueUserFaceBatch(List<FaceInfoDto> faceInfoDtoList, Instruct instruct) {
        Map<String, List<FaceInfoDto>> deviceDataMap = new HashMap<>();
        for(FaceInfoDto dto : faceInfoDtoList){
            List<Device> deviceList = this.getListByEstateUser(dto.getResidentialId(), dto.getUnitId());
            for(Device device : deviceList){
                String serialNumber = device.getSerialNumber();
                if(deviceDataMap.containsKey(serialNumber)){
                    deviceDataMap.get(serialNumber).add(dto);
                }else{
                    List<FaceInfoDto> faceInfoDtos = new ArrayList<>();
                    faceInfoDtos.add(dto);
                    deviceDataMap.put(serialNumber, faceInfoDtos);
                }
            }
        }
        for(String serialNumber : deviceDataMap.keySet()){
            Device device = this.deviceServiceInterface.selectBySerialNumber(serialNumber);
            List<FaceInfoDto> faceInfoDtos = deviceDataMap.get(serialNumber);
            BatchFaceDto batchFaceDto = new BatchFaceDto();
            batchFaceDto.setTotal(faceInfoDtos.size());
            batchFaceDto.setFaceInfo(faceInfoDtos);
            this.msgPublishService.batchPushInstruct(batchFaceDto, device, instruct);
        }
        return new ResultBean<>(ResultEnum.SUCCESS, true);
    }

    @Override
    @PostMapping(value = "/device/pushUserFaceToUniversalDevices/{operType}")
    public ResultBean<Boolean> pushUserFaceToUniversalDevices(@RequestBody DispatchTask task, @PathVariable(value = "operType") Integer operType, @RequestParam Map<String,String> map) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"人脸信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfoDto userInfoDto = objectMapper.convertValue(task.getData(), UserInfoDto.class);
        List<Device> deviceList = this.deviceServiceInterface.getDeviceByPathUseAndType(task.getXqId(), task.getUnitId(), DeviceConstants.DEVICE_ACCESS_TYPE_UNIVERSAL, OperationConstant.TWO);
        if(deviceList == null || deviceList.size() < 0){
//            Assert.notEmpty(deviceList, "小区下无人脸机，无需下发人脸");
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != userInfoDto.getBeginDate()){
            map.put("beginTime",format.format(userInfoDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (null != userInfoDto.getEndDate()){
            map.put("endTime",format.format(userInfoDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        //人脸
        if (userInfoDto.getFaceCodeList().size() > 0){
            List<String> list = new ArrayList<>();
            for (Map m : userInfoDto.getFaceCodeList()) {
                if (m.containsKey("imgSrc")){
                    list.add(m.get("imgSrc").toString());
                }
            }
            map.put("imgSrc", JsonUtils.listToString(list));
        }else {
            map.put("imgSrc",null);
        }
        if(operType.equals(OperationConstant.ONE)){
            //  获取设备列表
//            deviceList = this.deviceServiceInterface.getListByPathUse(task.getXqId(), task.getUnitId(), DeviceConstants.DEVICE_ACCESS_TYPE_UNIVERSAL);
            // 下发
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_user_face,map);
        }else if(operType.equals(OperationConstant.TWO)){ //更新人脸,只更新已经下发过的设备
            String id = userInfoDto.getId();
            Long userId = Long.parseLong(id.substring(OperationConstant.TWO));
            Integer accessUserType = OperationConstant.ZERO;
            if(id.startsWith(UserFlagConstant.SERVER_USER_NUMBER_FLAG)){
                accessUserType = OperationConstant.FOUR;
            }else if(id.startsWith(UserFlagConstant.USER_NUMBER_FLAG)){

            }
            ResultBean<AccessFacePushRecords> resultBean = this.accessFacePushRecordsFeign.getListByUserId(userId, accessUserType, OperationConstant.TWO);
            List<AccessFacePushRecords> pushRecords = resultBean.getList();
            if(pushRecords != null && pushRecords.size() > 0){
                List<Long> deviceIdList = new ArrayList<>();
                pushRecords.forEach(push -> {
                    deviceIdList.add(push.getDeviceId());
                });
                Wrapper<Device> wrapper = new EntityWrapper<>();
                wrapper.in("l_id", deviceIdList);
                List<Device> specialDeviceList = this.deviceServiceInterface.selectList(wrapper);
                deviceList.addAll(specialDeviceList);
            }
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_user_face,map);
        }

        /*--------------------------------------------------记录用户人脸授权下发设备记录------------------------------------------*/
        //获取用户
//        User user = this.userFeign.findUserById(Long.parseLong(userInfoDto.getId().substring(OperationConstant.TWO)));
//        this.editAccessFacePushRecords(userInfoDto, operType, deviceList,user.getFaceBeginDate(),user.getFaceEndDate());
        /*---------------------------------------------------------------------------------------------------------------------*/
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    public ResultBean<Boolean> deleteUserFaceToUniversalDevices(DispatchTask task, Map<String, String> map) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"人脸信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfoDto userInfoDto = objectMapper.convertValue(task.getData(), UserInfoDto.class);
        List<Device> deviceList = this.deviceServiceInterface.getDeviceByPathUseAndType(task.getXqId(), task.getUnitId(), DeviceConstants.DEVICE_ACCESS_TYPE_UNIVERSAL, OperationConstant.TWO);
        if(deviceList == null || deviceList.size() < 0){
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != userInfoDto.getBeginDate()){
            map.put("beginTime",format.format(userInfoDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (null != userInfoDto.getEndDate()){
            map.put("endTime",format.format(userInfoDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        //人脸
        if (userInfoDto.getFaceCodeList().size() > 0){
            List<String> list = new ArrayList<>();
            for (Map m : userInfoDto.getFaceCodeList()) {
                if (m.containsKey("imgSrc")){
                    list.add(m.get("imgSrc").toString());
                }
            }
            map.put("imgSrc", JsonUtils.listToString(list));
        }else {
            map.put("imgSrc",null);
        }

        String id = userInfoDto.getId();
        Long userId = Long.parseLong(id.substring(OperationConstant.TWO));
        Integer accessUserType = OperationConstant.ZERO;
        if(id.startsWith(UserFlagConstant.SERVER_USER_FLAG)){
            accessUserType = OperationConstant.FOUR;
        }else if(id.startsWith(UserFlagConstant.USER_FLAG)){

        }
        ResultBean<AccessFacePushRecords> resultBean = this.accessFacePushRecordsFeign.getListByUserId(userId, accessUserType, OperationConstant.TWO);
        List<AccessFacePushRecords> pushRecords = resultBean.getList();
        if(pushRecords != null && pushRecords.size() > 0){
            List<Long> deviceIdList = new ArrayList<>();
            pushRecords.forEach(push -> {
                deviceIdList.add(push.getDeviceId());
            });
            Wrapper<Device> wrapper = new EntityWrapper<>();
            wrapper.in("l_id", deviceIdList);
            List<Device> specialDeviceList = this.deviceServiceInterface.selectList(wrapper);
            deviceList.addAll(specialDeviceList);
            this.msgPublishService.batchPushInstruct(task.getData(), deviceList, Instruct.delete_user_face,map);
        }else{
            this.msgPublishService.batchPushInstruct(task.getData(), deviceList, Instruct.delete_user_face,map);
        }

        /*--------------------------------------------------记录用户人脸授权下发设备记录------------------------------------------*/
        //获取用户
//        User user = this.userFeign.findUserById(Long.parseLong(userInfoDto.getId().substring(OperationConstant.TWO)));
//        this.editAccessFacePushRecords(userInfoDto, operType, deviceList,user.getFaceBeginDate(),user.getFaceEndDate());
        /*---------------------------------------------------------------------------------------------------------------------*/
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     * 人工下发人脸到指定设备上
     * @param task 任务
     * @return
     */
    @Override
    @PostMapping(value = "/device/manualPushUserFaceToDevices")
    public ResultBean<Boolean> manualPushUserFaceToDevices(@RequestBody ManualPushDevicesTask task) {
        Assert.notNull(task.getDeviceIdList(),"设备列表不能为空");
        Assert.notNull(task.getData(),"人脸信息不能为空");
        //  获取设备列表
        Wrapper<Device> wrapper = new EntityWrapper<>();
        wrapper.in("l_id",task.getDeviceIdList());
        List<Device> deviceList = this.deviceServiceInterface.selectList(wrapper);
        Map<String,String> map = new HashMap<>();
        if(task.getOperType().equals(OperationConstant.TWO)){ //新增人脸

            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.delete_user_face,map);
            try{
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }

            this.msgPublishService.batchPushInstruct(task.getData(), deviceList, Instruct.add_user_face, map);
        }else{
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.delete_user_face,map);
        }
        /*--------------------------------------------------记录用户人脸授权下发设备记录------------------------------------------*/
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfoDto userInfoDto = objectMapper.convertValue(task.getData(), UserInfoDto.class);
        if(task.getOperType() != null){
            this.editAccessFacePushRecords(userInfoDto, task.getOperType(), deviceList, task.getBeginDate(), task.getEndDate());
        }
        /*---------------------------------------------------------------------------------------------------------------------*/
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     * 编辑用户人脸下发到特殊设备记录
     * @param dto
     * @param operType
     * @param deviceList
     */
    private void editAccessFacePushRecords(UserInfoDto dto, Integer operType, List<Device> deviceList, Date beginDate, Date endDate){
        String id = dto.getId(); //u_120000，s_12000等，表示用户ID，前缀表示用户类型
        AccessFacePushRecordsDto recordsDto = new AccessFacePushRecordsDto();
        Long userId = Long.parseLong(id.substring(OperationConstant.TWO));
        recordsDto.setUserId(Long.parseLong(id.substring(OperationConstant.TWO)));
        //设置人脸有效期 如果是禁用，则不改变有效时间
        recordsDto.setBeginDate(beginDate);
        recordsDto.setEndDate(endDate);

        Map<String, Object> face = null;
        if(!operType.equals(OperationConstant.THREE)){
            face = dto.getFaceCodeList().get(0);
            recordsDto.setFaceUri((String)face.get("imgSrc"));
        }
        Integer accessUserType = OperationConstant.ZERO;
        if(id.startsWith(UserFlagConstant.SERVER_USER_FLAG)){
            recordsDto.setAccessUserType(OperationConstant.FOUR); //服务人员
            accessUserType = OperationConstant.FOUR;
        }else if(id.startsWith(UserFlagConstant.USER_FLAG)){
            recordsDto.setAccessUserType(OperationConstant.ZERO); //住户
        }
        if(operType.equals(OperationConstant.ONE)){ //新增门禁卡到设备
            List<Long> deviceIdList = new ArrayList<>();
            deviceList.forEach(device -> {
                deviceIdList.add(device.getId());
            });
            recordsDto.setDeviceIdList(deviceIdList);
            recordsDto.setEnable(OperationConstant.ONE);
            recordsDto.setSendDeviceType(OperationConstant.TWO);
            this.accessFacePushRecordsFeign.addAccessFacePushRecordsByDevices(recordsDto);
        }else if(operType.equals(OperationConstant.TWO)){ //更新门禁卡到设备
//            List<Long> addDeviceIdList = new ArrayList<>();
//            ResultBean<AccessFacePushRecords> resultBean = accessFacePushRecordsFeign.getListByUserId(userId, accessUserType, null);
//            List<AccessFacePushRecords> pushRecords = resultBean.getList();
//            if(pushRecords != null && pushRecords.size() > 0){
//
//            }
//            List<Long> hadPushDeviceIdList = new ArrayList<>();
//            resultBean.getList().forEach(push -> {
//                hadPushDeviceIdList.add(push.getDeviceId());
//            });
//            List<Long> deviceIdList = new ArrayList<>();
//            deviceList.forEach(device -> {
//                deviceIdList.add(device.getId());
//            });
//            deviceIdList.forEach(deviceId ->{
//                if(hadPushDeviceIdList.contains(deviceId)){
//
//                }else{
//                    addDeviceIdList.add(deviceId);
//                }
//            } );
//            recordsDto.setEnable(OperationConstant.ONE);
//            this.accessFacePushRecordsFeign.updateAccessFacePushRecords(recordsDto);
//            if(addDeviceIdList.size() > 0){
//                recordsDto.setDeviceIdList(addDeviceIdList);
//                this.accessFacePushRecordsFeign.addAccessFacePushRecordsByDevices(recordsDto);
//            }
        }else if(operType.equals(OperationConstant.THREE)){ //删除或者禁用了
//            recordsDto.setEnable(OperationConstant.TWO);
            this.accessFacePushRecordsFeign.deleteAccessFacePushRecords(recordsDto);
//            this.accessFacePushRecordsFeign.updateAccessFacePushRecords(recordsDto);
        }
    }

    @Override
    @PostMapping(value = "/device/manualPushUserCardToDevices")
    public ResultBean<Boolean> manualPushUserCardToDevices(@RequestBody ManualPushDevicesTask task) {
        Assert.notNull(task.getDeviceIdList(),"设备列表不能为空");
        Assert.notNull(task.getData(),"卡片信息不能为空");
        //  获取设备列表
        Wrapper<Device> wrapper = new EntityWrapper<>();
        wrapper.in("l_id",task.getDeviceIdList());
        List<Device> deviceList = this.deviceServiceInterface.selectList(wrapper);
        Map<String,String> map = new HashMap<>();
        if(task.getEnable()){
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_card,map);
        }else{
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_card,map);
        }
        /*--------------------------------------------------记录用户门禁卡授权下发设备记录------------------------------------------*/
        ObjectMapper objectMapper = new ObjectMapper();
        AccessCardDto accessCardDto = objectMapper.convertValue(task.getData(), AccessCardDto.class);
        if(task.getOperType() != null){
            this.editAccessCardPushRecords(accessCardDto, task.getOperType(), deviceList,task.getBeginDate(),task.getEndDate());
        }
        /*---------------------------------------------------------------------------------------------------------------------*/
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushTestFace")
    public ResultBean<Boolean> pushTestFace(@RequestBody DispatchTask task) {
        Assert.hasText(task.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(task.getData(),"人脸信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfoDto userInfoDto = objectMapper.convertValue(task.getData(), UserInfoDto.class);
        //  获取设备信息
        Device device = this.deviceServiceInterface.selectBySerialNumber(task.getSerialNumber());
        Map<String,String> map = new HashMap<>();
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != userInfoDto.getBeginDate()){
            map.put("beginTime",format.format(userInfoDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (null != userInfoDto.getEndDate()){
            map.put("endTime",format.format(userInfoDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        //人脸
        if (userInfoDto.getFaceCodeList().size() > 0){
            List<String> list = new ArrayList<>();
            for (Map m : userInfoDto.getFaceCodeList()) {
                if (m.containsKey("imgSrc")){
                    list.add(m.get("imgSrc").toString());
                }
            }
            map.put("imgSrc", JsonUtils.listToString(list));
        }else {
            map.put("imgSrc",null);
        }
        this.msgPublishService.asyncPublish(task.getData(),device,Instruct.add_user_face,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushCard")
    public ResultBean<Boolean> pushCard(@RequestBody DispatchTask task) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        Map<String,String> map = new HashMap<>();
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_card,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushCardToNoDh")
    public ResultBean<Boolean> pushCardToNoDh(@RequestBody DispatchTask task) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        //  获取设备列表，排除大豪设备
        DeviceVO deviceVO = new DeviceVO();
        deviceVO.setXqId(task.getXqId());
        deviceVO.setUnitId(task.getUnitId());
        deviceVO.setFactory(task.getFactory());
        deviceVO.setInOrNotIn(OperationConstant.TWO);
        List<Device> deviceList = this.deviceServiceInterface.getListByCondition(deviceVO);
        Map<String,String> map = new HashMap<>();
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_card,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     * 大豪批量发卡任务
     * @param task 任务
     * @return
     */
    @Override
    @PostMapping(value = "/device/pushCardsToDHDevice")
    public ResultBean<Boolean> pushCardsToDHDevice(@RequestBody DispatchTask task) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        AccessCard accessCard = objectMapper.convertValue(task.getData(),AccessCard.class);
        //  获取设备列表
        Device device = this.deviceServiceInterface.selectBySerialNumber(task.getSerialNumber());
        InstructDH instructDH = new InstructDH();
        instructDH.setCode("add_open_door_card");
        instructDH.setBatchCode("add_open_door_card_batch");
        instructDH.setExchangeName("PERSISTENT_EXCHANGE_DH");
        instructDH.setDescribe("添加门禁卡");
        Map<String,String> logMap = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(accessCard.getResidentialName())){
            logMap.put("xqName",accessCard.getResidentialName());
        }else {
            logMap.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(accessCard.getUnitName())){
            logMap.put("unitName",accessCard.getUnitName());
        }else {
            logMap.put("unitName",null);
        }
        //房间
        if (!StringUtils.isEmpty(accessCard.getRoomName())){
            logMap.put("roomName",accessCard.getRoomName());
        }else {
            logMap.put("roomName",null);
        }
        //用户名
        if (!StringUtils.isEmpty(accessCard.getUserName())){
            logMap.put("userName",accessCard.getUserName());
        }else {
            logMap.put("userName",null);
        }
        //卡号
        if (!StringUtils.isEmpty(accessCard.getCardNo())){
            logMap.put("userName",accessCard.getCardNo());
        }else {
            logMap.put("userName",null);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != accessCard.getBeginDate()){
            logMap.put("beginTime",format.format(accessCard.getBeginDate()));
        }else {
            logMap.put("beginTime",null);
        }
        //有效期结束时间
        if (null != accessCard.getEndDate()){
            logMap.put("endTime",format.format(accessCard.getEndDate()));
        }else {
            logMap.put("endTime",null);
        }
        this.msgPublishService.topicMsgBatchPushInstruct(task.getData(),device,instructDH, logMap);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     *
     * @param task 任务
     * @param operType 1：新增门禁卡到一般位置上的设备。2：更新门禁卡到一般位置上的设备
     * @return
     */
    @Override
    @PostMapping(value = "/device/pushCardToUniversalDevices/{operType}")
    public ResultBean<Boolean> pushCardToUniversalDevices(@RequestBody DispatchTask task, @PathVariable(value = "operType") Integer operType) {
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        ObjectMapper objectMapper = new ObjectMapper();
        AccessCardDto accessCardDto = objectMapper.convertValue(task.getData(), AccessCardDto.class);
        List<Device> deviceList = this.deviceServiceInterface.getDeviceByPathUseAndType(task.getXqId(), task.getUnitId(), DeviceConstants.DEVICE_ACCESS_TYPE_UNIVERSAL, OperationConstant.ONE);
        if(deviceList == null || deviceList.size() <= 0){
//            Assert.notEmpty(deviceList, "小区下无刷卡门禁机，无需下发门禁卡");
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(accessCardDto.getResidentialName())){
            map.put("xqName",accessCardDto.getResidentialName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(accessCardDto.getUnitName())){
            map.put("unitName",accessCardDto.getUnitName());
        }else {
            map.put("unitName",null);
        }
        //房间
        if (!StringUtils.isEmpty(accessCardDto.getRoomName())){
            map.put("roomName",accessCardDto.getRoomName());
        }else {
            map.put("roomName",null);
        }
        //用户名
        if (!StringUtils.isEmpty(accessCardDto.getUserName())){
            map.put("userName",accessCardDto.getUserName());
        }else {
            map.put("userName",null);
        }
        //卡号
        if (!StringUtils.isEmpty(accessCardDto.getCardNo())){
            map.put("cardNo",accessCardDto.getCardNo());
        }else {
            map.put("cardNo",null);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (!StringUtils.isEmpty(accessCardDto.getBeginDate())){
            map.put("beginTime",format.format(accessCardDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (!StringUtils.isEmpty(accessCardDto.getEndDate())){
            map.put("endTime",format.format(accessCardDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        if(operType.equals(OperationConstant.ONE)){ //新增下发门禁卡到通用设备
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_card,map);
        }else if(operType.equals(OperationConstant.TWO)){ //更新下发门禁卡到以下发过的设备
            //是否有下发过特殊设备
            ResultBean<AccessCardPushRecords> resultBean = this.accessCardPushRecordsFeign.getListByUserId(Long.parseLong(accessCardDto.getUserId()), accessCardDto.getType(), OperationConstant.TWO);
            List<AccessCardPushRecords> pushRecords = resultBean.getList();
            if(pushRecords != null && pushRecords.size() > 0){
                List<Long> deviceIdList = new ArrayList<>();
                pushRecords.forEach(push -> {
                    deviceIdList.add(push.getDeviceId());
                });
                Wrapper<Device> wrapper = new EntityWrapper<>();
                wrapper.in("l_id", deviceIdList);
                List<Device> specialDeviceList = this.deviceServiceInterface.selectList(wrapper);
                //如果有特殊设备则增加特殊设备
                if (specialDeviceList != null && specialDeviceList.size() >0){
                    deviceList.addAll(specialDeviceList);
                }
            }
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_open_door_card,map);
        }
        /*--------------------------------------------------记录用户门禁卡授权下发设备记录------------------------------------------*/
        /*if(StringUtils.hasText(accessCardDto.getUserId())){ //如果是不记名门禁卡下发，就不记录用户下发门禁卡记录了
            this.editAccessCardPushRecords(accessCardDto, operType, deviceList,accessCardDto.getBeginDate(),accessCardDto.getEndDate());
        }*/
        /*---------------------------------------------------------------------------------------------------------------------*/
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    /**
     *
     * @param accessCardSimpleDtoList
     * @return
     */
    @Override
    @PostMapping(value = "/device/pushCardToUniversalDevicesBatch")
    public ResultBean<Boolean> pushCardToUniversalDevicesBatch(@RequestBody List<AccessCardSimpleDto> accessCardSimpleDtoList) {
        ResultBean<Boolean> resultBean = this.handleIssueCardBatch(accessCardSimpleDtoList, Instruct.add_open_door_card_batch);
        return resultBean;
    }

    private void editAccessCardPushRecords(AccessCardDto accessCardDto, Integer operType, List<Device> deviceList,Date beginDate, Date endDate){
        AccessCardPushRecordsDto recordsDto = new AccessCardPushRecordsDto();
        Long userId = Long.parseLong(accessCardDto.getUserId());
        recordsDto.setUserId(userId);
        recordsDto.setCardNo(accessCardDto.getCardNo());
        recordsDto.setBeginDate(beginDate);
        recordsDto.setEndDate(endDate);
        Integer accessUserType = OperationConstant.ZERO;
        if(accessCardDto.getType().equals(OperationConstant.FOUR)){
            recordsDto.setAccessUserType(OperationConstant.FOUR); //服务人员
            accessUserType = OperationConstant.FOUR;
        }else if(accessCardDto.getType().equals(OperationConstant.ZERO)){
            recordsDto.setAccessUserType(OperationConstant.ZERO); //住户
        }
        if(operType.equals(OperationConstant.ONE)){ //新增门禁卡到设备
            List<Long> deviceIdList = new ArrayList<>();
            deviceList.forEach(device -> {
                deviceIdList.add(device.getId());
            });
            recordsDto.setDeviceIdList(deviceIdList);
            recordsDto.setEnable(OperationConstant.ONE);
            recordsDto.setSendDeviceType(OperationConstant.TWO);
            this.accessCardPushRecordsFeign.addAccessCardPushRecordsByDevices(recordsDto);
        }else if(operType.equals(OperationConstant.TWO)){ //更新门禁卡到设备
//            List<Long> addDeviceIdList = new ArrayList<>();
//            ResultBean<AccessCardPushRecords> resultBean = accessCardPushRecordsFeign.getListByUserId(userId, accessUserType, null);
//            List<Long> hadPushDeviceIdList = new ArrayList<>();
//            resultBean.getList().forEach(push -> {
//                hadPushDeviceIdList.add(push.getDeviceId());
//            });
//            List<Long> deviceIdList = new ArrayList<>();
//            deviceList.forEach(device -> {
//                deviceIdList.add(device.getId());
//            });
//            deviceIdList.forEach(deviceId ->{
//                if(hadPushDeviceIdList.contains(deviceId)){
//
//                }else{
//                    addDeviceIdList.add(deviceId);
//                }
//            } );
//            recordsDto.setEnable(OperationConstant.ONE);
//            this.accessCardPushRecordsFeign.updateAccessCardPushRecords(recordsDto);
//            if(addDeviceIdList.size() > 0){
//                recordsDto.setDeviceIdList(addDeviceIdList);
//                this.accessCardPushRecordsFeign.addAccessCardPushRecordsByDevices(recordsDto);
//            }
        }else if(operType.equals(OperationConstant.THREE)){ //删除或者禁用门禁卡了，仅设置禁用状态
//            recordsDto.setEnable(OperationConstant.TWO);
            this.accessCardPushRecordsFeign.deleteAccessCardPushRecords(recordsDto);
//            this.accessCardPushRecordsFeign.updateAccessCardPushRecords(recordsDto);
        }
    }
    @Override
    @PostMapping(value = "/device/removeCard")
    public ResultBean<Boolean> removeCard(@RequestBody DispatchTask task) {
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        Map<String,String> map = new HashMap<>();
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_card,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/removePushCard")
    public ResultBean<Boolean> removePushCard(@RequestBody DispatchTask task) {
        Assert.notNull(task.getData(),"门禁卡信息不能为空");
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        //  获取设备列表
        ObjectMapper objectMapper = new ObjectMapper();
        AccessCardDto accessCardDto = objectMapper.convertValue(task.getData(), AccessCardDto.class);
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(accessCardDto.getResidentialName())){
            map.put("xqName",accessCardDto.getResidentialName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(accessCardDto.getUnitName())){
            map.put("unitName",accessCardDto.getUnitName());
        }else {
            map.put("unitName",null);
        }
        //房间
        if (!StringUtils.isEmpty(accessCardDto.getRoomName())){
            map.put("roomName",accessCardDto.getRoomName());
        }else {
            map.put("roomName",null);
        }
        //用户名
        if (!StringUtils.isEmpty(accessCardDto.getUserName())){
            map.put("userName",accessCardDto.getUserName());
        }else {
            map.put("userName",null);
        }
        //卡号
        if (!StringUtils.isEmpty(accessCardDto.getCardNo())){
            map.put("cardNo",accessCardDto.getCardNo());
        }else {
            map.put("cardNo",null);
        }
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (!StringUtils.isEmpty(accessCardDto.getBeginDate())){
            map.put("beginTime",format.format(accessCardDto.getBeginDate()));
        }else {
            map.put("beginTime",null);
        }
        //有效期结束时间
        if (!StringUtils.isEmpty(accessCardDto.getEndDate())){
            map.put("endTime",format.format(accessCardDto.getEndDate()));
        }else {
            map.put("endTime",null);
        }
        if(accessCardDto.getUserId() != null){
            ResultBean<AccessCardPushRecords> pushResult = this.accessCardPushRecordsFeign.getListByUserId(Long.parseLong(accessCardDto.getUserId()), accessCardDto.getType(), null);
            List<AccessCardPushRecords> list = pushResult.getList();
            List<Device> hadPushDevices = null;
            if(list != null && list.size() > 0){ //如果有下发记录，就按照下发的记录进行删除或者禁用
                List<Long> deviceIdList = new ArrayList<>();
                list.forEach(push -> {
                    deviceIdList.add(push.getDeviceId());
                });
                hadPushDevices = this.deviceServiceInterface.selectBatchIds(deviceIdList);
                if(hadPushDevices != null && hadPushDevices.size() > 0){
                    deviceList.addAll(hadPushDevices);
                }
                this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_card,map);
                AccessCardPushRecordsDto recordsDto = new AccessCardPushRecordsDto();
                recordsDto.setUserId(Long.parseLong(accessCardDto.getUserId()));
                recordsDto.setAccessUserType(accessCardDto.getType());
                this.accessCardPushRecordsFeign.deleteAccessCardPushRecords(recordsDto);
                return new ResultBean<>(ResultEnum.SUCCESS,true);
            }else{ //否则全部删除或者禁用
                this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_card,map);
                return new ResultBean<>(ResultEnum.SUCCESS,true);
            }
        }else{
            this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.del_open_door_card,map);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
    }

    @Override
    @PostMapping(value = "/device/removePushCardBatch")
    public ResultBean<Boolean> removePushCardBatch(@RequestBody List<AccessCardSimpleDto> accessCardSimpleDtoList) {
        ResultBean<Boolean> resultBean = this.handleIssueCardBatch(accessCardSimpleDtoList, Instruct.delete_open_door_card_batch);
        return resultBean;
    }

    private ResultBean<Boolean> handleIssueCardBatch(List<AccessCardSimpleDto> accessCardSimpleDtoList, Instruct instruct){
        Map<String, List<AccessCardSimpleDto>> deviceDataMap = new HashMap<>();
        for(AccessCardSimpleDto dto : accessCardSimpleDtoList){
            List<Device> deviceList = this.getListByEstateUser(dto.getResidentialId(), dto.getUnitId());
            for(Device device : deviceList){
                String serialNumber = device.getSerialNumber();
                if(deviceDataMap.containsKey(serialNumber)){
                    deviceDataMap.get(serialNumber).add(dto);
                }else{
                    List<AccessCardSimpleDto> cards = new ArrayList<>();
                    cards.add(dto);
                    deviceDataMap.put(serialNumber, cards);
                }
            }
        }
        for(String serialNumber : deviceDataMap.keySet()){
            Device device = this.deviceServiceInterface.selectBySerialNumber(serialNumber);
            List<AccessCardSimpleDto> cards = deviceDataMap.get(serialNumber);
            BatchCardsDto batchCardsDto = new BatchCardsDto();
            batchCardsDto.setTotal(cards.size());
            batchCardsDto.setCards(cards);
            this.msgPublishService.batchPushInstruct(batchCardsDto, device, instruct);
        }
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @GetMapping(value = "/device/evacuate/{xqId}/{time}")
    public ResultBean<Boolean> startOrClearEvacuate(
            @PathVariable(value = "xqId")Long xqId,
            @PathVariable(value = "time")Long time
    ) {
        Instruct instruct = 0 == time ? Instruct.cancel_evacuate : Instruct.evacuate;
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(xqId, null);
        Map<String,String> map = new HashMap<>();
        //  下发指令
        this.msgPublishService.batchPushInstruct(null,deviceList,instruct,map);
        //  修改小区的紧急疏散状态
        ResidentialDto residential = new ResidentialDto();
        residential.setId(xqId);
        residential.setOpenEvacuateTime(time);
        residential.setUpdateOrg(false);
        this.residentialFeign.updateResidential(residential);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Override
    @PostMapping(value = "/device/pushCallAccount")
    public void pushCallAccount(@RequestBody DispatchTask task) {
        Assert.notNull(task.getData(),"对讲账号不能为空");
        Assert.notNull(task.getXqId(),"小区Id不能为空");
        //  获取设备列表
        List<Device> deviceList = this.deviceServiceInterface.getListByEstateUser(task.getXqId(), task.getUnitId());
        Map<String,String> map = new HashMap<>();
        this.msgPublishService.batchPushInstruct(task.getData(),deviceList,Instruct.add_video_call_account,map);
    }

    @Override
    @PostMapping(value = "/device/deleteAdvert")
    public void deleteAdvert(@RequestBody DispatchTask task) {
        Assert.notNull(task.getSerialNumber(),"设备序列号不能为空");
        Device device = this.deviceServiceInterface.selectBySerialNumber(task.getSerialNumber());
        ObjectMapper objectMapper = new ObjectMapper();
        DeviceAdvert deviceAdvert = objectMapper.convertValue(task.getData(),DeviceAdvert.class);
        Map<String,String> logMap = new HashMap<>();
        //有效期开始时间
        SimpleDateFormat format = new SimpleDateFormat();
        if (null != deviceAdvert.getBeginTime()){
            logMap.put("beginTime",format.format(deviceAdvert.getBeginTime()));
        }else {
            logMap.put("beginTime",null);
        }
        //有效期结束时间
        if (null != deviceAdvert.getEndTime()){
            logMap.put("endTime",format.format(deviceAdvert.getEndTime()));
        }else {
            logMap.put("endTime",null);
        }
        this.msgPublishService.asyncPublish(task.getData(),device,Instruct.delete_advert,logMap);
    }

    /**
     * 功能描述: 指令下发
     * @param device 设备
     * @param instruct 指令
     * @return ResultBean<Boolean>
     *
     *
     */
    private ResultBean<Boolean> pushInstruct(Device device, Instruct instruct){
        //  获取设备信息
        Device dbDevice = this.deviceServiceInterface.selectById(device.getId());
        Assert.notNull(dbDevice,"设备不存在");
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(dbDevice.getXqName())){
            map.put("xqName",dbDevice.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(dbDevice.getDyName())){
            map.put("unitName",dbDevice.getDyName());
        }else {
            map.put("unitName",null);
        }
        if(dbDevice.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTORY_DAHAO)){ //大豪设备
            //  权限校验
            if (!dbDevice.getOrgPosition().startsWith(device.getOrgPosition())){
                return new ResultBean<>(ResultEnum.FORBIDDEN);
            }
            // 检查大豪设备是否在线
            Integer isOnline = this.checkDHDeviceOnLine(dbDevice.getSerialNumber());
            if(null != isOnline && isOnline.equals(OperationConstant.ONE)){
                //  下发指令
                InstructDH instructDH = new InstructDH();
                instructDH.setCode(instruct.getCode());
                instructDH.setExchangeName(instructDH.getDHExchange(instruct.getExchangeName()));
                instructDH.setDescribe(instruct.getDescribe());

                this.msgPublishService.topicMsgAsyncPublish(device.getUserId(),dbDevice,instructDH,map);
                return new ResultBean<>(ResultEnum.SUCCESS,true);
            }else{
                Assert.isTrue(0 == isOnline,"设备不在线");
            }
//            InstructDH instructDH = new InstructDH();
//            instructDH.setCode(instruct.getCode());
//            instructDH.setExchangeName(instructDH.getDHExchange(instruct.getExchangeName()));
//            instructDH.setDescribe(instruct.getDescribe());
//            this.msgPublishService.topicMsgAsyncPublish(device.getUserId(),dbDevice,instructDH);
//            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        //  校验设备是否在线
//        long lastHeartbeat = System.currentTimeMillis() - DeviceServiceInterface.HEART_RATE;
//        boolean isOnLine = null != dbDevice.getLastHeartbeat() && dbDevice.getLastHeartbeat() > lastHeartbeat;
//        Assert.isTrue(isOnLine,"设备不在线");
        //  权限校验
        if (!dbDevice.getOrgPosition().startsWith(device.getOrgPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //如果是app的一键开门device里面就会有小区、单元、房间、用户名
        if (!StringUtils.isEmpty(device.getXqName())){
            dbDevice.setXqName(device.getXqName());
        }
        if (!StringUtils.isEmpty(device.getDyName())){
            dbDevice.setDyName(device.getDyName());
        }
        //  下发指令
        this.msgPublishService.asyncPublish(device.getUserId(),dbDevice,instruct,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    private ResultBean<Boolean> checkOnline(Device device, Instruct instruct){
        //  获取设备信息
        Device dbDevice = this.deviceServiceInterface.selectById(device.getId());
        Assert.notNull(dbDevice,"设备不存在");
        Map<String,String> map = new HashMap<>();
        //小区
        if (!StringUtils.isEmpty(dbDevice.getXqName())){
            map.put("xqName",dbDevice.getXqName());
        }else {
            map.put("xqName",null);
        }
        //单元
        if (!StringUtils.isEmpty(dbDevice.getDyName())){
            map.put("unitName",dbDevice.getDyName());
        }else {
            map.put("unitName",null);
        }
        if(dbDevice.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTORY_DAHAO)){ //大豪设备
            //  权限校验
            if (!dbDevice.getOrgPosition().startsWith(device.getOrgPosition())){
                return new ResultBean<>(ResultEnum.FORBIDDEN);
            }
            // 检查大豪设备是否在线
            Integer isOnline = this.checkDHDeviceOnLine(dbDevice.getSerialNumber());
            if(null != isOnline && isOnline.equals(OperationConstant.ONE)){
                //  下发指令
                InstructDH instructDH = new InstructDH();
                instructDH.setCode(instruct.getCode());
                instructDH.setExchangeName(instructDH.getDHExchange(instruct.getExchangeName()));
                instructDH.setDescribe(instruct.getDescribe());
                this.msgPublishService.topicMsgAsyncPublish(device.getUserId(),dbDevice,instructDH,map);
                return new ResultBean<>(ResultEnum.SUCCESS,true);
            }else{
                Assert.isTrue(0 == isOnline,"设备不在线");
            }
//            InstructDH instructDH = new InstructDH();
//            instructDH.setCode(instruct.getCode());
//            instructDH.setExchangeName(instructDH.getDHExchange(instruct.getExchangeName()));
//            instructDH.setDescribe(instruct.getDescribe());
//            this.msgPublishService.topicMsgAsyncPublish(device.getUserId(),dbDevice,instructDH);
//            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        //  权限校验
        if (!dbDevice.getOrgPosition().startsWith(device.getOrgPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  下发指令
        this.msgPublishService.asyncPublish(device.getUserId(),dbDevice,instruct,map);
        return new ResultBean<>(ResultEnum.SUCCESS,true);
    }

    @Qualifier(value = "restTemplate")
    private final RestTemplate restTemplate;
    /**
     * 大豪设备在线状态监测
     * @param serialNumber 设备序列号
     * @return
     */
    private Integer checkDHDeviceOnLine(String serialNumber){
        //  调用大豪设备在线状态接口
        Map<String,Object> parameterMap = new HashMap<>(1);
        //  请求路径
        Conf config = confFeign.getEntityByToken("dh.api.host");
        String url = config.getConfValue() + "checkDeviceOnLineStatus?" + "DEVICE_ID="+serialNumber;
        Map resultMap = this.restTemplate.getForObject(url, Map.class);
        Assert.notNull(resultMap,"获取设备在线状态返回数据格式异常");
        String dataStr = JsonUtils.objectToJson(resultMap.get("data"));
        String dataStr2 = dataStr.replaceAll("\\\\", "");
        String dataStr3 = dataStr2.substring(1, dataStr2.length() - 1);
        JSONObject jsonObject = JSONObject.parseObject(dataStr3);
        Integer status = (Integer) jsonObject.get("status");
        //返回是在线的
        return status;
    }

    @Override
    @GetMapping(value = "/device/getListByEstateUser/{xqId}/{unitId}")
    public List<Device> getListByEstateUser(@PathVariable(value = "xqId")Long xqId, @PathVariable(value = "unitId")Long unitId) {
        return this.deviceServiceInterface.getListByEstateUser(xqId,unitId);
    }

    @Override
    @PostMapping(value = "/device/getListByCondition")
    public List<Device> getListByCondition(@RequestBody DeviceVO deviceVO) {
        return this.deviceServiceInterface.getListByCondition(deviceVO);
    }

    @Override
    @PostMapping(value = "/device/getListByOrgPosition")
    public List<Device> getListByOrgPosition(@RequestBody DeviceVO deviceVO) {
        return this.deviceServiceInterface.getListByOrgPosition(deviceVO);
    }

    @Override
    @PostMapping(value = "/device/getListByUnitIds")
    public List<Device> getListByUnitIds(@RequestBody List<Long> idList) {
        return this.deviceServiceInterface.selectListByUnitIds(idList);
    }

    @Override
    @GetMapping(value = "/device/getSpecialListByPathUse/{pathUse}")
    public List<Device> getSpecialListByPathUse(Long xqId, @PathVariable(value = "pathUse") Integer pathUse) {
        return this.deviceServiceInterface.getListByPathUse(xqId, null, pathUse);
    }

    @Override
    @GetMapping(value = "/device/getByOldId/{oldId}")
    public Device getByOldId(@PathVariable(value = "oldId") String oldId) {
        Wrapper<Device> wrapper = new EntityWrapper<>();
        wrapper.eq("old_id",oldId);
        return this.deviceServiceInterface.selectOne(wrapper);
    }

    @Override
    @GetMapping(value = "/device/getOfflineDeviceAccount")
    public long getOfflineDeviceAccount(Device device) {
        List<Device> list = this.deviceServiceInterface.getOfflineDeviceAccount(device);
        if (list != null){
            return list.size();
        }
        return 0;
    }

    @Override
    @GetMapping(value = "/device/getDeviceByPathUseAndType/{xqId}/{unitId}/{pathUse}/{type}")
    public List<Device> getDeviceByPathUseAndType(@PathVariable(value = "xqId") Long xqId, @PathVariable(value = "unitId") Long unitId, @PathVariable(value = "pathUse") Integer pathUse, @PathVariable(value = "type") Integer type) {
        return this.deviceServiceInterface.getDeviceByPathUseAndType(xqId, unitId, pathUse, type);
    }

    /**
     * 针对特殊情况处理（未录入设备信息时，设备开机，把设备和小区等信息关联上）
     * @param dto
     * @return
     */
    @Override
    @PostMapping(value = "/device/relateEntity")
    public ResultBean<Boolean> relateEntity(@RequestBody DeviceDto dto) {
        Device dbDevice = this.deviceServiceInterface.selectById(dto.getId());
        Assert.notNull(dbDevice,"设备不存在");

        dto.setCreateDate(dbDevice.getCreateDate());
        dto.setCreateAccountId(dbDevice.getCreateAccountId());
        dto.setStatus(dbDevice.getStatus());

        if (this.deviceServiceInterface.updateById(dto)){
            Map<String,String> map = new HashMap<>();
            //小区
            if (!StringUtils.isEmpty(dbDevice.getXqName())){
                map.put("xqName",dbDevice.getXqName());
            }else {
                map.put("xqName",null);
            }
            //单元
            if (!StringUtils.isEmpty(dbDevice.getDyName())){
                map.put("unitName",dbDevice.getDyName());
            }else {
                map.put("unitName",null);
            }
            //  通知设备信息被修改
            this.msgPublishService.asyncPublish(dbDevice,dbDevice,Instruct.update_device_info,map);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }else {
            log.warn("----------设备没有关联数据--------");
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    /**
     * 设备禁用类型
     * 1、禁用全部功能
     * 2、禁用刷脸开门功能
     * 3、禁用刷卡开门功能
     * 4、禁用密码开门功能
     * 5、禁用远程开门功能
     * 6、禁用设备按键功能
     * 7、禁用广告播放功能（但保留默认广告）
     */

    @Override
    @PostMapping(value = "/device/disable")
    public ResultBean<Boolean> disable(@RequestBody DeviceDto deviceDto) {
//        switch (deviceDto.getDisableType()){
//            case 1:
//                return pushInstruct(deviceDto, Instruct.disable_device);
//            case 2:
//                return pushInstruct(deviceDto, Instruct.disable_face_open_door);
//            case 3:
//                return pushInstruct(deviceDto, Instruct.disable_card_open_door);
//            case 4:
//                return pushInstruct(deviceDto, Instruct.disable_pwd_open_door);
//            case 5:
//                return pushInstruct(deviceDto, Instruct.disable_remote_open_door);
//            case 6:
//                return pushInstruct(deviceDto, Instruct.disable_keyboard);
//            case 7:
//                return pushInstruct(deviceDto, Instruct.disable_ad_play);
//            default:
//                return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY, false);
//        }
     return new ResultBean<>(ResultEnum.SUCCESS, true);
    }

    @Override
    @PostMapping(value = "/device/info/obtain")
    public ResultBean<Boolean> obtainInfo(@RequestBody Device device) {
        return pushInstruct(device,Instruct.remote_info_obtain);
    }

    @Override
    @PostMapping(value = "/device/page/getByCondition")
    public ResultBean<Page<Device>> getPageByCondition(@RequestBody PageBean<Device, DeviceDto> pageBean) {
        Page<Device> devicePage = this.deviceServiceInterface.pagingQuery(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS,devicePage);
    }

    @Override
    @PostMapping(value = "/device/grid/addEntity")
    public ResultBean<Boolean> addGridEntity(@RequestBody Map<String,Object> deviceList) {
        List<Device> devices=(List<Device>) deviceList.get("doorDeviceList");
        List<Device> insertList = new ArrayList<>();
        for(int i=0;i<devices.size();i++){
            Device device = JSON.parseObject(JSON.toJSONString(devices.get(i)),Device.class);
            Residential residential = this.residentialFeign.findResidentialById(device.getXqId());
            if(null != residential){
                device.setOrgPosition(residential.getOrgPosition());
                device.setRootOrgId(residential.getAgencyId());
                device.setRootOrgName(residential.getAgencyName());
            }
            insertList.add(device);

        }


        return new ResultBean<>(ResultEnum.SUCCESS,this.deviceServiceInterface.insertBatch(insertList));
    }

    @Override
    @PostMapping(value = "/device/updateEntity")
    public boolean updateEntity(@RequestBody Device device) {
        return this.deviceServiceInterface.updateById(device);
    }

    @Override
    @PostMapping(value = "/device/updateDeviceList")
    public boolean updateDeviceList(@RequestBody List<Device> deviceList){
        return this.deviceServiceInterface.updateBatchById(deviceList);
    }

    @Override
    @PostMapping(value = "/device/getListBySerialNumbers")
    public List<Device> getListBySerialNumbers(@RequestParam( value = "serialNumbers") String serialNumbers) {
        return this.deviceServiceInterface.getListBySerialNumbers(serialNumbers);
    }
}
