package com.flightfeather.obd.socket
|
|
import com.flightfeather.obd.common.utils.FileUtil
|
import com.flightfeather.obd.repository.*
|
import com.flightfeather.obd.socket.bean.EngineDataStream
|
import com.flightfeather.obd.socket.bean.ObdInfo
|
import com.flightfeather.obd.socket.bean.ObdPackageData
|
import com.flightfeather.obd.socket.bean.SupplementDataStream
|
import com.flightfeather.obd.socket.decoder.VehicleDataDecoder
|
import com.flightfeather.obd.socket.decoder.impl.DataPackageDecoderImpl
|
import com.flightfeather.obd.socket.eunm.ObdCommandUnit
|
import io.netty.buffer.Unpooled
|
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 MessageManager{
|
|
companion object{
|
private lateinit var instance: MessageManager
|
}
|
|
@Autowired
|
lateinit var obdDataRepository: ObdDataRepository
|
@Autowired
|
lateinit var originDataRepository: OriginDataRepository
|
@Autowired
|
lateinit var obdInfoRepository: ObdInfoRepository
|
@Autowired
|
lateinit var dataStreamRepository: DataStreamRepository
|
@Autowired
|
lateinit var carLogoutRepository: CarLogoutRepository
|
@Autowired
|
lateinit var carLoginRepository: CarLoginRepository
|
|
val vehicleDataDecoder = VehicleDataDecoder()
|
val dataPackageDecoder = DataPackageDecoderImpl()
|
|
@PostConstruct
|
fun init() {
|
instance = this
|
instance.obdDataRepository = this.obdDataRepository
|
instance.originDataRepository = this.originDataRepository
|
instance.obdInfoRepository = this.obdInfoRepository
|
instance.dataStreamRepository = this.dataStreamRepository
|
instance.carLogoutRepository = this.carLogoutRepository
|
instance.carLoginRepository = this.carLoginRepository
|
}
|
|
fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) {
|
//解包
|
val packageData = vehicleDataDecoder.decode(msg)
|
|
saveToTxt(msg)
|
|
val isCommand = command(packageData, ctx)
|
|
if (isCommand) {
|
println("------远程控制指令 [${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}]")
|
} else {
|
if (bccCheck(msg)) {
|
//保存
|
DeviceSession.saveDevice(packageData.deviceCode, ctx)
|
saveToDataBase(packageData, msg)
|
} else {
|
println("------数据BCC校验失败,舍弃 [${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}]")
|
}
|
}
|
}
|
|
/**
|
* 保存至txt文本
|
*/
|
fun saveToTxt(msg: String) {
|
val data = "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}]data=> $msg"
|
FileUtil.instance?.saveObdData(data)
|
}
|
|
/**
|
* 保存至数据库
|
*/
|
fun saveToDataBase(packageData: ObdPackageData, msg: String) {
|
// instance.obdDataRepository.saveObdData(packageData)
|
instance.originDataRepository.saveOriginData(packageData, msg)
|
when (packageData.commandUnit) {
|
ObdCommandUnit.CarRegister.value -> instance.carLoginRepository.saveCarLogin(packageData)
|
ObdCommandUnit.RealTimeData.value,
|
ObdCommandUnit.ReplacementData.value -> {
|
var done = false
|
for (i in 0 until packageData.dataUnit.size) {
|
when (packageData.dataUnit[i]) {
|
is ObdInfo -> instance.obdInfoRepository.saveObdInfo(packageData)
|
is EngineDataStream,
|
is SupplementDataStream -> {
|
instance.dataStreamRepository.saveDataStream(packageData)
|
done = true
|
}
|
}
|
if (done) break
|
}
|
}
|
ObdCommandUnit.CarLogOut.value-> instance.carLogoutRepository.saveCarLogout(packageData)
|
}
|
}
|
|
/**
|
* BCC(异或校验)
|
*/
|
fun bccCheck(msg: String):Boolean {
|
val list = mutableListOf<String>().apply {
|
addAll(dataPackageDecoder.toStringList(msg))
|
//去除2 位起始符
|
removeAt(0)
|
removeAt(0)
|
}
|
//取得数据包中的bcc校验结果
|
val oldBcc = list[list.size - 1].toInt(16)
|
|
//去除校验结果
|
list.removeAt(list.size-1)
|
|
//计算bcc校验结果
|
var newBcc = 0x00
|
list.forEach {
|
newBcc = newBcc.xor(it.toInt(16))
|
}
|
|
//返回校验结果是否正确
|
return oldBcc == newBcc
|
}
|
|
/**
|
* 远程指令
|
*/
|
fun command(packageData: ObdPackageData, ctx: ChannelHandlerContext?): Boolean {
|
if (packageData.commandUnit == ObdCommandUnit.Update.value) {
|
val channel = DeviceSession.getDevice(packageData.deviceCode)
|
if (channel != null) {
|
val s = getDataPackage(packageData.deviceCode)
|
if (s == null) {
|
ctx?.writeAndFlush("[${packageData.deviceCode}] 设备编号为空")
|
} else {
|
val bytes = encodeToBytes(s)
|
channel.writeAndFlush(Unpooled.copiedBuffer(bytes))
|
ctx?.writeAndFlush("[${packageData.deviceCode}] 指令发送成功")
|
}
|
} else {
|
ctx?.writeAndFlush("[${packageData.deviceCode}] 设备未连接或不存在")
|
}
|
return true
|
} else if (packageData.commandUnit != ObdCommandUnit.CarRegister.value
|
&& packageData.commandUnit != ObdCommandUnit.RealTimeData.value
|
&& packageData.commandUnit != ObdCommandUnit.ReplacementData.value
|
&& packageData.commandUnit != ObdCommandUnit.CarLogOut.value
|
&& packageData.commandUnit != ObdCommandUnit.TimeCalibration.value) {
|
ctx?.writeAndFlush("[${packageData.deviceCode}] 命令不存在")
|
|
return true
|
} else {
|
return false
|
}
|
}
|
|
fun encodeToBytes(msg:String): ByteArray {
|
val list = msg.split(" ")
|
val bytes = ByteArray(list.size)
|
for (i in 0 until list.size) {
|
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()
|
}
|
}
|