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
package com.flightfeather.uav.socket.processor
 
import com.flightfeather.uav.biz.FactorFilter
import com.flightfeather.uav.biz.sourcetrace.RealTimeExceptionAnalysisController
import com.flightfeather.uav.common.location.LocationRoadNearby
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.model.epw.EPWDataPrep
import com.flightfeather.uav.domain.repository.AirDataRep
import com.flightfeather.uav.domain.repository.RealTimeDataRep
import com.flightfeather.uav.domain.repository.SceneInfoRep
import com.flightfeather.uav.domain.repository.SegmentInfoRep
import com.flightfeather.uav.socket.bean.AirDataPackage
import com.flightfeather.uav.socket.decoder.AirDataDecoder
import com.flightfeather.uav.socket.decoder.DataPackageDecoder
import com.flightfeather.uav.socket.eunm.AirCommandUnit
import com.flightfeather.uav.socket.eunm.FactorType
import com.flightfeather.uav.socket.eunm.UWDeviceType
import com.flightfeather.uav.socket.handler.UnderwayWebSocketServerHandler
import io.netty.channel.ChannelHandlerContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.text.SimpleDateFormat
import java.util.*
import javax.annotation.PostConstruct
 
/**
 * 处理socket接收的消息
 * Date: 2019.8.27
 * @author riku
 */
 
@Component
class UnderwayProcessor(
    private val airDataRep: AirDataRep,
    private val sceneInfoRep: SceneInfoRep,
) : BaseProcessor() {
 
    companion object {
        private const val TAG = "UAV"
    }
 
    private val airDataDecoder = AirDataDecoder.instance
    private val dataPackageDecoder = DataPackageDecoder()
 
    // 数据预处理函数
    private val dataProcessMap = mutableMapOf<String?, EPWDataPrep>()
 
    // 实时走航污染溯源处理器
    private val realTimeExceptionAnalysisMap = mutableMapOf<String?, RealTimeExceptionAnalysisController>()
 
    override var tag: String = "走航监测"
 
    override fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) {
        //解包
        val packageData = airDataDecoder.decode(msg)
 
        if (bccCheck(msg)) {
            //保存
            deviceSession.saveDevice(packageData.deviceCode, ctx)
            saveToTxt(msg)
            saveToDataBase(packageData)?.takeIf { it.isNotEmpty() }?.get(0)?.let {
                // 每台设备有各自单独的异常数据处理器
                if (!realTimeExceptionAnalysisMap.containsKey(it.deviceCode)) {
                    realTimeExceptionAnalysisMap[it.deviceCode] = RealTimeExceptionAnalysisController(sceneInfoRep)
                }
                // 将走航数据传入异常处理器
                realTimeExceptionAnalysisMap[it.deviceCode]?.addOneData(it)
            }
 
        } else {
            println("------${TAG}数据BCC校验失败,舍弃 [${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}]")
        }
    }
 
    /**
     * 保存至数据库
     */
    fun saveToDataBase(dataPackage: AirDataPackage): List<BaseRealTimeData>? {
        when (dataPackage.commandUnit) {
            AirCommandUnit.AirData.value -> {
                // 以json格式存储原始数据
                airDataRep.saveAirData(dataPackage)
                // 进行预处理后,存储至对应数据表
                if (!dataProcessMap.containsKey(dataPackage.deviceCode)) {
                    // 每台设备有单独的数据预处理对象
                    dataProcessMap[dataPackage.deviceCode] = EPWDataPrep(UWDeviceType.getType(dataPackage.deviceCode))
                }
                return dataProcessMap[dataPackage.deviceCode]?.run {
                    val list = this.mDataPrep2(dataPackage)// 数据平滑处理
                    airDataRep.savePrepData2(list)// 按照设备类型存储至对应数据表
                }
            }
 
            else -> return emptyList()
        }
    }
 
    /**
     * BCC(异或校验)
     */
    fun bccCheck(msg: String): Boolean {
        val list = mutableListOf<String>().apply {
            addAll(dataPackageDecoder.toStringList(msg))
        }
        //取得数据包中的bcc校验结果
        val oldBcc = "${list[list.lastIndex - 1]}${list[list.lastIndex]}".toInt(16)
 
        //去除校验结果
        list.removeAt(list.lastIndex)
        list.removeAt(list.lastIndex)
 
        //计算bcc校验结果
        var newBcc = 0x00
        list.forEach {
            newBcc = newBcc.xor(it.toInt(16))
        }
 
        //返回校验结果是否正确
        return oldBcc == newBcc
    }
 
 
    fun encodeToBytes(msg: String): ByteArray {
        val list = msg.split(" ")
        val bytes = ByteArray(list.size)
        for (i in list.indices) {
            bytes[i] = list[i].toInt(16).toByte()
        }
 
        return bytes
    }
 
    fun getDataPackage(deviceCode: String?): String? {
        if (deviceCode == null) return null
        //23 23 7f 31 37 36 39 31 35 33 31 39 30 39 31 32 30 30 31 31 01 01 00 00 39
        val sb = StringBuilder("23 23 10 ")
        deviceCode.forEach {
            sb.append(it.toInt().toString(16)).append(" ")
        }
        sb.append("01 01 00 00 00 0A 41 54 2B 56 45 52 53 49 4F 4E")
 
        val list = sb.split(" ")
 
        //计算bcc校验结果
        var bcc = 0x00
        list.forEach {
            bcc = bcc.xor(it.toInt(16))
        }
 
        sb.append(" ").append(bcc.toString(16))
 
        return sb.toString()
    }
}