package com.moral.api.utils; 
 | 
  
 | 
import com.moral.api.entity.Device; 
 | 
import com.moral.api.entity.Sensor; 
 | 
import com.moral.api.entity.UnitConversion; 
 | 
import com.moral.api.entity.Version; 
 | 
import com.moral.constant.RedisConstants; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.data.redis.core.RedisTemplate; 
 | 
import org.springframework.stereotype.Component; 
 | 
import org.springframework.util.ObjectUtils; 
 | 
import javax.annotation.PostConstruct; 
 | 
import javax.script.ScriptEngine; 
 | 
import javax.script.ScriptEngineManager; 
 | 
import javax.script.ScriptException; 
 | 
import java.math.BigDecimal; 
 | 
import java.util.ArrayList; 
 | 
import java.util.List; 
 | 
import java.util.Map; 
 | 
  
 | 
/** 
 | 
 * @ClassName UnitConvertUtils 
 | 
 * @Description TODO 
 | 
 * @Author 陈凯裕 
 | 
 * @Date 2021/12/27 16:17 
 | 
 * @Version TODO 
 | 
 **/ 
 | 
@Component 
 | 
public class UnitConvertUtils { 
 | 
  
 | 
    /* 
 | 
     * 小数点后保留位数 
 | 
     * */ 
 | 
    public static Integer num = 3; 
 | 
  
 | 
    private static RedisTemplate redisTemplate; 
 | 
  
 | 
    private static List<UnitConversion> unitConversions; 
 | 
  
 | 
    private static Map<String,Device> devices; 
 | 
  
 | 
    @PostConstruct 
 | 
    public void init() { 
 | 
        UnitConvertUtils.unitConversions = redisTemplate.opsForList().range(RedisConstants.UNIT_CONVERSION, 0, -1); 
 | 
        devices = redisTemplate.opsForHash().entries(RedisConstants.DEVICE_INFO); 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setRedisTemplate(RedisTemplate redisTemplate) { 
 | 
        this.redisTemplate = redisTemplate; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 转换数据单位到对应的显示单位 
 | 
     * @Param: [mac, data] 
 | 
     * @return: java.util.Map<java.lang.String                                                               ,                                                               java.lang.Object> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/12/27 
 | 
     */ 
 | 
    public static Map<String, Object> convertUnitToShowUnit(String mac, Map<String, Object> data) { 
 | 
        if (mac == null || data == null) 
 | 
            return null; 
 | 
        Device device = devices.get(mac); 
 | 
        //如果缓存中没有设备则刷新缓存 
 | 
        if(device==null){ 
 | 
            devices = redisTemplate.opsForHash().entries(RedisConstants.DEVICE_INFO); 
 | 
            device = devices.get(mac); 
 | 
            if(device==null) 
 | 
                return null; 
 | 
        } 
 | 
        Version version = device.getVersion(); 
 | 
        //型号中所有的因子 
 | 
        List<Sensor> sensors = version.getSensors(); 
 | 
        //遍历型号中所有的因子,给数据做单位转换 
 | 
        for (Sensor sensor : sensors) { 
 | 
            String unitKey = sensor.getUnitKey();//原始单位 
 | 
            String showUnitKey = sensor.getShowUnitKey();//显示单位 
 | 
            //如果原始单位和显示单位不一致则进行单位转换 
 | 
            if (!unitKey.equals(showUnitKey)) { 
 | 
                Object valueObject = data.get(sensor.getCode()); 
 | 
                //如果因子不存在则跳过本次循环,进行下一个因子处理 
 | 
                if (valueObject == null) 
 | 
                    continue; 
 | 
                //获取计算公式 
 | 
                String formula = getFormula(sensor); 
 | 
                if (formula == null) 
 | 
                    continue; 
 | 
                //获取对应因子数据 
 | 
                Double value = Double.valueOf(String.valueOf(valueObject)); 
 | 
                //对数据转换格式 
 | 
                String valueStr = new BigDecimal(value).toString(); 
 | 
                //用公式对原始数据进行转换 
 | 
                String calculateValue = calculate(valueStr, formula); 
 | 
                if(calculateValue==null) 
 | 
                    continue; 
 | 
                value = Double.parseDouble(calculateValue); 
 | 
                data.put(sensor.getCode(),value); 
 | 
            } else 
 | 
                continue; 
 | 
        } 
 | 
        return data; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 获取单位转换的公式 
 | 
     * @Param: [sensor] 
 | 
     * @return: java.lang.String 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/12/28 
 | 
     */ 
 | 
    private static String getFormula(Sensor sensor) { 
 | 
        String formula = sensor.getFormula(); 
 | 
        if (!ObjectUtils.isEmpty(formula)) 
 | 
            return formula; 
 | 
  
 | 
        List<UnitConversion> tmpUnitConversions = new ArrayList<>(); 
 | 
        for (UnitConversion unitConversion : unitConversions) { 
 | 
            if (unitConversion.getOriginalUnitKey().equals(sensor.getUnitKey()) && unitConversion.getTargetUnitKey().equals(sensor.getShowUnitKey())) 
 | 
                tmpUnitConversions.add(unitConversion); 
 | 
        } 
 | 
        //如果缓存没有则刷新程序内部缓存 
 | 
        if (tmpUnitConversions.size() == 0) { 
 | 
            refreshUnitConversionCache(); 
 | 
        } 
 | 
        //重新查找公式 
 | 
        for (UnitConversion unitConversion : unitConversions) { 
 | 
            if (unitConversion.getOriginalUnitKey().equals(sensor.getUnitKey()) && unitConversion.getTargetUnitKey().equals(sensor.getShowUnitKey())) 
 | 
                tmpUnitConversions.add(unitConversion); 
 | 
        } 
 | 
        //如果没有则直接返回null 
 | 
        if (tmpUnitConversions.size() == 0) 
 | 
            return null; 
 | 
        //如果只有一个则是没有专用因子 
 | 
        if (unitConversions.size() == 1) 
 | 
            return unitConversions.get(0).getFormula(); 
 | 
        //根据专用因子剔除 
 | 
        for (UnitConversion unitConversion : unitConversions) { 
 | 
            if (unitConversion.getSensorCode().equals(sensor.getCode())) 
 | 
                return unitConversion.getFormula(); 
 | 
        } 
 | 
        return null; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 刷新公式内部缓存 
 | 
     * @Param: [] 
 | 
     * @return: void 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/12/28 
 | 
     */ 
 | 
    private static void refreshUnitConversionCache() { 
 | 
        UnitConvertUtils.unitConversions = redisTemplate.opsForList().range(RedisConstants.UNIT_CONVERSION, 0, -1); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: value为要转换的值,format为公式 
 | 
     * @Param: [value, format] 
 | 
     * @return: java.lang.Double 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/7/5 
 | 
     */ 
 | 
    public static String calculate(String value, String formula) { 
 | 
        if (ObjectUtils.isEmpty(formula)) 
 | 
            return null; 
 | 
        ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); 
 | 
        formula = formula.replaceAll("\\{0\\}", value); 
 | 
        Double result = null; 
 | 
        try { 
 | 
            result = (Double) jse.eval(formula); 
 | 
        } catch (ScriptException e) { 
 | 
            e.printStackTrace(); 
 | 
        } 
 | 
        //保留小数点后三位 
 | 
        BigDecimal bg = new BigDecimal(result); 
 | 
        result = bg.setScale(num, BigDecimal.ROUND_HALF_UP).doubleValue(); 
 | 
        return result.toString(); 
 | 
    } 
 | 
  
 | 
  
 | 
  
 | 
} 
 |