package com.fuyuanshen.web.service.device;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.app.domain.AppPersonnelInfo;
import com.fuyuanshen.app.domain.AppPersonnelInfoRecords;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
import com.fuyuanshen.app.domain.dto.DeviceInstructDto;
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.*;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.enums.LightModeEnum;
import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.Duration;
import java.util.*;

import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.buildArr;
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.generateFixedBitmapData;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;


@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceBJQBizService {

    private final DeviceMapper deviceMapper;
    private final AppPersonnelInfoMapper appPersonnelInfoMapper;
    private final AppPersonnelInfoRecordsMapper appPersonnelInfoRecordsMapper;
    private final DeviceTypeMapper deviceTypeMapper;
    private final MqttGateway mqttGateway;
    private final DeviceLogMapper deviceLogMapper;


    public int sendMessage(AppDeviceSendMsgBo bo) {
        List<Long> deviceIds = bo.getDeviceIds();
        if (deviceIds == null || deviceIds.isEmpty()) {
            throw new ServiceException("请选择设备");
        }
        for (Long deviceId : deviceIds) {
            Device device = deviceMapper.selectById(deviceId);
            if (device == null) {
                throw new ServiceException("设备不存在" + deviceId);
            }
            if (getDeviceStatus(device.getDeviceImei())) {
                throw new ServiceException(device.getDeviceName() + ",设备已断开连接");
            }
            try {
                ClassPathResource resource = new ClassPathResource("image/background.png");
                InputStream inputStream = resource.getInputStream();

                byte[] largeData = ImageWithTextGenerate.generate160x80ImageWithText2(bo.getSendMsg(), inputStream, 25600);
                int[] ints = convertHexToDecimal(largeData);
                RedisUtils.setCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + ":app_send_message_data", Arrays.toString(ints), Duration.ofSeconds(5 * 60L));

                String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + ":app_send_message_data");

                byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data);
                byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512);
                log.info("发送信息第0块数据大小: {} 字节", specificChunk.length);

                ArrayList<Integer> intData = new ArrayList<>();
                intData.add(6);
                intData.add(1);
                ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData);
                intData.add(0);
                intData.add(0);
                intData.add(0);
                intData.add(0);
                Map<String, Object> map = new HashMap<>();
                map.put("instruct", intData);
                mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
                log.info("发送信息点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));

                UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", deviceId)
                        .set("send_msg", bo.getSendMsg());
                deviceMapper.update(updateWrapper);

                recordDeviceLog(deviceId, device.getDeviceName(), "发送信息", bo.getSendMsg(), AppLoginHelper.getUserId());
            } catch (Exception e) {
                log.info("发送信息设备发送信息失败:{}", deviceId);
                throw new ServiceException("发送指令失败");
            }
            // 发送消息
            messageSending(device.getDeviceImei());
        }


        return 1;
    }

    /**
     * 记录设备操作日志
     *
     * @param deviceId 设备ID
     * @param content  日志内容
     * @param operator 操作人
     */
    private void recordDeviceLog(Long deviceId, String deviceName, String deviceAction, String content, Long operator) {
        try {
            // 创建设备日志实体
            com.fuyuanshen.equipment.domain.DeviceLog deviceLog = new com.fuyuanshen.equipment.domain.DeviceLog();
            deviceLog.setDeviceId(deviceId);
            deviceLog.setDeviceAction(deviceAction);
            deviceLog.setContent(content);
            deviceLog.setCreateBy(operator);
            deviceLog.setDeviceName(deviceName);
            deviceLog.setCreateTime(new Date());

            // 插入日志记录
            deviceLogMapper.insert(deviceLog);
        } catch (Exception e) {
            log.error("记录设备操作日志失败: {}", e.getMessage(), e);
        }
    }


    public AppDeviceDetailVo getInfo(Long id) {
        Device device = deviceMapper.selectById(id);
        if (device == null) {
            throw new RuntimeException("请先将设备入库！！！");
        }

        AppDeviceDetailVo vo = new AppDeviceDetailVo();
        vo.setDeviceId(device.getId());
        vo.setDeviceName(device.getDeviceName());
        vo.setDevicePic(device.getDevicePic());
        vo.setDeviceImei(device.getDeviceImei());
        vo.setDeviceMac(device.getDeviceMac());
        vo.setDeviceStatus(device.getDeviceStatus());
        DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
        if (deviceType != null) {
            vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
            vo.setTypeName(deviceType.getTypeName());
        }
        vo.setBluetoothName(device.getBluetoothName());

        vo.setSendMsg(device.getSendMsg());

        QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
                .eq("device_id", device.getId());
        AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw);
        if (appPersonnelInfo != null) {
            AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class);
            vo.setPersonnelInfo(personnelInfoVo);
        }
        // 设备在线状态
        String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
        // 设备在线状态
        if ("1".equals(onlineStatus)) {
            vo.setOnlineStatus(1);
        } else if ("2".equals(onlineStatus)) {
            vo.setOnlineStatus(2);
        } else {
            vo.setOnlineStatus(0);
        }
        String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX);
        // 获取电量
        if (StringUtils.isNotBlank(deviceStatus)) {
            JSONObject jsonObject = JSONObject.parseObject(deviceStatus);
            vo.setMainLightMode(jsonObject.getString("mainLightMode"));
            vo.setLaserLightMode(jsonObject.getString("laserLightMode"));
            vo.setBatteryPercentage(jsonObject.getString("batteryPercentage"));
            vo.setChargeState(jsonObject.getString("chargeState"));
            vo.setBatteryRemainingTime(jsonObject.getString("batteryRemainingTime"));
        } else {
            vo.setBatteryPercentage("0");
        }

        String lightModeStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LIGHT_MODE_KEY_PREFIX);
        // 获取电量
        if (StringUtils.isNotBlank(deviceStatus)) {
            vo.setMainLightMode(lightModeStatus);
        }

        String lightBrightnessStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX);
        if (StringUtils.isNotBlank(lightBrightnessStatus)) {
            vo.setLightBrightness(lightBrightnessStatus);
        }

        String laserLightMode = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LASER_MODE_KEY_PREFIX);
        if (StringUtils.isNotBlank(laserLightMode)) {
            vo.setLaserLightMode(laserLightMode);
        }

        // 获取经度纬度
        String locationKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;
        String locationInfo = RedisUtils.getCacheObject(locationKey);
        if (StringUtils.isNotBlank(locationInfo)) {
            JSONObject jsonObject = JSONObject.parseObject(locationInfo);
            vo.setLongitude(jsonObject.get("longitude").toString());
            vo.setLatitude(jsonObject.get("latitude").toString());
            vo.setAddress((String) jsonObject.get("address"));
        }

        String alarmStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX);
        if (StringUtils.isNotBlank(alarmStatus)) {
            vo.setAlarmStatus(alarmStatus);
        }

        String lightBrightness = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX);
        if (StringUtils.isNotBlank(lightBrightness)) {
            vo.setLightBrightness(lightBrightness);
        }

        return vo;
    }


    public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
        Long deviceId = bo.getDeviceId();
        Device deviceObj = deviceMapper.selectById(deviceId);
        if (deviceObj == null) {
            throw new RuntimeException("请先将设备入库！！！");
        }
        if (getDeviceStatus(deviceObj.getDeviceImei())) {
            throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
        }
        QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
                .eq("device_id", deviceId);
        List<AppPersonnelInfoVo> appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw);
//        unitName,position,name,id
        byte[] unitName = generateFixedBitmapData(bo.getUnitName(), 120);
        byte[] position = generateFixedBitmapData(bo.getPosition(), 120);
        byte[] name = generateFixedBitmapData(bo.getName(), 120);
        byte[] id = generateFixedBitmapData(bo.getCode(), 120);
        ArrayList<Integer> intData = new ArrayList<>();
        intData.add(2);
        buildArr(convertHexToDecimal(unitName), intData);
        buildArr(convertHexToDecimal(name), intData);
        buildArr(convertHexToDecimal(position), intData);
        buildArr(convertHexToDecimal(id), intData);
        intData.add(0);
        intData.add(0);
        intData.add(0);
        intData.add(0);
        Map<String, Object> map = new HashMap<>();
        map.put("instruct", intData);
        mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), 1, JSON.toJSONString(map));
        log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), bo);
        String logContent = "单位：" + bo.getUnitName() + ",职位：" + bo.getPosition() + ",姓名：" + bo.getName() + ",ID：" + bo.getCode();
        recordDeviceLog(deviceId, deviceObj.getDeviceName(), "人员信息登记", logContent, AppLoginHelper.getUserId());
        if (ObjectUtils.length(appPersonnelInfoVos) == 0) {
            AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
            appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);

            AppPersonnelInfoRecords appPersonnelInfoRecords = new AppPersonnelInfoRecords();
            BeanUtil.copyProperties(appPersonnelInfo, appPersonnelInfoRecords);
            appPersonnelInfoRecords.setId(null);
            appPersonnelInfoRecords.setPersonnelId(appPersonnelInfo.getId());

            appPersonnelInfoRecordsMapper.insert(appPersonnelInfoRecords);
        } else {
            UpdateWrapper<AppPersonnelInfo> uw = new UpdateWrapper<>();
            uw.eq("device_id", deviceId)
                    .set("name", bo.getName())
                    .set("position", bo.getPosition())
                    .set("unit_name", bo.getUnitName())
                    .set("code", bo.getCode());
            appPersonnelInfoMapper.update(null, uw);

            AppPersonnelInfoVo personnelInfoVo = appPersonnelInfoVos.get(0);
            AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
            AppPersonnelInfoRecords appPersonnelInfoRecords = new AppPersonnelInfoRecords();
            BeanUtil.copyProperties(appPersonnelInfo, appPersonnelInfoRecords);
            appPersonnelInfoRecords.setId(null);
            appPersonnelInfoRecords.setPersonnelId(personnelInfoVo.getId());
            appPersonnelInfoRecordsMapper.insert(appPersonnelInfoRecords);
        }
        return true;
    }

    public void uploadDeviceLogo2(AppDeviceLogoUploadDto bo) {
        try {
            Device device = deviceMapper.selectById(bo.getDeviceId());
            if (device == null) {
                throw new ServiceException("设备不存在");
            }
            MultipartFile file = bo.getFile();

            byte[] largeData = ImageToCArrayConverter.convertImageToCArray(file.getInputStream(), 160, 80, 25600);

            log.info("长度：" + largeData.length);
            // 在获取 largeData 后，将其与前缀合并
            byte[] prefix = new byte[]{0x50, 0x49, 0x43, 0x54, 0x55, 0x52, 0x45}; // "PICTURE"
            byte[] combinedData = new byte[prefix.length + largeData.length];
            System.arraycopy(prefix, 0, combinedData, 0, prefix.length);
            System.arraycopy(largeData, 0, combinedData, prefix.length, largeData.length);

            // 将 combinedData 转换为十六进制表示
            String[] hexArray = new String[combinedData.length];
            for (int i = 0; i < combinedData.length; i++) {
                hexArray[i] = String.format("0x%02X", combinedData[i]);
            }
//            Map<String, Object> map = new HashMap<>();
//            map.put("instruct", combinedData);
            String[] specificChunk = ImageToCArrayConverter.getChunk2(hexArray, 0, bo.getChunkSize());
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, Arrays.toString(specificChunk));
            log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), Arrays.toString(specificChunk));

            recordDeviceLog(device.getId(), device.getDeviceName(), "上传开机画面", "上传开机画面", AppLoginHelper.getUserId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送指令失败");
        }
    }

    public void uploadDeviceLogo(AppDeviceLogoUploadDto bo) {
        try {
            Device device = deviceMapper.selectById(bo.getDeviceId());
            if (device == null) {
                throw new ServiceException("设备不存在");
            }
            if (getDeviceStatus(device.getDeviceImei())) {
//                throw new ServiceException(device.getDeviceName()+",设备已断开连接");
                log.info(device.getDeviceName() + ",设备已断开连接");
                recordDeviceLog(device.getId(), device.getDeviceName(), "上传开机画面", device.getDeviceName() + ",设备已断开连接", AppLoginHelper.getUserId());
                return;
            }
            MultipartFile file = bo.getFile();

            byte[] largeData = ImageToCArrayConverter.convertImageToCArray(file.getInputStream(), 160, 80, 25600);
            log.info("长度：" + largeData.length);

            log.info("原始数据大小: {} 字节", largeData.length);

            int[] ints = convertHexToDecimal(largeData);
            RedisUtils.setCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX, Arrays.toString(ints), Duration.ofSeconds(5 * 60L));

            String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX);

            byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data);
            byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512);
            log.info("第0块数据大小: {} 字节", specificChunk.length);
//            log.info("第0块数据: {}", Arrays.toString(specificChunk));

            ArrayList<Integer> intData = new ArrayList<>();
            intData.add(3);
            intData.add(1);
            ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData);
            intData.add(0);
            intData.add(0);
            intData.add(0);
            intData.add(0);
            Map<String, Object> map = new HashMap<>();
            map.put("instruct", intData);
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
            log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));

            recordDeviceLog(device.getId(), device.getDeviceName(), "上传开机画面", "上传开机画面", AppLoginHelper.getUserId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送指令失败");
        }
    }

    /**
     * 灯光模式
     * 0（关灯），1（强光模式），2（弱光模式）,  3（爆闪模式）,   4（泛光模式）
     */

    public void lightModeSettings(DeviceInstructDto params) {
        try {
            Long deviceId = params.getDeviceId();
            Device device = deviceMapper.selectById(deviceId);
            if (device == null) {
                throw new ServiceException("设备不存在");
            }
            if (getDeviceStatus(device.getDeviceImei())) {
                throw new ServiceException(device.getDeviceName() + ",设备已断开连接");
            }
            Integer instructValue = Integer.parseInt(params.getInstructValue());
            ArrayList<Integer> intData = new ArrayList<>();
            intData.add(1);
            intData.add(instructValue);
            intData.add(0);
            intData.add(0);
            intData.add(0);
            Map<String, Object> map = new HashMap<>();
            map.put("instruct", intData);
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
            log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));
            LightModeEnum modeEnum = LightModeEnum.getByCode(instructValue);
            recordDeviceLog(device.getId(), device.getDeviceName(), "灯光模式", modeEnum != null ? modeEnum.getName() : null, AppLoginHelper.getUserId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送指令失败");
        }
    }

    // 灯光亮度设置
    public void lightBrightnessSettings(DeviceInstructDto params) {
        try {
            Long deviceId = params.getDeviceId();
            Device device = deviceMapper.selectById(deviceId);
            if (device == null) {
                throw new ServiceException("设备不存在");
            }
            if (getDeviceStatus(device.getDeviceImei())) {
                throw new ServiceException(device.getDeviceName() + ",设备已断开连接");
            }
            String instructValue = params.getInstructValue();
            ArrayList<Integer> intData = new ArrayList<>();
            intData.add(5);
            String[] values = instructValue.split("\\.");
            String value1 = values[0];
            String value2 = values[1];
            if (StringUtils.isNoneBlank(value1)) {
                intData.add(Integer.parseInt(value1));
            }
            if (StringUtils.isNoneBlank(value2)) {
                intData.add(Integer.parseInt(value2));
            }
            intData.add(0);
            intData.add(0);
            intData.add(0);
            Map<String, Object> map = new HashMap<>();
            map.put("instruct", intData);
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
            log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送指令失败");
        }
    }

    // 激光模式设置
    public void laserModeSettings(DeviceInstructDto params) {
        try {
            Long deviceId = params.getDeviceId();
            Device device = deviceMapper.selectById(deviceId);
            if (device == null) {
                throw new ServiceException("设备不存在");
            }
            if (getDeviceStatus(device.getDeviceImei())) {
                throw new ServiceException(device.getDeviceName() + ",设备已断开连接");
            }
            Integer instructValue = Integer.parseInt(params.getInstructValue());
            ArrayList<Integer> intData = new ArrayList<>();
            intData.add(4);
            intData.add(instructValue);
            intData.add(0);
            intData.add(0);
            intData.add(0);
            Map<String, Object> map = new HashMap<>();
            map.put("instruct", intData);
            mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
            log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));
            // 1代表开启激光灯，此时主灯关闭，主灯控件为关机状态，为0代表关闭激光灯
            if ("1".equals(params.getInstructValue())) {
                recordDeviceLog(device.getId(), device.getDeviceName(), "激光模式设置", "开启激光灯", AppLoginHelper.getUserId());
            } else {
                recordDeviceLog(device.getId(), device.getDeviceName(), "激光模式设置", "关闭激光灯", AppLoginHelper.getUserId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送指令失败");
        }
    }

    public String mapReverseGeocoding(DeviceInstructDto params) {
        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("device_imei", params.getDeviceImei());
        List<Device> devices = deviceMapper.selectList(queryWrapper);
        if (ObjectUtils.length(devices) == 0) {
            throw new ServiceException("设备不存在");
        }
        return RedisUtils.getCacheObject("device:location:" + devices.get(0).getDeviceImei());
    }

    public int sendAlarmMessage(AppDeviceSendMsgBo bo) {
        try {
            List<Long> deviceIds = bo.getDeviceIds();
            if (deviceIds == null || deviceIds.isEmpty()) {
                throw new ServiceException("请选择设备");
            }

            for (Long deviceId : deviceIds) {
                Device device = deviceMapper.selectById(deviceId);
                if (device == null) {
                    throw new ServiceException("设备不存在" + deviceId);
                }
                if (getDeviceStatus(device.getDeviceImei())) {
                    throw new ServiceException(device.getDeviceName() + ",设备已断开连接");
                }
                try {

                    ArrayList<Integer> intData = new ArrayList<>();
                    intData.add(7);
                    intData.add(Integer.parseInt(bo.getInstructValue()));
                    intData.add(0);
                    intData.add(0);
                    intData.add(0);
                    intData.add(0);
                    Map<String, Object> map = new HashMap<>();
                    map.put("instruct", intData);
                    mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), 1, JSON.toJSONString(map));
                    log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + device.getDeviceImei(), JSON.toJSONString(map));

                    UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("id", deviceId)
                            .set("send_msg", bo.getSendMsg());
                    deviceMapper.update(updateWrapper);
                    if ("0".equals(bo.getInstructValue())) {
                        recordDeviceLog(device.getId(), device.getDeviceName(), "解除告警信息", "关闭设备", AppLoginHelper.getUserId());
                    } else {
                        recordDeviceLog(device.getId(), device.getDeviceName(), "发送告警信息", bo.getSendMsg(), AppLoginHelper.getUserId());
                    }
                } catch (Exception e) {
                    log.info("设备发送告警信息信息失败:{}", deviceId);
                    throw new ServiceException("设备发送告警信息信息失败");
                }
                messageSending(device.getDeviceImei());
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("发送告警信息指令失败");
        }
        return 1;
    }

    private void messageSending(String deviceImei) {
        String sendMessageIng = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + ":messageSending";
        RedisUtils.setCacheObject(sendMessageIng, "1", Duration.ofDays(1));
    }

    private boolean getDeviceStatus(String deviceImei) {
        String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
        return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null;
    }

    public void batchUploadLogo(AppDeviceLogoUploadDto bo) {

        List<Long> deviceIds = bo.getDeviceIds();
        MultipartFile file = bo.getFile();
        if (deviceIds == null || deviceIds.isEmpty()) {
            throw new ServiceException("请选择设备");
        }
        for (Long deviceId : deviceIds) {
            AppDeviceLogoUploadDto dto = new AppDeviceLogoUploadDto();
            dto.setDeviceId(deviceId);
            dto.setFile(file);
            uploadDeviceLogo(dto);
        }
    }

}
