kaiyu
2021-12-30 bd9a7f2d97af968d43ccd5516644f6933b42f5b2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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();
    }
 
 
 
}