| | |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | <exclusions> |
| | | <!-- å»é¤æ§logä¾èµ --> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-logging</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.module</groupId> |
| | |
| | | <version>1.2.12</version> |
| | | </dependency> |
| | | |
| | | <!--å¢å log4j2ä¾èµâ--> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-log4j2</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.common.utils |
| | | |
| | | import java.io.BufferedWriter |
| | | import java.io.File |
| | | import java.io.FileWriter |
| | | import java.text.SimpleDateFormat |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/11 |
| | | */ |
| | | class FileUtil { |
| | | |
| | | private var file: File |
| | | private var basePath:String = "${File.separator}ObdData${File.separator}" |
| | | private var closeThread: Thread? = null |
| | | private var fw: FileWriter? = null |
| | | private var bw: BufferedWriter? = null |
| | | |
| | | init { |
| | | val fileName = "data-${SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Date())}.txt" |
| | | val path = "$basePath$fileName" |
| | | file = File(path) |
| | | } |
| | | |
| | | companion object{ |
| | | var instance: FileUtil? = null |
| | | get() { |
| | | if (field == null) { |
| | | field = FileUtil() |
| | | } |
| | | return field |
| | | } |
| | | } |
| | | |
| | | fun saveObdData(str: String) { |
| | | //æ£æ¥ææ¡£æ¯å¦åå¨ |
| | | if (!file.exists()) { |
| | | file.parentFile.mkdirs() |
| | | println("----å建æä»¶å¤¹ï¼${file.parentFile.absolutePath}") |
| | | file.createNewFile() |
| | | println("----å建æä»¶ï¼${file.absolutePath}") |
| | | } |
| | | //æä»¶æå¤§512Kb,è¶
è¿åæ°å»ºææ¡£ |
| | | if (file.length() + str.toByteArray().size > 512 * 1024) { |
| | | val fileName = "data-${SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(Date())}.txt" |
| | | val path = "$basePath$fileName" |
| | | file = File(path) |
| | | file.createNewFile() |
| | | |
| | | //å
³éåæè¾åºæµ |
| | | bw?.run { |
| | | flush() |
| | | close() |
| | | } |
| | | fw?.run { |
| | | flush() |
| | | close() |
| | | } |
| | | //æ°å»ºè¾åºæµ |
| | | fw = FileWriter(file, true) |
| | | bw = BufferedWriter(fw) |
| | | } |
| | | //ç¬¬ä¸æ¬¡åææ¡£æ¶åå§åè¾åºæµ |
| | | if (bw == null || fw == null) { |
| | | fw = FileWriter(file, true) |
| | | bw = BufferedWriter(fw) |
| | | } |
| | | |
| | | bw?.run { |
| | | write(str) |
| | | newLine() |
| | | flush() |
| | | } |
| | | |
| | | readyToShutDownStream(bw, fw) |
| | | println("----åå
¥å®æ") |
| | | |
| | | } |
| | | |
| | | private fun readyToShutDownStream(bw: BufferedWriter?, fw:FileWriter?) { |
| | | //ç»ç«¯ä¸ä¸æ¬¡ç计æ¶çº¿ç¨ |
| | | closeThread?.interrupt() |
| | | closeThread = Thread(Runnable { |
| | | //2åéæ²¡ææ°çæ°æ®åå
¥å°±å
³éè¾åºæµ |
| | | try { |
| | | Thread.sleep(20 * 1000) |
| | | } catch (e: Throwable) { |
| | | } |
| | | bw?.run { |
| | | close() |
| | | } |
| | | this.bw = null |
| | | fw?.run { |
| | | close() |
| | | } |
| | | this.fw = null |
| | | }).also { |
| | | it.start() |
| | | } |
| | | } |
| | | } |
| | |
| | | var obdEngineTorque: Double? = null |
| | | var obdFrictionTorque: Double? = null |
| | | var obdEngineRpm: Int? = null |
| | | var obdStartFuelFlow: Double? = null |
| | | var obdEngineFuelFlow: Double? = null |
| | | var obdScrUpstreamNo: Double? = null |
| | | var obdScrDownstreamNo: Double? = null |
| | | var obdRemainReactant: Double? = null |
| | |
| | | import com.flightfeather.obd.domain.entity.ObdData |
| | | import com.flightfeather.obd.domain.mapper.ObdDataMapper |
| | | import com.flightfeather.obd.lightshare.bean.ObdDataVo |
| | | import com.flightfeather.obd.socket.bean.ObdPackageData |
| | | import org.springframework.beans.BeanUtils |
| | | import org.springframework.beans.factory.annotation.Autowired |
| | | import org.springframework.stereotype.Component |
| | |
| | | * éè¿æ±½è½¦vinç è·åææ°æ°æ® |
| | | */ |
| | | fun getDataByVinCode(vinCode: String, pageNum: Int?, pageSize: Int?): MutableList<ObdDataVo> |
| | | |
| | | fun saveObdData(packageData: ObdPackageData):Boolean |
| | | |
| | | } |
| | |
| | | import com.flightfeather.obd.domain.mapper.ObdDataMapper |
| | | import com.flightfeather.obd.lightshare.bean.ObdDataVo |
| | | import com.flightfeather.obd.repository.ObdDataRepository |
| | | import com.flightfeather.obd.socket.bean.EngineDataFlow |
| | | import com.flightfeather.obd.socket.bean.ObdPackageData |
| | | import com.flightfeather.obd.socket.bean.SupplementDataFlow |
| | | import com.flightfeather.obd.socket.eunm.ObdCommandUnit |
| | | import com.github.pagehelper.PageHelper |
| | | import org.springframework.beans.BeanUtils |
| | | import org.springframework.stereotype.Repository |
| | |
| | | |
| | | return resultList |
| | | } |
| | | |
| | | override fun saveObdData(packageData: ObdPackageData): Boolean { |
| | | val obdData = ObdData().apply { |
| | | obdVin = packageData.vinCode |
| | | } |
| | | when (packageData.commandUnit) { |
| | | ObdCommandUnit.CarRegister.value -> { |
| | | |
| | | } |
| | | ObdCommandUnit.RealTimeData.value, |
| | | ObdCommandUnit.ReplacementData.value -> { |
| | | packageData.dataUnit.forEach { |
| | | when (it) { |
| | | is com.flightfeather.obd.socket.bean.ObdData -> { |
| | | obdData.apply { |
| | | obdTime = it.time |
| | | obdProtocol = it.obdProtocol |
| | | obdMil = it.obdMil |
| | | obdIdCode = it.obdSoftwareCode |
| | | obdVerificationCode = it.obdCvn |
| | | obdFaultCodeNum = it.obdFaultCodeNum |
| | | obdFaultCode = it.obdFaultCode |
| | | } |
| | | } |
| | | is EngineDataFlow -> { |
| | | obdData.apply { |
| | | obdLng = it.obdLong |
| | | obdLat = it.obdLat |
| | | obdSpeed = it.obdSpeed?.toInt() |
| | | obdAirPressure = it.obdAirPressure |
| | | obdEngineTorque = it.obdEngineTorque |
| | | obdFrictionTorque = it.obdFrictionTorque |
| | | obdEngineRpm = it.obdEngineRpm?.toInt() |
| | | obdStartFuelFlow = it.obdEngineFuelFlow |
| | | obdScrUpstreamNo = it.obdScrUpstreamNo |
| | | obdScrDownstreamNo = it.obdScrDownstreamNo |
| | | obdRemainReactant = it.obdRemainReactant |
| | | obdAirInput = it.obdAirInput |
| | | obdScrInputTemp = it.obdScrInputTemp |
| | | obdScrOutputTemp = it.obdScrOutputTemp |
| | | obdDpf = it.obdDpf |
| | | obdEngineCoolantTemp = it.obdEngineCoolantTemp |
| | | obdFuelLevel = it.obdFuelLevel |
| | | obdLocationStatus = it.obdLocationStatus |
| | | obdTotalMileage = it.obdTotalMileage |
| | | } |
| | | } |
| | | is SupplementDataFlow -> { |
| | | obdData.apply { |
| | | obdEngineTorqueMode = it.obdEngineTorqueMode?.toString() |
| | | obdAcceleratorPedal = it.obdAcceleratorPedal |
| | | obdTotalOilConsumption = it.obdTotalOilConsumption |
| | | obdUreaBoxTemp = it.obdUreaBoxTemp |
| | | obdUreaVolume = it.obdUreaVolume?.toInt() |
| | | obdTotalUreaConsume = it.obdTotalUreaConsume |
| | | obdDpfTemp = it.obdDpfTemp |
| | | // obdFirmwareVersion = |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | ObdCommandUnit.CarLogOut.value -> { |
| | | |
| | | } |
| | | ObdCommandUnit.TimeCalibration.value -> { |
| | | |
| | | } |
| | | } |
| | | |
| | | return obdDataMapper.insert(obdData) == 1 |
| | | } |
| | | } |
| | |
| | | package com.flightfeather.obd.socket |
| | | |
| | | import com.flightfeather.obd.common.utils.FileUtil |
| | | import com.flightfeather.obd.lightshare.bean.BaseJson |
| | | import com.flightfeather.obd.lightshare.bean.ObdDataVo |
| | | import com.flightfeather.obd.repository.ObdDataRepository |
| | | import com.flightfeather.obd.socket.decoder.VehicleDataDecoder |
| | | import com.google.gson.Gson |
| | | import io.netty.channel.ChannelHandlerContext |
| | | import org.springframework.beans.factory.annotation.Autowired |
| | | import org.springframework.stereotype.Component |
| | | import org.springframework.util.FileSystemUtils |
| | | import javax.annotation.PostConstruct |
| | | import javax.annotation.Resource |
| | | |
| | |
| | | @Autowired |
| | | lateinit var obdDataRepository: ObdDataRepository |
| | | |
| | | val vehicleDataDecoder = VehicleDataDecoder() |
| | | |
| | | @PostConstruct |
| | | fun init() { |
| | | instance = this |
| | | instance.obdDataRepository = this.obdDataRepository |
| | | } |
| | | |
| | | fun dealMsg(msg: String, ctx: ChannelHandlerContext?) { |
| | | try { |
| | | val baseJson = Gson().fromJson<BaseJson>(msg, BaseJson::class.java) |
| | | when (baseJson.cmdCode) { |
| | | 2001 -> { |
| | | val data = Gson().fromJson(msg, ObdDataVo::class.java) |
| | | DeviceSession.saveDevice(data.obdVin, ctx) |
| | | instance.obdDataRepository.saveObdData(data) |
| | | fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) { |
| | | // try { |
| | | // val baseJson = Gson().fromJson<BaseJson>(msg, BaseJson::class.java) |
| | | // when (baseJson.cmdCode) { |
| | | // 2001 -> { |
| | | // val data = Gson().fromJson(msg, ObdDataVo::class.java) |
| | | // DeviceSession.saveDevice(data.obdVin, ctx) |
| | | // instance.obdDataRepository.saveObdData(data) |
| | | // } |
| | | // } |
| | | // } catch (e: Throwable) { |
| | | // } |
| | | |
| | | saveToTxt(msg) |
| | | val packageData = vehicleDataDecoder.decode(msg) |
| | | } |
| | | |
| | | fun dealByteArrayMsg(msg: ByteArray, ctx: ChannelHandlerContext?) { |
| | | val b = ByteArray(20) {19} |
| | | println(b) |
| | | } |
| | | } catch (e: Throwable) { |
| | | // println("------æ¶å°æ ¼å¼éè¯¯çæ°æ®ï¼$msg") |
| | | } |
| | | |
| | | fun saveToTxt(msg: String) { |
| | | val data = "data=> $msg" |
| | | FileUtil.instance?.saveObdData(data) |
| | | } |
| | | } |
| | |
| | | import io.netty.channel.ChannelHandlerContext |
| | | import io.netty.channel.ChannelInboundHandlerAdapter |
| | | import io.netty.util.AttributeKey |
| | | import java.lang.StringBuilder |
| | | import java.text.SimpleDateFormat |
| | | import java.util.* |
| | | |
| | | |
| | | class ServerHandler : ChannelInboundHandlerAdapter() { |
| | |
| | | |
| | | override fun channelRegistered(ctx: ChannelHandlerContext?) { |
| | | super.channelRegistered(ctx) |
| | | // ctx?.fireChannelActive() |
| | | } |
| | | |
| | | override fun channelActive(ctx: ChannelHandlerContext?) { |
| | |
| | | |
| | | override fun channelRead(ctx: ChannelHandlerContext?, msg: Any?) { |
| | | super.channelRead(ctx, msg) |
| | | println("------æ¶å°çåå§æ°æ®ï¼[ip:${ctx?.channel()?.remoteAddress()}]\r\n$msg") |
| | | if (msg is String) { |
| | | MessageManager().dealMsg(msg, ctx) |
| | | } |
| | | |
| | | // val attribute = ctx?.channel()?.attr(attributeKey)?.apply { |
| | | // if (get() == null) { |
| | | // set(data.obdVin) |
| | | // } |
| | | // } |
| | | val sb = StringBuilder() |
| | | |
| | | if (msg is ByteArray) { |
| | | println("------æ¶å°çåå§æ°æ®ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") |
| | | msg.forEach { |
| | | var a = 0 |
| | | a = if (it < 0) { |
| | | it + 256 |
| | | } else { |
| | | it.toInt() |
| | | } |
| | | print("${a.toString(16)} ") |
| | | sb.append(a.toString(16)).append(" ") |
| | | } |
| | | sb.deleteCharAt(sb.length - 1) |
| | | } |
| | | val str = sb.toString() |
| | | if (str.isNotEmpty()) { |
| | | MessageManager().dealStringMsg(str, ctx) |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | import io.netty.channel.ChannelInitializer |
| | | import io.netty.channel.ChannelOption |
| | | import io.netty.channel.nio.NioEventLoopGroup |
| | | import io.netty.channel.socket.SocketChannel |
| | | import io.netty.channel.socket.nio.NioServerSocketChannel |
| | | import io.netty.channel.socket.nio.NioSocketChannel |
| | | import io.netty.handler.codec.bytes.ByteArrayDecoder |
| | | import io.netty.handler.codec.bytes.ByteArrayEncoder |
| | | import io.netty.handler.codec.string.StringDecoder |
| | | import io.netty.handler.codec.string.StringEncoder |
| | | |
| | | /** |
| | | * socketé¿è¿æ¥æå¡ç«¯ |
| | |
| | | return ServerBootstrap() |
| | | .group(bossGroup, workerGroup) |
| | | .channel(NioServerSocketChannel::class.java) |
| | | .option(ChannelOption.SO_BACKLOG, 128) |
| | | .childOption(ChannelOption.SO_KEEPALIVE, true) |
| | | .childOption(ChannelOption.TCP_NODELAY, true) |
| | | .childHandler(object : ChannelInitializer<NioSocketChannel>() { |
| | | override fun initChannel(p0: NioSocketChannel?) { |
| | | p0?.pipeline() |
| | | ?.addLast(StringDecoder()) |
| | | // ?.addLast("decoder", StringDecoder()) |
| | | // ?.addLast("encoder", StringEncoder()) |
| | | ?.addLast(ByteArrayDecoder()) |
| | | ?.addLast(ByteArrayEncoder()) |
| | | ?.addLast(ServerHandler()) |
| | | } |
| | | }) |
| | | .option(ChannelOption.SO_BACKLOG, 128) |
| | | .childOption(ChannelOption.SO_KEEPALIVE, true) |
| | | } catch (e: Throwable) { |
| | | e.printStackTrace() |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * 车è¾ç»åºä¿¡æ¯ |
| | | * |
| | | */ |
| | | class CarLogOutData( |
| | | var time: Date? = null, |
| | | var serialNum: Int? = null |
| | | ): DataUnit() |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * |
| | | * 车è¾ç»å
¥æ°æ®æ ¼å¼ |
| | | * |
| | | * èµ·å§åè å
容 æè¿° |
| | | * 0 æ°æ®ééæ¶é´ æ¶é´å®ä¹è§ 6.4.4 |
| | | * 6 ç»å
¥æµæ°´å· 车载ç»ç«¯æ¯ç»å
¥ä¸æ¬¡ï¼ç»å
¥æµæ°´å·èªå¨å 1ï¼ä» 1å¼å§å¾ªç¯ç´¯å ï¼æå¤§å¼ä¸º 65531ï¼å¾ªç¯å¨æä¸ºå¤©ã |
| | | * 10 SIM å¡å· SIM å¡ ICCID å·ï¼ICCID åºä¸ºç»ç«¯ä» SIM å¡è·åçå¼ï¼ä¸åºäººä¸ºå¡«åæä¿®æ¹ï¼ã |
| | | */ |
| | | class CarRegisterData( |
| | | var time: Date? = null, |
| | | var serialNum: Int? = null, |
| | | var SIMCode: String? = null |
| | | ): DataUnit() |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | open class DataUnit { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | * å卿ºæ°æ®æµ |
| | | */ |
| | | class EngineDataFlow( |
| | | time: Date?, |
| | | serialNum: Int? |
| | | ) : RealTimeData(time, serialNum) { |
| | | var obdSpeed: Double? = null |
| | | var obdAirPressure: Double? = null |
| | | var obdEngineTorque: Double? = null |
| | | var obdFrictionTorque: Double? = null |
| | | var obdEngineRpm: Double? = null |
| | | var obdEngineFuelFlow: Double? = null |
| | | var obdScrUpstreamNo: Double? = null |
| | | var obdScrDownstreamNo: Double? = null |
| | | var obdRemainReactant: Double? = null |
| | | var obdAirInput: Double? = null |
| | | var obdScrInputTemp: Double? = null |
| | | var obdScrOutputTemp: Double? = null |
| | | var obdDpf: Double? = null |
| | | var obdEngineCoolantTemp: Double? = null |
| | | var obdFuelLevel: Double? = null |
| | | var obdLocationStatus: Int? = null |
| | | var obdLong: Double? = null |
| | | var obdLat: Double? = null |
| | | var obdTotalMileage: Double? = null |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import com.flightfeather.obd.socket.bean.* |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | * 宿¶ä¿¡æ¯[RealTimeData] ä¸çobdæ°æ® |
| | | */ |
| | | class ObdData( |
| | | time: Date?, |
| | | serialNum: Int? |
| | | ) : RealTimeData(time, serialNum) { |
| | | var obdProtocol: Int? = null |
| | | var obdMil: Int? = null |
| | | var diagnosisSupportStatus: String? = null//è¯ææ¯æç¶æ |
| | | var diagnosisReadyStatus: String? = null//è¯æå°±ç»ªç¶æ |
| | | var obdVin: String? = null |
| | | var obdSoftwareCode: String? = null//软件æ å®è¯å«å· |
| | | var obdCvn: String? = null//æ å®éªè¯ç |
| | | var IUPR:String?=null//å®ä¹åè SAE J 1979-DA 表 G11 |
| | | var obdFaultCodeNum: Int? = null//æ
éç æ»æ°: ææå¼èå´ï¼0~253ï¼â0xFEâè¡¨ç¤ºæ æã |
| | | var obdFaultCode: String? = null//æ
éç ä¿¡æ¯å表: æ¯ä¸ªæ
éç 为ååèï¼å¯ææ
éå®é
顺åºè¿è¡æåº |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | data class ObdPackageData constructor( |
| | | var head: String? = null, |
| | | var commandUnit: Int? = null, |
| | | var vinCode: String? = null, |
| | | var softwareVersion: Int? = null, |
| | | var encryptionWay: Int? = null, |
| | | var dataLength: Int? = null, |
| | | var dataUnit: List<DataUnit>, |
| | | var checkCode: Int? = null |
| | | ) |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * |
| | | */ |
| | | open class RealTimeData( |
| | | var time: Date? = null, |
| | | var serialNum: Int? = null |
| | | ) : ReplacementData() |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * è¡¥åä¿¡æ¯ä¸å®æ¶ä¿¡æ¯å
容ä¸è´ |
| | | */ |
| | | open class ReplacementData : DataUnit() { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | * è¡¥å
æ°æ®æµ |
| | | * |
| | | * èµ·å§åè æ°æ®é¡¹ æ°æ®ç±»å åä½ æè¿°åè¦æ± |
| | | * 0 å卿ºæç©æ¨¡å¼ BYTE 0ï¼è¶
é失æ |
| | | * 1ï¼è½¬éæ§å¶ |
| | | * 2ï¼æç©æ§å¶ |
| | | * 3ï¼è½¬é/æç©æ§å¶ |
| | | * 1 æ²¹é¨è¸æ¿ BYTE % æ°æ®é¿åº¦ï¼1bytes |
| | | * 精度ï¼0.4%/bit |
| | | * åç§»éï¼0 |
| | | * æ°æ®èå´ï¼0~100% |
| | | * â0xFFâè¡¨ç¤ºæ æ |
| | | * 2 累计油èï¼æ»æ²¹èï¼ DWORD L æ°æ®é¿åº¦ï¼4bytes |
| | | * 精度ï¼0.5L per bit |
| | | * åç§»éï¼0 |
| | | * æ°æ®èå´ï¼0~2,105,540,607.5L |
| | | * â0xFF,0xFF,0xFF,0xFFâè¡¨ç¤ºæ æ |
| | | * 6 å°¿ç´ ç®±æ¸©åº¦ BYTE â æ°æ®é¿åº¦ï¼1bytes |
| | | * 精度ï¼1 â/bit |
| | | * åç§»éï¼-40 |
| | | * æ°æ®èå´ï¼-40~210â |
| | | * â0xFFâè¡¨ç¤ºæ æ |
| | | * 7 å®é
å°¿ç´ å·å°é DWORD ml/h æ°æ®é¿åº¦ï¼4bytes |
| | | * 精度ï¼0.01 ml/h per bit |
| | | * åç§»éï¼0 |
| | | * æ°æ®èå´ï¼0 |
| | | * â0xFF,0xFF,0xFF,0xFFâè¡¨ç¤ºæ æ |
| | | * 11 ç´¯è®¡å°¿ç´ æ¶èï¼æ»å°¿ç´ æ¶èï¼DWORD g æ°æ®é¿åº¦ï¼4bytes |
| | | * 精度ï¼1 g per bit |
| | | * åç§»éï¼0 |
| | | * æ°æ®èå´ï¼0 |
| | | * â0xFF,0xFF,0xFF,0xFFâè¡¨ç¤ºæ æ |
| | | * 15 DPF ææ°æ¸©åº¦ WORD â æ°æ®é¿åº¦ï¼2bytes |
| | | * 精度ï¼0.03125 â per bit |
| | | * åç§»éï¼-273 |
| | | * æ°æ®èå´ï¼-273~1734.96875â |
| | | * â0xFF,0xFFâè¡¨ç¤ºæ æ |
| | | */ |
| | | class SupplementDataFlow( |
| | | time: Date?, |
| | | serialNum: Int? |
| | | ) : RealTimeData(time, serialNum) { |
| | | var obdEngineTorqueMode: Int? = null |
| | | var obdAcceleratorPedal: Double? = null |
| | | var obdTotalOilConsumption: Double? = null |
| | | var obdUreaBoxTemp: Double? = null |
| | | var obdUreaVolume: Double? = null |
| | | var obdTotalUreaConsume: Double? = null |
| | | var obdDpfTemp: Double? = null |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.bean |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | class TimeCalibrationData : DataUnit() { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder |
| | | |
| | | import com.flightfeather.obd.socket.bean.DataUnit |
| | | import com.flightfeather.obd.socket.eunm.ObdCommandUnit |
| | | |
| | | /** |
| | | * obd 第ä¸å±æ°æ®å
è§£ç å¨ |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * |
| | | * æ°æ®ç¬¬ä¸å±ç»æå®ä¹å¦ä¸ï¼ |
| | | * èµ·å§åè å®ä¹ |
| | | * 0 èµ·å§ç¬¦ |
| | | * 2 å½ä»¤åå
ç±»å@see [ObdCommandUnit] |
| | | * 3 车è¾è¯å«å· |
| | | * 4 ç»ç«¯è½¯ä»¶çæ¬å· |
| | | * 21 æ°æ®å 坿¹å¼ |
| | | * 22 æ°æ®åå
é¿åº¦ |
| | | * 24 æ°æ®åå
è§£ç å¨@see [DataUnitDecoder] |
| | | * åæ°ç¬¬1 æ ¡éªç |
| | | */ |
| | | interface DataPackageDecoder { |
| | | |
| | | fun getHead(b: List<String>): String? |
| | | |
| | | fun getCommandUnit(b: List<String>): Int? |
| | | |
| | | fun getVinCode(b: List<String>): String? |
| | | |
| | | fun getSoftwareVersion(b: List<String>): Int? |
| | | |
| | | fun getEncryptionWay(b: List<String>): Int? |
| | | |
| | | fun getDataLength(b: List<String>): Int |
| | | |
| | | fun getDataUnit(b: List<String>): List<DataUnit> |
| | | |
| | | fun getCheckCode(b: List<String>): Int? |
| | | |
| | | fun toStringList(msg: String): List<String> |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder |
| | | |
| | | import com.flightfeather.obd.socket.bean.* |
| | | import com.flightfeather.obd.socket.eunm.ObdCommandUnit |
| | | import java.util.* |
| | | |
| | | /** |
| | | * obd 第äºå±æ°æ®åå
è§£ç å¨ |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | * |
| | | * æ°æ®åå
æç
§å½ä»¤åå
çç±»åå
±æä»¥ä¸å ç§ç±»åï¼ |
| | | * å½ä»¤åå
@see [ObdCommandUnit] |
| | | * ç¼ç (byte) å®ä¹ |
| | | * 0x01 车è¾ç»å
¥ |
| | | * 0x02 宿¶ä¿¡æ¯ä¸æ¥ |
| | | * 0x03 è¡¥åä¿¡æ¯ä¸æ¥ |
| | | * 0x04 车è¾ç»åº |
| | | * 0x05 ç»ç«¯æ ¡æ¶ |
| | | * 0x06~0x7f ä¸è¡æ°æ®ç³»ç»é¢ç |
| | | */ |
| | | interface DataUnitDecoder { |
| | | |
| | | fun getCarRegisterData(b: List<String>): List<CarRegisterData> |
| | | |
| | | fun getRealTimeData(b: List<String>): List<RealTimeData> |
| | | |
| | | fun getReplacementData(b: List<String>): List<ReplacementData> |
| | | |
| | | fun getCarLogOutData(b: List<String>): List<CarLogOutData> |
| | | |
| | | fun getTimeCalibrationData(b: List<String>): List<TimeCalibrationData> |
| | | |
| | | fun decodeDataTime(b: List<String>): Date? |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder |
| | | |
| | | import com.flightfeather.obd.socket.bean.* |
| | | import com.flightfeather.obd.socket.eunm.ObdDataType |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | * æ°æ®åå
[DataUnit]ä¸ï¼ç±»åä¸ºå®æ¶ä¿¡æ¯[RealTimeData]çè§£ç å¨ |
| | | * å
¶åç±» @see [ObdDataType] |
| | | */ |
| | | interface RealTimeDataDecoder { |
| | | |
| | | fun getObdData(time: Date?, serialNum: Int, b: List<String>): ObdData? |
| | | |
| | | fun getEngineDataFlow(time: Date?, serialNum: Int, b: List<String>): EngineDataFlow? |
| | | |
| | | fun getSupplementDataFlow(time: Date?, serialNum: Int, b: List<String>): SupplementDataFlow? |
| | | |
| | | /** |
| | | * æ ¹æ®ä¼ å
¥çå表ï¼é»è®¤ç¬¬ä¸ä½ä¸º [ObdDataType]ï¼è¿å对åºçæ°æ®å表 |
| | | */ |
| | | fun getDataListByDataType(list: List<String>): MutableList<String> |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder |
| | | |
| | | import com.flightfeather.obd.socket.bean.ObdPackageData |
| | | import com.flightfeather.obd.socket.decoder.impl.DataPackageDecoderImpl |
| | | import org.springframework.beans.factory.annotation.Autowired |
| | | import org.springframework.stereotype.Component |
| | | import javax.annotation.PostConstruct |
| | | |
| | | /** |
| | | * è½¦è¾ obd æ°æ®è§£ç å¨ |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | class VehicleDataDecoder { |
| | | |
| | | private val dataPackageDecoder: DataPackageDecoder = DataPackageDecoderImpl() |
| | | |
| | | fun decode(msg: String): ObdPackageData { |
| | | val list = dataPackageDecoder.toStringList(msg) |
| | | dataPackageDecoder.run { |
| | | return ObdPackageData( |
| | | getHead(list), |
| | | getCommandUnit(list), |
| | | getVinCode(list), |
| | | getSoftwareVersion(list), |
| | | getEncryptionWay(list), |
| | | getDataLength(list), |
| | | getDataUnit(list), |
| | | getCheckCode(list) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder.impl |
| | | |
| | | import com.flightfeather.obd.socket.bean.DataUnit |
| | | import com.flightfeather.obd.socket.decoder.DataPackageDecoder |
| | | import com.flightfeather.obd.socket.decoder.DataUnitDecoder |
| | | import com.flightfeather.obd.socket.eunm.ObdCommandUnit |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | class DataPackageDecoderImpl : DataPackageDecoder { |
| | | |
| | | private val dataUnitDecoder: DataUnitDecoder = DataUnitDecoderImpl() |
| | | |
| | | //fixme 2019.9.12: ç°å¨æä¸¤ç§æ
åµï¼1ï¼æ¥æ¶å°çå符串æ¯byte转ç åçï¼é£ä¹å
¶å°±è¡¨ç¤ºå符çASCIIç ï¼2ï¼å¦ä¸ç§å°±æ¯æ¥æ¶å°çæ¯è½¬ç åçå符串ãç®åå¾
å® |
| | | |
| | | override fun getHead(b: List<String>): String? { |
| | | return if (b.size >= 2) { |
| | | "${b[0]}${b[1]}" |
| | | } else { |
| | | null |
| | | } |
| | | } |
| | | |
| | | override fun getCommandUnit(b: List<String>): Int? = if (b.size >= 3) { |
| | | b[2].toIntOrNull(16) |
| | | } else { |
| | | null |
| | | } |
| | | |
| | | override fun getVinCode(b: List<String>): String? { |
| | | if (b.size < 20) return null |
| | | |
| | | //fixme åºè¯¥æ¯éè¦å°bå½ä½ASCIIç ï¼åè·å转æ¢åçå符串 |
| | | val s = StringBuilder() |
| | | |
| | | for (i in 3..19) { |
| | | s.append(b[i].toIntOrNull(16)?.toChar()) |
| | | } |
| | | |
| | | return s.toString() |
| | | } |
| | | |
| | | override fun getSoftwareVersion(b: List<String>): Int? = if (b.size >= 21) { |
| | | b[20].toIntOrNull(16) |
| | | } else { |
| | | null |
| | | } |
| | | |
| | | override fun getEncryptionWay(b: List<String>): Int? = if (b.size >= 21) { |
| | | b[21].toIntOrNull(16) |
| | | } else { |
| | | null |
| | | } |
| | | |
| | | override fun getDataLength(b: List<String>): Int { |
| | | if (b.size < 24) return 0 |
| | | |
| | | val hexNum = "${b[22]}${b[23]}" |
| | | |
| | | return hexNum.toIntOrNull(16) ?: 0 |
| | | } |
| | | |
| | | override fun getDataUnit(b: List<String>): List<DataUnit> { |
| | | if (getDataLength(b) == 0 || b.size < 26) { |
| | | return emptyList() |
| | | } |
| | | |
| | | val unit = mutableListOf<String>() |
| | | for (i in 24..b.size - 2) { |
| | | unit.add(b[i]) |
| | | } |
| | | dataUnitDecoder.run { |
| | | return when (getCommandUnit(b)) { |
| | | ObdCommandUnit.CarRegister.value -> getCarRegisterData(unit) |
| | | ObdCommandUnit.RealTimeData.value -> getRealTimeData(unit) |
| | | ObdCommandUnit.ReplacementData.value -> getReplacementData(unit) |
| | | ObdCommandUnit.CarLogOut.value -> getCarLogOutData(unit) |
| | | ObdCommandUnit.TimeCalibration.value -> getTimeCalibrationData(unit) |
| | | else -> emptyList() |
| | | } |
| | | } |
| | | } |
| | | |
| | | override fun getCheckCode(b: List<String>): Int? { |
| | | return if (b.isNotEmpty()) { |
| | | b[b.size - 1].toIntOrNull(16) |
| | | } else { |
| | | null |
| | | } |
| | | } |
| | | |
| | | override fun toStringList(msg: String): List<String> { |
| | | return msg.split(" ") |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder.impl |
| | | |
| | | import com.flightfeather.obd.socket.bean.* |
| | | import com.flightfeather.obd.socket.decoder.DataUnitDecoder |
| | | import com.flightfeather.obd.socket.decoder.RealTimeDataDecoder |
| | | import com.flightfeather.obd.socket.eunm.ObdDataType |
| | | import org.springframework.beans.factory.annotation.Autowired |
| | | import org.springframework.stereotype.Component |
| | | import java.lang.StringBuilder |
| | | import java.util.* |
| | | import javax.annotation.PostConstruct |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | */ |
| | | class DataUnitDecoderImpl : DataUnitDecoder { |
| | | |
| | | private var realTimeDataDecoder: RealTimeDataDecoder = RealTimeDataDecoderImpl() |
| | | |
| | | override fun getCarRegisterData(b: List<String>): List<CarRegisterData> { |
| | | val time = decodeDataTime(b) |
| | | |
| | | val serialNum = "${b[6]}${b[7]}".toInt(16) |
| | | |
| | | val simCode = StringBuilder() |
| | | for (i in 10 until b.size) { |
| | | simCode.append(b[i].toInt(16).toChar()) |
| | | } |
| | | |
| | | return mutableListOf(CarRegisterData(time, serialNum, simCode.toString())) |
| | | } |
| | | |
| | | override fun getRealTimeData(b: List<String>): List<RealTimeData> { |
| | | val time = decodeDataTime(b) |
| | | |
| | | //彿 æ³: èµ·å§åè为7 å¼å§ç2个åè表示 æµæ°´å· |
| | | // val serialNum = "${b[7]}${b[8]}".toInt(16) |
| | | |
| | | //䏿µ·æ³: èµ·å§åè为6 å¼å§ç2个åè表示 æµæ°´å· |
| | | val serialNum = "${b[6]}${b[7]}".toInt(16) |
| | | |
| | | val dataList = mutableListOf<String>().apply { addAll(b) } |
| | | //å å»å6使¶é´ |
| | | for (i in 0..5) { |
| | | if (dataList.isNotEmpty()) dataList.removeAt(0) |
| | | } |
| | | |
| | | //fixme 2019.9.15 ç®å两ç§è§åæå²çªï¼å¹¶ä¸åªä»æ°æ®å
å®¹æ æ³åºåãææ¶ä½¿ç¨ 彿 æ³ |
| | | /* |
| | | * å 廿µæ°´å·ï¼å¾å°ä¿¡æ¯æ å¿ä¸ä¿¡æ¯ä½çç»å |
| | | * (彿 æ³ï¼å»é¤å6使¶é´åï¼èµ·å§åè为1 å¼å§ç2个åè表示 æµæ°´å·) |
| | | */ |
| | | // if (dataList.size >= 2) dataList.removeAt(1) |
| | | // if (dataList.size >= 2) dataList.removeAt(1) |
| | | |
| | | /* |
| | | * å 廿µæ°´å·ï¼å¾å°ä¿¡æ¯æ å¿ä¸ä¿¡æ¯ä½çç»å |
| | | * (䏿µ·æ³ï¼å»é¤å6使¶é´åï¼èµ·å§åè为0 å¼å§ç2个åè表示 æµæ°´å·) |
| | | */ |
| | | if (dataList.isNotEmpty()) dataList.removeAt(0) |
| | | if (dataList.isNotEmpty()) dataList.removeAt(0) |
| | | |
| | | val resultList = mutableListOf<RealTimeData>() |
| | | |
| | | /* |
| | | * æç»å¾å°çæ°æ®ç»æä¸º [ ä¿¡æ¯ç±»åæ å¿, ä¿¡æ¯ä½, ...... , ä¿¡æ¯ç±»åæ å¿, ä¿¡æ¯ä½ ] |
| | | */ |
| | | while (dataList.isNotEmpty()) { |
| | | //å¾å°æåé¢çä¸ç»ä¿¡æ¯ç±»å+ä¿¡æ¯ä½å表 |
| | | val data = realTimeDataDecoder.getDataListByDataType(dataList) |
| | | if (data.isNotEmpty()) { |
| | | val r = when (data[0].toInt(16)) { |
| | | ObdDataType.ObdData.value -> realTimeDataDecoder.getObdData(time, serialNum, data) |
| | | ObdDataType.EngineDataFlow.value -> realTimeDataDecoder.getEngineDataFlow(time, serialNum, data) |
| | | ObdDataType.SupplementDataFlow.value -> realTimeDataDecoder.getSupplementDataFlow(time, serialNum, data) |
| | | else -> null |
| | | } |
| | | |
| | | if (r != null) { |
| | | resultList.add(r) |
| | | } |
| | | |
| | | for (i in 0 until data.size) { |
| | | if (dataList.isNotEmpty()) dataList.removeAt(0) |
| | | } |
| | | } |
| | | } |
| | | |
| | | return resultList |
| | | } |
| | | |
| | | override fun getReplacementData(b: List<String>): List<ReplacementData> = getRealTimeData(b) |
| | | |
| | | override fun getCarLogOutData(b: List<String>): List<CarLogOutData> { |
| | | val time = decodeDataTime(b) |
| | | |
| | | val serialNum = "${b[6]}${b[7]}".toInt(16) |
| | | |
| | | return mutableListOf(CarLogOutData(time, serialNum)) |
| | | } |
| | | |
| | | override fun getTimeCalibrationData(b: List<String>): List<TimeCalibrationData> = emptyList() |
| | | |
| | | override fun decodeDataTime(b: List<String>): Date? { |
| | | if (b.size < 6) { |
| | | return null |
| | | } |
| | | |
| | | val year = b[0].toInt(16) + 2000 |
| | | if (year < 2000 || year > 2099) return null |
| | | val month = b[1].toInt(16) |
| | | val day = b[2].toInt(16) |
| | | val hour = b[3].toInt(16) |
| | | val min = b[4].toInt(16) |
| | | val sec = b[5].toInt(16) |
| | | val cal = Calendar.getInstance().apply { |
| | | set(year, month - 1, day, hour, min, sec) |
| | | } |
| | | |
| | | return cal.time |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.decoder.impl |
| | | |
| | | import com.flightfeather.obd.socket.bean.EngineDataFlow |
| | | import com.flightfeather.obd.socket.bean.ObdData |
| | | import com.flightfeather.obd.socket.bean.SupplementDataFlow |
| | | import com.flightfeather.obd.socket.decoder.RealTimeDataDecoder |
| | | import com.flightfeather.obd.socket.eunm.ObdDataType |
| | | import org.springframework.stereotype.Component |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | */ |
| | | class RealTimeDataDecoderImpl : RealTimeDataDecoder { |
| | | override fun getObdData(time: Date?, serialNum: Int, b: List<String>): ObdData? { |
| | | val dataList = mutableListOf<String>().apply { addAll(b) } |
| | | if (b.isNotEmpty()) { |
| | | //å»é¤ ä¿¡æ¯ç±»åæ å¿ |
| | | dataList.removeAt(0) |
| | | } |
| | | if (dataList.size >= 96) { |
| | | val vin = StringBuilder() |
| | | for (i in 6..22) { |
| | | vin.append(dataList[i].toIntOrNull(16)?.toChar()) |
| | | } |
| | | val softwareCode = StringBuilder() |
| | | for (i in 23..40) { |
| | | softwareCode.append(dataList[i].toIntOrNull(16)?.toChar()) |
| | | } |
| | | val cvn = StringBuilder() |
| | | for (i in 41..58) { |
| | | cvn.append(dataList[i].toIntOrNull(16)?.toChar()) |
| | | } |
| | | val IUPR = StringBuilder() |
| | | for (i in 59..94) { |
| | | //todo 2019.9.15 å æä¸æ¸
æ¥æ ¼å¼ä¸å«ä¹ï¼ç´æ¥ä¿å |
| | | IUPR.append(dataList[i]) |
| | | } |
| | | var faultCodeNum = dataList[95].toIntOrNull() ?: 0 |
| | | val faultCode = StringBuilder() |
| | | if (faultCodeNum < 0 || faultCodeNum > 253) { |
| | | faultCodeNum = 254//ä»£è¡¨æ æ |
| | | } else { |
| | | for (i in 96..(95 + 4 * faultCodeNum)) { |
| | | faultCode.append(dataList[i]) |
| | | } |
| | | } |
| | | |
| | | return ObdData(time, serialNum).apply { |
| | | obdProtocol = dataList[0].toIntOrNull(16) |
| | | obdMil = dataList[1].toIntOrNull(16) |
| | | diagnosisSupportStatus = "${dataList[2]}${dataList[3]}".toIntOrNull(16)?.toString(2) |
| | | diagnosisReadyStatus = "${dataList[4]}${dataList[5]}".toIntOrNull(16)?.toString(2) |
| | | obdVin = vin.toString() |
| | | obdSoftwareCode = softwareCode.toString() |
| | | obdCvn = cvn.toString() |
| | | this.IUPR = IUPR.toString() |
| | | obdFaultCodeNum = faultCodeNum |
| | | obdFaultCode = faultCode.toString() |
| | | } |
| | | } else { |
| | | return null |
| | | } |
| | | } |
| | | |
| | | override fun getEngineDataFlow(time: Date?, serialNum: Int, b: List<String>): EngineDataFlow? { |
| | | val dataList = mutableListOf<String>().apply { addAll(b) } |
| | | if (b.isNotEmpty()) { |
| | | //å»é¤ ä¿¡æ¯ç±»åæ å¿ |
| | | dataList.removeAt(0) |
| | | } |
| | | |
| | | return if (dataList.size >= 37) { |
| | | EngineDataFlow(time, serialNum).apply { |
| | | obdSpeed = "${dataList[0]}${dataList[1]}".toIntOrNull(16)?.toDouble()?.times((1 / 256).toDouble()) |
| | | obdAirPressure = dataList[2].toIntOrNull(16)?.toDouble()?.times(0.5) |
| | | obdEngineTorque = dataList[3].toIntOrNull(16)?.minus(125)?.toDouble()?.div(100) |
| | | obdFrictionTorque = dataList[4].toIntOrNull(16)?.minus(125)?.toDouble()?.div(100) |
| | | obdEngineRpm = "${dataList[5]}${dataList[6]}".toIntOrNull(16)?.toDouble()?.times(0.125) |
| | | obdEngineFuelFlow = "${dataList[7]}${dataList[8]}".toIntOrNull(16)?.toDouble()?.times(0.05) |
| | | obdScrUpstreamNo = "${dataList[9]}${dataList[10]}".toIntOrNull(16)?.minus(200)?.toDouble()?.times(0.05) |
| | | obdScrDownstreamNo = "${dataList[11]}${dataList[12]}".toIntOrNull(16)?.minus(200)?.toDouble()?.times(0.05) |
| | | obdRemainReactant = dataList[13].toIntOrNull(16)?.toDouble()?.times(0.4)?.div(100) |
| | | obdAirInput = "${dataList[14]}${dataList[15]}".toIntOrNull(16)?.toDouble()?.times(0.05) |
| | | obdScrInputTemp = "${dataList[16]}${dataList[17]}".toIntOrNull(16)?.minus(273)?.toDouble()?.times(0.03125) |
| | | obdScrOutputTemp = "${dataList[18]}${dataList[19]}".toIntOrNull(16)?.minus(273)?.toDouble()?.times(0.03125) |
| | | obdDpf = "${dataList[20]}${dataList[21]}".toIntOrNull(16)?.toDouble()?.times(0.1) |
| | | obdEngineCoolantTemp = dataList[22].toIntOrNull(16)?.minus(40)?.toDouble() |
| | | obdFuelLevel = dataList[23].toIntOrNull(16)?.toDouble()?.times(0.4) |
| | | obdLocationStatus = dataList[24].toIntOrNull(16) |
| | | obdLong = "${dataList[25]}${dataList[26]}${dataList[27]}${dataList[28]}".toIntOrNull(16)?.toDouble()?.times(0.000001) |
| | | obdLat = "${dataList[29]}${dataList[30]}${dataList[31]}${dataList[32]}".toIntOrNull(16)?.toDouble()?.times(0.000001) |
| | | obdTotalMileage = "${dataList[33]}${dataList[34]}${dataList[35]}${dataList[36]}".toIntOrNull(16)?.toDouble()?.times(0.1) |
| | | } |
| | | } else { |
| | | null |
| | | } |
| | | } |
| | | |
| | | override fun getSupplementDataFlow(time: Date?, serialNum: Int, b: List<String>): SupplementDataFlow? { |
| | | val dataList = mutableListOf<String>().apply { addAll(b) } |
| | | if (b.isNotEmpty()) { |
| | | //å»é¤ ä¿¡æ¯ç±»åæ å¿ |
| | | dataList.removeAt(0) |
| | | } |
| | | |
| | | return if (dataList.size >= 17) { |
| | | SupplementDataFlow(time, serialNum).apply { |
| | | obdEngineTorqueMode = dataList[0].toIntOrNull(16) |
| | | obdAcceleratorPedal = dataList[1].toIntOrNull(16)?.toDouble()?.times(0.4)?.div(100) |
| | | obdTotalOilConsumption = "${dataList[2]}${dataList[3]}${dataList[4]}${dataList[5]}".toIntOrNull(16)?.toDouble()?.times(0.5) |
| | | obdUreaBoxTemp = dataList[6].toIntOrNull(16)?.toDouble()?.minus(40) |
| | | obdUreaVolume = "${dataList[7]}${dataList[8]}${dataList[9]}${dataList[10]}".toIntOrNull(16)?.toDouble()?.times(0.01) |
| | | obdTotalUreaConsume = "${dataList[11]}${dataList[12]}${dataList[13]}${dataList[14]}".toIntOrNull(16)?.toDouble() |
| | | obdDpfTemp = "${dataList[15]}${dataList[16]}".toIntOrNull(16)?.minus(273)?.toDouble()?.times(0.03125) |
| | | } |
| | | } else { |
| | | null |
| | | } |
| | | } |
| | | |
| | | override fun getDataListByDataType(list: List<String>): MutableList<String> { |
| | | if (list.isEmpty()) return mutableListOf() |
| | | |
| | | val resultList = mutableListOf<String>().apply { |
| | | //æ·»å ä¿¡æ¯ç±»åæ å¿ |
| | | add(list[0]) |
| | | } |
| | | |
| | | when (list[0].toIntOrNull(16)) { |
| | | ObdDataType.ObdData.value -> { |
| | | //ä»èµ·å§åè 1 å¼å§ï¼åºå®æ97个åèçæ°æ® |
| | | for (i in 1..96) { |
| | | resultList.add(list[i]) |
| | | } |
| | | |
| | | val faultCodeNum = list[96].toIntOrNull() ?: 0//æ
éç æ»æ° |
| | | //æ ¹æ®æ
éç æ»æ°ï¼æ¯ä¸ªæ
éç 4个åèï¼å¾å°æ
éç æ»åèæ° |
| | | if (faultCodeNum in 0..253) { |
| | | for (i in 97..(96 + faultCodeNum * 4)) { |
| | | resultList.add(list[i]) |
| | | } |
| | | } |
| | | } |
| | | ObdDataType.EngineDataFlow.value -> { |
| | | //ä»èµ·å§åè 1 å¼å§ï¼åºå®æ37个åèçæ°æ® |
| | | for (i in 1..37) { |
| | | resultList.add(list[i]) |
| | | } |
| | | } |
| | | ObdDataType.SupplementDataFlow.value -> { |
| | | //ä»èµ·å§åè 1 å¼å§ï¼åºå®æ17个åèçæ°æ® |
| | | for (i in 1..17) { |
| | | resultList.add(list[i]) |
| | | } |
| | | } |
| | | } |
| | | |
| | | return resultList |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.eunm |
| | | |
| | | /** |
| | | * obd å½ä»¤åå
|
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | enum class ObdCommandUnit constructor(val value: Int) { |
| | | CarRegister(1), |
| | | RealTimeData(2), |
| | | ReplacementData(3), |
| | | CarLogOut(4), |
| | | TimeCalibration(5) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd.socket.eunm |
| | | |
| | | import com.flightfeather.obd.socket.bean.* |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/15 |
| | | * 宿¶ä¿¡æ¯[RealTimeData]åè¡¥åä¿¡æ¯[ReplacementData]ä¸çæ°æ®ç±»å |
| | | * ç±»åç¼ç 说æ |
| | | * 0x01 OBD ä¿¡æ¯ |
| | | * 0x02 æ°æ®æµä¿¡æ¯ |
| | | * 0x03-0x7F é¢ç |
| | | * 0x80 è¡¥å
æ°æ®æµ |
| | | * 0x81~0xFE ç¨æ·èªå®ä¹ |
| | | */ |
| | | enum class ObdDataType constructor(val value: Int){ |
| | | ObdData(1), |
| | | EngineDataFlow(2), |
| | | SupplementDataFlow(128) |
| | | } |
| | |
| | | not-empty: false |
| | | identity: MYSQL |
| | | |
| | | #æ°æ®åºå页é
ç½® |
| | | pagehelper: |
| | | helperDialect: mysql |
| | | reasonable: true |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | 6个ä¼å
级ä»é«å°ä½ä¾æ¬¡ä¸ºï¼OFFãFATALãERRORãWARNãINFOãDEBUGãTRACEã ALLã |
| | | å¦æè®¾ç½®ä¼å
级为WARNï¼é£ä¹OFFãFATALãERRORãWARN 4个级å«çlogè½æ£å¸¸è¾åº |
| | | 设置为OFF 表示ä¸è®°å½log4j2æ¬èº«çæ¥å¿ï¼ |
| | | --> |
| | | |
| | | <!-- statusï¼ç¨æ¥æå®log4jæ¬èº«çæå°æ¥å¿çº§å«,monitorInterval:æå®log4jèªå¨éæ°é
ç½®ççæµé´éæ¶é´ --> |
| | | <configuration status="INFO" monitorInterval="30"> |
| | | <!-- èªå·±è®¾ç½®å±æ§ï¼åé¢éè¿${}æ¥è®¿é® --> |
| | | <properties> |
| | | <property name="LOG_HOME">../obdLogs</property> |
| | | </properties> |
| | | |
| | | <appenders> |
| | | <!--Appender 1. è¾åºå°Consoleæ§å¶å°ï¼æå®è¾åºæ ¼å¼åè¿æ»¤å¨ç级为INFO --> |
| | | <Console name="Console" target="SYSTEM_OUT"> |
| | | <!--ThresholdFilteræå®æ¥å¿æ¶æ¯çè¾åºæä½å±æ¬¡--> |
| | | <ThresholdFilter level="ALL" onMatch="ACCEPT" onMismatch="DENY"/> |
| | | <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> |
| | | </Console> |
| | | |
| | | <!--Appender 2. è¾åºå°æ»å¨ä¿åçæä»¶, 触åä¿åæ¥å¿æä»¶çæ¡ä»¶æ¯æ¥å¿æä»¶å¤§äº3KBï¼åªä¿åææ°ç10个æ¥å¿--> |
| | | <File name="allLog" fileName="${LOG_HOME}/all.log"> |
| | | <ThresholdFilter level="ALL" onMatch="ACCEPT" onMismatch="DENY"/> |
| | | <PatternLayout charset="UTF-8" pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> |
| | | </File> |
| | | |
| | | |
| | | <!--Appender 3. è¾åºå°æ»å¨ä¿åçæä»¶, 触åä¿åæ¥å¿æä»¶çæ¡ä»¶æ¯æ¥å¿æä»¶å¤§äº3KBï¼åªä¿åææ°ç10个æ¥å¿--> |
| | | <RollingFile name="debugLog" fileName="${LOG_HOME}/debug.log" filePattern="${LOG_HOME}/debug-%i.log"> |
| | | <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/> |
| | | <PatternLayout charset="UTF-8" pattern="[%-5level][%d{yyyy-MM-dd HH:mm:ss}][%F:%L] - %m%n"/> |
| | | <SizeBasedTriggeringPolicy size="3KB"/> |
| | | <!-- DefaultRolloverStrategy ä¸çåæ°maxï¼å¯ä»¥éå¶ SizeBasedTriggeringPolicyä¸sizeè¶
åºåï¼åªä¿çmaxä¸ªåæ¡£--> |
| | | <DefaultRolloverStrategy max="10"/> |
| | | </RollingFile> |
| | | |
| | | <!--Appender 4. è¾åºå°æ»å¨ä¿åçæä»¶, 触åä¿åæ¥å¿æä»¶çæ¡ä»¶æ¯æ¯åéç¬¬ä¸æ¬¡çæ¥å¿äºä»¶ãERRORæ¥å¿æ¯æåéäº§çæ¥å¿ --> |
| | | <RollingFile name="errorLog" fileName="${LOG_HOME}/error.log" filePattern="${LOG_HOME}/error-%d{yyyy-MM-dd_HH-mm}.log"> |
| | | <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> |
| | | <PatternLayout charset="UTF-8" pattern="[%-5level][%d{yyyy-MM-dd HH:mm:ss}][%C:%F:%L] - %m%n"/> |
| | | <TimeBasedTriggeringPolicy/> |
| | | </RollingFile> |
| | | |
| | | <RollingFile name="RollingFile" fileName="${LOG_HOME}/rar.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{MM-dd-yyyy}-%i.log.gz"> |
| | | <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> |
| | | <!--æ¥å¿æä»¶æå¤§å¼ 第äºå¤©å缩--> |
| | | <Policies> |
| | | <TimeBasedTriggeringPolicy/> |
| | | <SizeBasedTriggeringPolicy size="10 MB"/> |
| | | </Policies> |
| | | </RollingFile> |
| | | |
| | | |
| | | </appenders> |
| | | <!--root é»è®¤å è½½--> |
| | | <loggers> |
| | | <root level="DEBUG"> |
| | | <appender-ref ref="Console"/> |
| | | <!--<appender-ref ref="allLog"/>--> |
| | | <appender-ref ref="debugLog"/> |
| | | <appender-ref ref="errorLog"/> |
| | | <appender-ref ref="RollingFile"/> |
| | | </root> |
| | | </loggers> |
| | | </configuration> |
| | |
| | | import com.google.gson.Gson |
| | | import org.junit.Test |
| | | import org.junit.runner.RunWith |
| | | import org.slf4j.LoggerFactory |
| | | import org.springframework.beans.factory.annotation.Autowired |
| | | import org.springframework.boot.test.context.SpringBootTest |
| | | import org.springframework.test.context.junit4.SpringRunner |
| | |
| | | println(map.cmdCode) |
| | | } |
| | | |
| | | @Test |
| | | fun logTest() { |
| | | val log = LoggerFactory.getLogger(javaClass) |
| | | log.trace("trace") |
| | | log.debug("debug") |
| | | log.warn("warn") |
| | | log.info("info") |
| | | log.error("error") |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.flightfeather.obd |
| | | |
| | | import org.junit.Test |
| | | import java.nio.charset.Charset |
| | | import java.text.SimpleDateFormat |
| | | import java.util.* |
| | | |
| | | /** |
| | | * @author riku |
| | | * Date: 2019/9/12 |
| | | */ |
| | | class Test { |
| | | |
| | | @Test |
| | | fun foo1() { |
| | | val b = ByteArray(20) {8} |
| | | println(b[18]) |
| | | } |
| | | |
| | | @Test |
| | | fun foo2() { |
| | | val b = ByteArray(1){97} |
| | | val s = "a" |
| | | println() |
| | | } |
| | | |
| | | @Test |
| | | fun foo3() { |
| | | val hexNum = "ff" |
| | | val length = hexNum.toInt(16) |
| | | println(length) |
| | | } |
| | | |
| | | @Test |
| | | fun foo4() { |
| | | val h = "0101" |
| | | val byte = 0xff |
| | | val b = h.toInt(16) |
| | | println(b) |
| | | } |
| | | |
| | | @Test |
| | | fun foo5() { |
| | | val s = "23 23 30 30 30 30 30 35 33 31 36 30 38 30 31 30 35 33 36" |
| | | val sb = StringBuilder() |
| | | val ascii = s.split(" ") |
| | | ascii.forEach { |
| | | sb.append(it.toIntOrNull(16)?.toChar()) |
| | | } |
| | | println(sb.toString()) |
| | | } |
| | | |
| | | @Test |
| | | fun foo6() { |
| | | val cal = Calendar.getInstance().apply { |
| | | set(2019, 9, 15, 23, 16, 59) |
| | | } |
| | | |
| | | println(SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.time)) |
| | | } |
| | | |
| | | @Test |
| | | fun foo7() { |
| | | val a = "0AAF".toIntOrNull(16)?.toString(2) |
| | | println(a) |
| | | } |
| | | |
| | | @Test |
| | | fun foo8() { |
| | | val byte = ByteArray(2) |
| | | byte[0] = 0x23 |
| | | byte[1] = 0x23 |
| | | |
| | | byte[0].toString(16) |
| | | } |
| | | |
| | | @Test |
| | | fun foo9() { |
| | | val b = 128.toByte() |
| | | var a = 0 |
| | | if (b < 0) { |
| | | a = b + 256 |
| | | } else { |
| | | a = b.toInt() |
| | | } |
| | | println(b.toString(16)) |
| | | } |
| | | } |