//package com.ruoyi.web.controller.iot.receive;
//
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson2.JSON;
//import com.alibaba.fastjson2.JSONArray;
//import com.alibaba.fastjson2.JSONObject;
//import com.ruoyi.common.constant.IotConstants;
//import com.ruoyi.common.constant.ServiceConstants;
//import com.ruoyi.common.exception.ServiceException;
//import com.ruoyi.common.utils.CommonUtil;
//import com.ruoyi.common.utils.DateUtils;
////import com.ruoyi.common.utils.map.GeoUtils;
//import com.ruoyi.common.utils.map.GpsCoordinateUtils;
//import com.ruoyi.system.domain.device.EDevice;
//import com.ruoyi.system.model.domain.EModel;
//import com.ruoyi.system.domain.onlineLog.EOnlineLog;
//import com.ruoyi.system.model.service.IEModelService;
//import com.ruoyi.system.service.IEDeviceService;
//import com.ruoyi.ss.onlineLog.service.IEOnlineLogService;
//import com.ruoyi.web.controller.iot.domain.BodyObj;
//import com.ruoyi.web.controller.iot.domain.LogEntry;
//import com.ruoyi.web.controller.iot.util.Util;
//import lombok.SneakyThrows;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.transaction.annotation.Transactional;
//import org.springframework.web.bind.annotation.*;
//
//import javax.annotation.Resource;
//import java.io.UnsupportedEncodingException;
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//import java.security.InvalidKeyException;
//import java.security.NoSuchAlgorithmException;
//import java.util.concurrent.ScheduledExecutorService;
//import java.util.concurrent.TimeUnit;
//
///**
// * 接收硬件参数
// *
// * @author ruoyi
// */
//@RestController
//@RequestMapping("/common")
//public class ReceiveController {
//
//    private static final Logger log = LoggerFactory.getLogger(ReceiveController.class);
//
//    @Value(value = "${iot.token}")
//    private String token;
//
//    @Resource
//    private IEDeviceService eDeviceService;
//
//    @Autowired
//    private IEModelService etModelService;
//
//    @Autowired
//    private ScheduledExecutorService scheduledExecutorService;
//
//    @Autowired
//    private IEOnlineLogService eOnlineLogService;
//
//    private final Object lock = new Object();
//
//
//    /**
//     * 功能描述：第三方平台数据接收。<p>
//     *           <ul>注:
//     *               <li>1.OneNet平台为了保证数据不丢失，有重发机制，如果重复数据对业务有影响，数据接收端需要对重复数据进行排除重复处理。</li>
//     *               <li>2.OneNet每一次post数据请求后，等待客户端的响应都设有时限，在规定时限内没有收到响应会认为发送失败。
//     *                    接收程序接收到数据时，尽量先缓存起来，再做业务逻辑处理。</li>
//     *           </ul>
//     * @param body 数据消息
//     * @return 任意字符串。OneNet平台接收到http 200的响应，才会认为数据推送成功，否则会重发。
//     */
//    @RequestMapping(value = "/receive",method = RequestMethod.POST)
//    @ResponseBody
//    @SneakyThrows
//    @Transactional
//    public String receive(@RequestBody String body){
//
//        log.info("receive方法接收到参数:  body String --- " +body);
//        /************************************************
//         *  解析数据推送请求，非加密模式。
//         *  如果是明文模式使用以下代码 hangdleBody(body, false);  ChatGPT is under heavy load
//         **************************************************/
//        /*************明文模式  start****************/
//        BodyObj obj = Util.resolveBody(body, false);
//        log.info("receive方法解析对象:  body Object --- " + JSON.toJSONString(obj));
//        // 起一个异步线程处理数据
//        scheduledExecutorService.schedule(() -> {
////            new Thread(() -> {
////                synchronized (lock) {
////                    try {
//////                        handleBody(obj);
////                    } catch (UnsupportedEncodingException e) {
////                        e.printStackTrace();
////                    } catch (NoSuchAlgorithmException e) {
////                        e.printStackTrace();
////                    } catch (InvalidKeyException e) {
////                        e.printStackTrace();
////                    }
////                }
////            }).start();
//        }, 0, TimeUnit.SECONDS);
//        /*************明文模式  end****************/
//        return "ok";
//    }
//
////    private void handleBody(BodyObj obj) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
////        if (obj != null){
////            boolean dataRight = Util.checkSignature(obj, token);
////            if (dataRight){
////                log.info("receive方法验证签名正确: content" + JSON.toJSONString(obj));
////                String msg = (String) obj.getMsg();
////                log.info("receive方法-获取到消息体: msg---" +msg);
////                JSONObject jsonObject = JSONObject.parseObject(msg, JSONObject.class);
////                String devName = (String)jsonObject.get("dev_name");
////                /*异步更新在线状态*/
////                EDevice eDevice = eDeviceService.selectEDeviceByMac(devName);
////                String ver = null;
////                if(IotConstants.ONENET_VER.equals(jsonObject.get("ds_id")) && ObjectUtil.isNotNull(jsonObject.get("value"))){
////                    ver = (String)jsonObject.get("value");
////                    log.info("获取到版本号------------------------------------："+ver);
////                }
////                asynchronousUpdateOnlineStatus(eDevice,ver);
////                if(IotConstants.ONENET_LOCATION.equals(jsonObject.get("ds_id")) && ObjectUtil.isNotNull(jsonObject.get("value"))){
////                    LogEntry logEntry = JSONObject.parseObject(msg, LogEntry.class);
////                    log.info("logEntry转换后的对象: logEntry---【{}】" , JSON.toJSONString(logEntry));
////                    LogEntry.LocationValue value = logEntry.getValue();
////                    /**如果是定位日志则，获取到车辆mac，找到对应车辆
////                     * 1.更新车辆定位、计算续航里程
////                     * 2.判断是否在禁行区内，如果在，根据配置‘禁行区内断电配置’进行断电，
////                     * 3.超出运营区外断电
////                     * 4.行程线路添加，更新订单中的trip_route字段
////                     * 5.低于电量（%）不得骑行，声音播报
////                     * 6.低电量 生成换电工单
////                     * 7.运营边界判断
////                     * */
////                    /** 1.更新车辆定位、电压；计算续航里程 */
////                    EDevice device = eDeviceService.selectEDeviceByMac(logEntry.getDevName());
////                    if(ObjectUtil.isNull(device)){
////                        throw new ServiceException("未找到车辆信息");
////                    }
//////                    EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(device.getAreaId());
////                    if(ObjectUtil.isNotNull(device)){
////                        BigDecimal lon = new BigDecimal(value.getLon());
////                        BigDecimal lat = new BigDecimal(value.getLat());
////                        log.info("WGS84经纬度（未计算）：" + lon + "---" + lat);
////                        // 除以100
////                        lon = lon.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP);
////                        lat = lat.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP);
////                        log.info("WGS84经纬度（除以100后）：" + lon + "---" + lat);
////                        // 取出lon中后面的小数点
////                        String[] lonStr = getDecimalPart(lon);
////                        String[] latStr = getDecimalPart(lat);
////                        log.info("WGS84经纬度（截取小数点）：" + lonStr[0] + "---" + lonStr[1] + "---"+ latStr[0]+"---"+ latStr[1]);
////                        // 再将结果乘以5/3
////                        String lon2 = "0."+ lonStr[1];
////                        String lat2 = "0."+ latStr[1];
////                        BigDecimal lons = new BigDecimal(lon2).multiply(new BigDecimal(5).divide(new BigDecimal(3), 8, RoundingMode.HALF_UP));
////                        BigDecimal lats = new BigDecimal(lat2).multiply(new BigDecimal(5).divide(new BigDecimal(3), 8, RoundingMode.HALF_UP));
////                        BigDecimal lo = new BigDecimal(lonStr[0]).add(lons);
////                        BigDecimal la = new BigDecimal(latStr[0]).add(lats);
////                        log.info("WGS84经纬度（计算后）：" + lo + "---" + la);
////                        lo = lo.setScale(8, RoundingMode.HALF_UP);
////                        la = la.setScale(8, RoundingMode.HALF_UP);
////                        log.info("WGS84经纬度（保留8为小数）：" + lo + "---" + la);
////                        double[] doubles = GpsCoordinateUtils.calWGS84toGCJ02(la.doubleValue(), lo.doubleValue());
////                        lat = new BigDecimal(doubles[0]).setScale(8, RoundingMode.HALF_UP);
////                        lon = new BigDecimal(doubles[1]).setScale(8, RoundingMode.HALF_UP);
////                        log.info("转换后的GCJ02经纬度：" + lon + "---" + lat);
////                        if(BigDecimal.ZERO.compareTo(lon) != 0 && BigDecimal.ZERO.compareTo(lat) != 0){
////                            device.setLatitude(lat.toString());
////                            device.setLongitude(lon.toString());
////                            Integer bat = value.getBat();
////                            BigDecimal divide = new BigDecimal(bat).divide(new BigDecimal(10));
////                            log.info("保存电压：" + divide);
////                            device.setVoltage(divide.toString());//电压
////                            // 根据电压计算续航里程
//////                            EModel model = etModelService.selectEModelByModelId(device.getModelId());
////                            Integer remainingMileage = 0;
////                            if(StrUtil.isNotBlank(device.getVoltage())){
////                                remainingMileage = CommonUtil.getRemainingMileage(device.getVoltage(), model.getFullVoltage(), model.getLowVoltage(), model.getFullEndurance());
////                            }
////                            Integer electricQuantity = CommonUtil.getElectricQuantity(device.getVoltage(), model.getFullVoltage(), model.getLowVoltage());//电量百分百
////                            device.setRemainingMileage(remainingMileage);
////                            device.setRemainingPower(electricQuantity.toString());
////                            device.setLastTime(DateUtils.getNowDate());
////                            device.setLastLocationTime(DateUtils.getNowDate());
////                            device.setGps("1");
////                            // 信号强度
////                            device.setSignalStrength(value.getCsq());
////                            device.setSatellites(value.getS());
////                            device.setQuality(value.getQ());
////                            int i = eDeviceService.updateLocation(device);
////                            if(i>0){
////                                log.info("更新定位成功==========================>" +logEntry.getDevName());
////                                /** 4.行程线路添加，更新的trip_route字段 */
//////                                Integer status = value.getStatus();
//////                                if(status == 1){//上电运行
//////                                    log.info("上电运行：" +logEntry.getDevName());
//////                                    if(BigDecimal.ZERO.compareTo(lon) != 0 && BigDecimal.ZERO.compareTo(lat) != 0){
//////                                        //获取当前正在骑行中的订单
//////                                        EtOrder etOrder = etOrderService.getCurrentOrder(device.getSn());
//////                                        if(ObjectUtil.isNotNull(etOrder)){
//////                                            JSONArray jsonArray;
//////                                            if(StrUtil.isNotBlank(etOrder.getTripRouteStr())){
//////                                                jsonArray = JSON.parseArray(etOrder.getTripRouteStr());
//////                                            }else{
//////                                                jsonArray = new JSONArray();
//////                                            }
//////                                            JSONArray newPoint = new JSONArray();
//////                                            newPoint.add(lon);
//////                                            newPoint.add(lat);
//////
//////                                            // 优化轨迹，如果获取到的定位与最后一个定位相同，则不添加
//////                                            optimizeRoute(jsonArray, newPoint,lon,lat,etOrder);
//////                                        }else{
//////                                            //当前无订单，并且不是管理员开锁的情况下，直接关锁
//////                                            if(!isAdminUnlocking.equals("1")){
//////                                                log.info("当前无订单，并且不是管理员开锁的情况下，直接关锁--------" +logEntry.getDevName());
//////                                                eDeviceService.sendCommand(asDevice.getMac(), Token.getToken(), IotConstants.COMMAND_CLOSE+IotConstants.COMMAND_FREQUENCY_3600,"无订单关锁",null,null);
//////                                            }
//////                                        }
//////                                    }
//////                                }
////                            }else{
////                                log.info("更新定位失败：" +logEntry.getDevName());
////                            }
////                        }else{
////                            log.info("----------------未获取到定位，保存电压等数值----------------" +logEntry.getDevName());
////                            Integer bat = value.getBat();
////                            BigDecimal divide = new BigDecimal(bat).divide(new BigDecimal(10));
////                            log.info("保存电压：" + divide);
////                            device.setVoltage(divide.toString());//电压
////                            // 根据电压计算续航里程
////                            EModel model = etModelService.selectEModelByModelId(device.getModelId());
////                            Integer remainingMileage = 0;
////                            if(StrUtil.isNotBlank(device.getVoltage())){
////                                remainingMileage = CommonUtil.getRemainingMileage(device.getVoltage(), model.getFullVoltage(), model.getLowVoltage(), model.getFullEndurance());
////                            }
////                            Integer electricQuantity = CommonUtil.getElectricQuantity(device.getVoltage(), model.getFullVoltage(), model.getLowVoltage());//电量百分百
////                            device.setRemainingMileage(remainingMileage);
////                            device.setRemainingPower(electricQuantity.toString());
////                            device.setLastTime(DateUtils.getNowDate());
////                            device.setGps("0");
////                            device.setSignalStrength(value.getCsq());
////                            device.setSatellites(0);
////                            device.setQuality(value.getQ());
////                            int i = eDeviceService.updateLocation(device);
////                            if(i>0){
////                                log.info("未获取到定位===============保存电压等数值成功===========>" +logEntry.getDevName());
////                            }
////                        }
////                    }else{
////                        log.info("未找到车辆对象：" +logEntry.getDevName());
////                    }
////
////                }
////            }else {
////                log.info("receive方法验证签名错误: signature error");
////            }
////
////        }else {
////            log.info("receive方法参数为空: body empty error");
////        }
////    }
//
//    /**
//     * 异步更新在线状态
//     */
//    private void asynchronousUpdateOnlineStatus(EDevice device,String verStr) {
//        if(StrUtil.isNotBlank(verStr)){
//            device.setVersion(verStr);
//        }
//        //开异步线程：1.更新在线状态  2.记录在线、离线日志
//        scheduledExecutorService.schedule(() -> {
//            if(device.getOnlineStatus().equals(ServiceConstants.VEHICLE_STATUS_OFFLINE)){
//                log.info("【接收onenet推送】异步更新在线状态"+JSON.toJSONString(device));
//                device.setOnlineStatus(ServiceConstants.VEHICLE_STATUS_ONLINE);
//                int i = eDeviceService.updateEDevice(device);
//                if(i>0){
//                    log.info("【接收onenet推送】异步保存在线状态成功");
//                }
//                EOnlineLog etOnlineLog = new EOnlineLog();
//                etOnlineLog.setMac(device.getMac());
//                etOnlineLog.setSn(device.getSn());
//                etOnlineLog.setOnlineStatus(ServiceConstants.VEHICLE_STATUS_ONLINE);
//                etOnlineLog.setLongitude(device.getLongitude());
//                etOnlineLog.setLatitude(device.getLatitude());
//                etOnlineLog.setCreateTime(DateUtils.getNowDate());
//                int i1 = eOnlineLogService.insertEtOnlineLog(etOnlineLog);
//                if(i1>0){
//                    log.info("【接收onenet推送】异步保存在线日志成功");
//                }
//            }
//        }, 0, TimeUnit.SECONDS);
//    }
//
//    private boolean isLastPointSame(JSONArray jsonArray, BigDecimal lon, BigDecimal lat) {
//        if (jsonArray.size() > 0) {
//            JSONArray lastPoint = (JSONArray) jsonArray.get(jsonArray.size() - 1);
//            return lastPoint.get(0).equals(lon) && lastPoint.get(1).equals(lat);
//        }
//        return false;
//    }
//
//    public void optimizeRoute(JSONArray jsonArray, JSONArray newPoint, BigDecimal lon, BigDecimal lat) {
//        if (isLastPointSame(jsonArray, lon, lat)) {
//            log.info("获取到的定位与最后一个定位相同，不添加线路");
//        } else {
//            jsonArray.add(newPoint);
//            String tripRouteStr = jsonArray.toJSONString();
//            log.info("更新行程jsonArray：" + tripRouteStr);
////            etOrder.setTripRouteStr(tripRouteStr);
//
////            Geometry geometry = GeoUtils.toGeometryByLinearRing(tripRouteStr);
////            String wkt = GeoUtils.wkt(geometry);
////            etOrder.setTripRoute(wkt);
//            // todo 放在还车的接口计算
////            double[][] doubles = GeoUtils.parseJsonTrack(tripRouteStr);
////            double v = GeoUtils.calculateTotalDistance(doubles);
////            etOrder.setDistance((int)Math.round(v));
//
////            int updateEtOrderResult = etOrderService.updateEtOrder(etOrder);
////            if (updateEtOrderResult > 0) {
////                log.info("更新行程线路成功==========================>" + etOrder.getSn());
////            } else {
////                log.info("更新行程线路失败==========================>" + etOrder.getSn());
////            }
//        }
//    }
//
//
//    /**
//     * 功能说明： URL&Token验证接口。如果验证成功返回msg的值，否则返回其他值。
//     * @param msg 验证消息
//     * @param nonce 随机串
//     * @param signature 签名
//     * @return msg值
//     */
//
//    @RequestMapping(value = "/receive", method = RequestMethod.GET)
//    @ResponseBody
//    public String check(@RequestParam(value = "msg") String msg,
//                        @RequestParam(value = "nonce") String nonce,
//                        @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {
//
//        log.info("check方法接收到参数：: msg:{} nonce{} signature:{}",msg,nonce,signature);
//        if (Util.checkToken(msg,nonce,signature,token)){
//            log.info("校验成功",msg,nonce,signature);
//            return msg;
//        }else {
//            log.info("校验失败",msg,nonce,signature);
//            return "error";
//        }
//
//    }
//
//    private static String[] getDecimalPart(BigDecimal number) {
//        // 将BigDecimal转换为字符串
//        String numberStr = number.toPlainString();
//
//        // 找到小数点的位置
//        int indexOfDecimal = numberStr.indexOf(".");
//
//        // 初始化结果数组
//        String[] parts = new String[2];
//
//        // 如果有小数点
//        if (indexOfDecimal >= 0) {
//            parts[0] = numberStr.substring(0, indexOfDecimal); // 整数部分
//            parts[1] = numberStr.substring(indexOfDecimal + 1); // 小数部分
//        } else {
//            // 如果没有小数点，整数部分为整个字符串，小数部分为空
//            parts[0] = numberStr;
//            parts[1] = "";
//        }
//
//        return parts;
//    }
//}
