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 unitConversions; private static Map 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 * @Author: 陈凯裕 * @Date: 2021/12/27 */ public static Map convertUnitToShowUnit(String mac, Map 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 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 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(); } }