New file |
| | |
| | | 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(); |
| | | } |
| | | |
| | | |
| | | } |