src/main/kotlin/com/flightfeather/uav/UAVApplication.kt
@@ -1,6 +1,9 @@ package com.flightfeather.uav import com.flightfeather.uav.socket.UnderwaySocketServer import com.flightfeather.uav.socket.processor.ElectricProcessor import com.flightfeather.uav.socket.processor.UnderwayProcessor import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.ApplicationRunner import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -9,9 +12,18 @@ @SpringBootApplication class UAVApplication{ @Autowired lateinit var underwayProcessor: UnderwayProcessor @Autowired lateinit var electricProcessor: ElectricProcessor private val socketServer = UnderwaySocketServer() @Bean fun runner() = ApplicationRunner{ UnderwaySocketServer().startServer(9030) socketServer.startUnderwayServer(9030, underwayProcessor) socketServer.startElectricServer(9009, electricProcessor) } } src/main/kotlin/com/flightfeather/uav/common/utils/CommonUtil.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.flightfeather.uav.common.utils /** * @author riku * Date: 2020/9/10 */ object CommonUtil { fun getSubStr(strData: String, startIndexStr: String, endIndexStr: String): String? { try { val startIndex = strData.indexOf(startIndexStr) val endIndex = strData.indexOf(endIndexStr, startIndex + startIndexStr.length) return strData.substring(startIndex, endIndex) } catch (e: Exception) { // println("åæ®µ[$startIndexStr]æ æ³è·å") } return null } } src/main/kotlin/com/flightfeather/uav/common/utils/DateUtil.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,765 @@ package com.flightfeather.uav.common.utils import java.sql.Timestamp import java.text.ParsePosition import java.text.SimpleDateFormat import java.util.* class DateUtil { private val threadLocal = ThreadLocal<SimpleDateFormat>() private val `object` = Any() /** * è·åSimpleDateFormat * @param pattern æ¥ææ ¼å¼ * @return SimpleDateFormat对象 * @throws RuntimeException å¼å¸¸ï¼éæ³æ¥ææ ¼å¼ */ @Throws(RuntimeException::class) private fun getDateFormat(pattern: String): SimpleDateFormat { var dateFormat: SimpleDateFormat? = threadLocal.get() if (dateFormat == null) { synchronized(`object`) { if (dateFormat == null) { dateFormat = SimpleDateFormat(pattern) dateFormat!!.isLenient = false threadLocal.set(dateFormat) } } } dateFormat!!.applyPattern(pattern) return dateFormat as SimpleDateFormat } /** * è·åæ¥æä¸çææ°å¼ãå¦è·åæä»½ * @param date æ¥æ * @param dateType æ¥ææ ¼å¼ * @return æ°å¼ */ private fun getInteger(date: Date?, dateType: Int): Int { var num = 0 val calendar = Calendar.getInstance() if (date != null) { calendar.time = date num = calendar.get(dateType) } return num } /** * å¢å æ¥æä¸æç±»åçææ°å¼ãå¦å¢å æ¥æ * @param date æ¥æå符串 * @param dateType ç±»å * @param amount æ°å¼ * @return 计ç®åæ¥æå符串 */ private fun addInteger(date: String, dateType: Int, amount: Int): String? { var dateString: String? = null val dateStyle = getDateStyle(date) if (dateStyle != null) { var myDate = StringToDate(date, dateStyle) myDate = addInteger(myDate, dateType, amount) dateString = DateToString(myDate, dateStyle) } return dateString } /** * å¢å æ¥æä¸æç±»åçææ°å¼ãå¦å¢å æ¥æ * @param date æ¥æ * @param dateType ç±»å * @param amount æ°å¼ * @return 计ç®åæ¥æ */ private fun addInteger(date: Date?, dateType: Int, amount: Int): Date? { var myDate: Date? = null if (date != null) { val calendar = Calendar.getInstance() calendar.time = date calendar.add(dateType, amount) myDate = calendar.time } return myDate } /** * è·åç²¾ç¡®çæ¥æ * @param timestamps æ¶é´longéå * @return æ¥æ */ private fun getAccurateDate(timestamps: List<Long>?): Date? { var date: Date? = null var timestamp: Long = 0 val map = HashMap<Long, LongArray>() val absoluteValues = ArrayList<Long>() if (timestamps != null && timestamps.size > 0) { if (timestamps.size > 1) { for (i in timestamps.indices) { for (j in i + 1 until timestamps.size) { val absoluteValue = Math.abs(timestamps[i] - timestamps[j]) absoluteValues.add(absoluteValue) val timestampTmp = longArrayOf(timestamps[i], timestamps[j]) map.put(absoluteValue, timestampTmp) } } // æå¯è½æç¸ççæ åµãå¦2012-11å2012-11-01ãæ¶é´æ³æ¯ç¸ççãæ¤æ¶minAbsoluteValue为0 // å æ¤ä¸è½å°minAbsoluteValueåé»è®¤å¼0 var minAbsoluteValue: Long = -1 if (!absoluteValues.isEmpty()) { minAbsoluteValue = absoluteValues[0] for (i in 1 until absoluteValues.size) { if (minAbsoluteValue > absoluteValues[i]) { minAbsoluteValue = absoluteValues[i] } } } if (!minAbsoluteValue.equals(-1)) { val timestampsLastTmp = map[minAbsoluteValue] val dateOne = timestampsLastTmp?.get(0) val dateTwo = timestampsLastTmp?.get(1) if (absoluteValues.size > 1) { timestamp = if (Math.abs(dateOne!!) > Math.abs(dateTwo!!)) dateOne else dateTwo } } } else { timestamp = timestamps[0] } } if (timestamp != 0L) { date = Date(timestamp) } return date } /** * 夿å符串æ¯å¦ä¸ºæ¥æå符串 * @param date æ¥æå符串 * @return true or false */ fun isDate(date: String?): Boolean { var isDate = false if (date != null) { if (getDateStyle(date) != null) { isDate = true } } return isDate } /** * è·åæ¥æåç¬¦ä¸²çæ¥æé£æ ¼ã失æè¿ånullã * @param date æ¥æå符串 * @return æ¥æé£æ ¼ */ fun getDateStyle(date: String?): DateStyle? { var dateStyle: DateStyle? = null val map = HashMap<Long, DateStyle>() val timestamps = ArrayList<Long>() for (style in DateStyle.values()) { if (style.isShowOnly) { continue } var dateTmp: Date? = null if (date != null) { try { val pos = ParsePosition(0) dateTmp = getDateFormat(style.value).parse(date, pos) if (pos.index != date.length) { dateTmp = null } } catch (e: Exception) { } } if (dateTmp != null) { timestamps.add(dateTmp.time) map.put(dateTmp.time, style) } } val accurateDate = getAccurateDate(timestamps) if (accurateDate != null) { dateStyle = map[accurateDate.time] } return dateStyle } /** * Timestamp -> String * */ fun timestampToString(ts: Timestamp, format: String): String { var tsStr = "" val sdf = SimpleDateFormat(format) try { //æ¹æ³ä¸ tsStr = sdf.format(ts) } catch (e: Exception) { e.printStackTrace() } return tsStr } /** * å°æ¥æå符串转åä¸ºæ¥æã失败è¿ånullã * @param date æ¥æå符串 * @return æ¥æ */ fun StringToDate(date: String): Date? { val dateStyle = getDateStyle(date) return StringToDate(date, dateStyle) } /** * å°æ¥æå符串转åä¸ºæ¥æã失败è¿ånullã * @param date æ¥æå符串 * @param pattern æ¥ææ ¼å¼ * @return æ¥æ */ fun StringToDate(date: String?, pattern: String): Date? { var myDate: Date? = null if (date != null) { try { myDate = getDateFormat(pattern).parse(date) } catch (e: Exception) { } } return myDate } /** * å°æ¥æå符串转åä¸ºæ¥æã失败è¿ånullã * @param date æ¥æå符串 * @param dateStyle æ¥æé£æ ¼ * @return æ¥æ */ fun StringToDate(date: String?, dateStyle: DateStyle?): Date? { var myDate: Date? = null if (dateStyle != null) { myDate = StringToDate(date, dateStyle.value) } return myDate } /** * å°æ¥æå符串转åä¸ºæ¥æã失败è¿ånullã * @param millisecondStamp æ¥ææ¶é´æ³ * @param dateStyle æ¥æé£æ ¼ * @return æ¥æ */ fun LongToString(millisecondStamp: Long?, dateStyle: DateStyle?): String? { var dateString: String? = null if (dateStyle != null) { dateString = DateToString(Date(millisecondStamp!!), dateStyle.value) } return dateString } /** * å°æ¥æè½¬åä¸ºæ¥æå符串ã失败è¿ånullã * @param date æ¥æ * @param pattern æ¥ææ ¼å¼ * @return æ¥æå符串 */ fun DateToString(date: Date?, pattern: String): String? { var dateString: String? = null if (date != null) { try { dateString = getDateFormat(pattern).format(date) } catch (e: Exception) { } } return dateString } /** * å°æ¥æè½¬åä¸ºæ¥æå符串ã失败è¿ånullã * @param date æ¥æ * @param dateStyle æ¥æé£æ ¼ * @return æ¥æå符串 */ fun DateToString(date: Date?, dateStyle: DateStyle?): String? { var dateString: String? = null if (dateStyle != null) { dateString = DateToString(date, dateStyle.value) } return dateString } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param newPattern æ°æ¥ææ ¼å¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, newPattern: String): String? { val oldDateStyle = getDateStyle(date) return StringToString(date, oldDateStyle, newPattern) } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param newDateStyle æ°æ¥æé£æ ¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, newDateStyle: DateStyle): String? { val oldDateStyle = getDateStyle(date) return StringToString(date, oldDateStyle, newDateStyle) } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param olddPattern æ§æ¥ææ ¼å¼ * @param newPattern æ°æ¥ææ ¼å¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, olddPattern: String, newPattern: String): String? { return DateToString(StringToDate(date, olddPattern), newPattern) } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param olddDteStyle æ§æ¥æé£æ ¼ * @param newParttern æ°æ¥ææ ¼å¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, olddDteStyle: DateStyle?, newParttern: String): String? { var dateString: String? = null if (olddDteStyle != null) { dateString = StringToString(date, olddDteStyle.value, newParttern) } return dateString } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param olddPattern æ§æ¥ææ ¼å¼ * @param newDateStyle æ°æ¥æé£æ ¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, olddPattern: String, newDateStyle: DateStyle?): String? { var dateString: String? = null if (newDateStyle != null) { dateString = StringToString(date, olddPattern, newDateStyle.value) } return dateString } /** * å°æ¥æå符串转å为å¦ä¸æ¥æå符串ã失败è¿ånullã * @param date æ§æ¥æå符串 * @param olddDteStyle æ§æ¥æé£æ ¼ * @param newDateStyle æ°æ¥æé£æ ¼ * @return æ°æ¥æå符串 */ fun StringToString(date: String, olddDteStyle: DateStyle?, newDateStyle: DateStyle?): String? { var dateString: String? = null if (olddDteStyle != null && newDateStyle != null) { dateString = StringToString(date, olddDteStyle.value, newDateStyle.value) } return dateString } /** * å¢å æ¥æç年份ã失败è¿ånullã * @param date æ¥æ * @param yearAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å 年份åçæ¥æå符串 */ fun addYear(date: String, yearAmount: Int): String? { return addInteger(date, Calendar.YEAR, yearAmount) } /** * å¢å æ¥æç年份ã失败è¿ånullã * @param date æ¥æ * @param yearAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å 年份åçæ¥æ */ fun addYear(date: Date, yearAmount: Int): Date? { return addInteger(date, Calendar.YEAR, yearAmount) } /** * å¢å æ¥æçæä»½ã失败è¿ånullã * @param date æ¥æ * @param monthAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å æä»½åçæ¥æå符串 */ fun addMonth(date: String, monthAmount: Int): String? { return addInteger(date, Calendar.MONTH, monthAmount) } /** * å¢å æ¥æçæä»½ã失败è¿ånullã * @param date æ¥æ * @param monthAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å æä»½åçæ¥æ */ fun addMonth(date: Date, monthAmount: Int): Date? { return addInteger(date, Calendar.MONTH, monthAmount) } /** * å¢å æ¥æç天æ°ã失败è¿ånullã * @param date æ¥æå符串 * @param dayAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å 天æ°åçæ¥æå符串 */ fun addDay(date: String, dayAmount: Int): String? { return addInteger(date, Calendar.DATE, dayAmount) } /** * å¢å æ¥æç天æ°ã失败è¿ånullã * @param date æ¥æ * @param dayAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å 天æ°åçæ¥æ */ fun addDay(date: Date, dayAmount: Int): Date? { return addInteger(date, Calendar.DATE, dayAmount) } /** * å¢å æ¥æçå°æ¶ã失败è¿ånullã * @param date æ¥æå符串 * @param hourAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å å°æ¶åçæ¥æå符串 */ fun addHour(date: String, hourAmount: Int): String? { return addInteger(date, Calendar.HOUR_OF_DAY, hourAmount) } /** * å¢å æ¥æçå°æ¶ã失败è¿ånullã * @param date æ¥æ * @param hourAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å å°æ¶åçæ¥æ */ fun addHour(date: Date, hourAmount: Int): Date? { return addInteger(date, Calendar.HOUR_OF_DAY, hourAmount) } /** * å¢å æ¥æçåéã失败è¿ånullã * @param date æ¥æå符串 * @param minuteAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å åéåçæ¥æå符串 */ fun addMinute(date: String, minuteAmount: Int): String? { return addInteger(date, Calendar.MINUTE, minuteAmount) } /** * å¢å æ¥æçåéã失败è¿ånullã * @param date æ¥æ * @param minuteAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å åéåçæ¥æ */ fun addMinute(date: Date, minuteAmount: Int): Date? { return addInteger(date, Calendar.MINUTE, minuteAmount) } /** * å¢å æ¥æçç§éã失败è¿ånullã * @param date æ¥æå符串 * @param secondAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å ç§éåçæ¥æå符串 */ fun addSecond(date: String, secondAmount: Int): String? { return addInteger(date, Calendar.SECOND, secondAmount) } /** * å¢å æ¥æçç§éã失败è¿ånullã * @param date æ¥æ * @param secondAmount å¢å æ°éãå¯ä¸ºè´æ° * @return å¢å ç§éåçæ¥æ */ fun addSecond(date: Date, secondAmount: Int): Date? { return addInteger(date, Calendar.SECOND, secondAmount) } /** * è·åæ¥æç年份ã失败è¿å0ã * @param date æ¥æå符串 * @return 年份 */ fun getYear(date: String): Int { return getYear(StringToDate(date)) } /** * è·åæ¥æç年份ã失败è¿å0ã * @param date æ¥æ * @return 年份 */ fun getYear(date: Date?): Int { return getInteger(date, Calendar.YEAR) } /** * è·åæ¥æçæä»½ã失败è¿å0ã * @param date æ¥æå符串 * @return æä»½ */ fun getMonth(date: String): Int { return getMonth(StringToDate(date)) } /** * è·åæ¥æçæä»½ã失败è¿å0ã * @param date æ¥æ * @return æä»½ */ fun getMonth(date: Date?): Int { return getInteger(date, Calendar.MONTH) + 1 } /** * è·åæ¥æç天æ°ã失败è¿å0ã * @param date æ¥æå符串 * @return 天 */ fun getDay(date: String): Int { return getDay(StringToDate(date)) } /** * è·åæ¥æç天æ°ã失败è¿å0ã * @param date æ¥æ * @return 天 */ fun getDay(date: Date?): Int { return getInteger(date, Calendar.DATE) } /** * è·åæ¥æçå°æ¶ã失败è¿å0ã * @param date æ¥æå符串 * @return å°æ¶ */ fun getHour(date: String): Int { return getHour(StringToDate(date)) } /** * è·åæ¥æçå°æ¶ã失败è¿å0ã * @param date æ¥æ * @return å°æ¶ */ fun getHour(date: Date?): Int { return getInteger(date, Calendar.HOUR_OF_DAY) } /** * è·åæ¥æçåéã失败è¿å0ã * @param date æ¥æå符串 * @return åé */ fun getMinute(date: String): Int { return getMinute(StringToDate(date)) } /** * è·åæ¥æçåéã失败è¿å0ã * @param date æ¥æ * @return åé */ fun getMinute(date: Date?): Int { return getInteger(date, Calendar.MINUTE) } /** * è·åæ¥æçç§éã失败è¿å0ã * @param date æ¥æå符串 * @return ç§é */ fun getSecond(date: String): Int { return getSecond(StringToDate(date)) } /** * è·åæ¥æçç§éã失败è¿å0ã * @param date æ¥æ * @return ç§é */ fun getSecond(date: Date?): Int { return getInteger(date, Calendar.SECOND) } /** * è·åæ¥æ ãé»è®¤yyyy-MM-ddæ ¼å¼ã失败è¿ånullã * @param date æ¥æå符串 * @return æ¥æ */ fun getDate(date: String): String? { return StringToString(date, DateStyle.YYYY_MM_DD) } /** * è·åæ¥æãé»è®¤yyyy-MM-ddæ ¼å¼ã失败è¿ånullã * @param date æ¥æ * @return æ¥æ */ fun getDate(date: Date?): String? { return DateToString(date, DateStyle.YYYY_MM_DD) } /** * è·åæ¥æçæ¶é´ãé»è®¤HH:mm:ssæ ¼å¼ã失败è¿ånullã * @param date æ¥æå符串 * @return æ¶é´ */ fun getTime(date: String): String? { return StringToString(date, DateStyle.HH_MM_SS) } /** * è·åæ¥æçæ¶é´ãé»è®¤HH:mm:ssæ ¼å¼ã失败è¿ånullã * @param date æ¥æ * @return æ¶é´ */ fun getTime(date: Date): String? { return DateToString(date, DateStyle.HH_MM_SS) } /** * è·åæ¥æçææã失败è¿ånullã * @param date æ¥æå符串 * @return ææ */ fun getWeek(date: String): Week? { var week: Week? = null val dateStyle = getDateStyle(date) if (dateStyle != null) { val myDate = StringToDate(date, dateStyle) week = getWeek(myDate) } return week } /** * è·åæ¥æçææã失败è¿ånullã * @param date æ¥æ * @return ææ */ fun getWeek(date: Date?): Week? { var week: Week? = null val calendar = Calendar.getInstance() calendar.time = date!! val weekNumber = calendar.get(Calendar.DAY_OF_WEEK) - 1 when (weekNumber) { 0 -> week = Week.SUNDAY 1 -> week = Week.MONDAY 2 -> week = Week.TUESDAY 3 -> week = Week.WEDNESDAY 4 -> week = Week.THURSDAY 5 -> week = Week.FRIDAY 6 -> week = Week.SATURDAY } return week } /** * è·åä¸¤ä¸ªæ¥æç¸å·®çå¤©æ° * @param date æ¥æå符串 * @param otherDate å¦ä¸ä¸ªæ¥æå符串 * @return ç¸å·®å¤©æ°ãå¦æå¤±è´¥åè¿å-1 */ fun getIntervalDays(date: String, otherDate: String): Int { return getIntervalDays(StringToDate(date), StringToDate(otherDate)) } /** * @param date æ¥æ * @param otherDate å¦ä¸ä¸ªæ¥æ * @return ç¸å·®å¤©æ°ãå¦æå¤±è´¥åè¿å-1 */ fun getIntervalDays(date: Date?, otherDate: Date?): Int { var num = -1 val dateTmp = StringToDate(getDate(date), DateStyle.YYYY_MM_DD) val otherDateTmp = StringToDate(getDate(otherDate), DateStyle.YYYY_MM_DD) if (dateTmp != null && otherDateTmp != null) { val time = Math.abs(dateTmp.time - otherDateTmp.time) num = (time / (24 * 60 * 60 * 1000)).toInt() } return num } enum class DateStyle private constructor(val value: String, val isShowOnly: Boolean) { YYYYMMDD("yyyyMMdd", false), YYYY_MM("yyyy-MM", false), YYYY_MM_DD("yyyy-MM-dd", false), YYYY_MM_DD_HH("yyyyMMddHH", false), YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm", false), YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss", false), YYYY_MM_EN("yyyy/MM", false), YYYY_MM_DD_EN("yyyy/MM/dd", false), YYYY_MM_DD_HH_MM_EN("yyyy/MM/dd HH:mm", false), YYYY_MM_DD_HH_MM_SS_EN("yyyy/MM/dd HH:mm:ss", false), YYYY_MM_CN("yyyyå¹´MMæ", false), YYYY_MM_DD_CN("yyyyå¹´MMæddæ¥", false), YYYY_MM_DD_HH_MM_CN("yyyyå¹´MMæddæ¥ HH:mm", false), YYYY_MM_DD_HH_MM_SS_CN("yyyyå¹´MMæddæ¥ HH:mm:ss", false), HH_MM("HH:mm", true), HH_MM_SS("HH:mm:ss", true), MM_DD("MM-dd", true), MM_DD_HH_MM("MM-dd HH:mm", true), MM_DD_HH_MM_SS("MM-dd HH:mm:ss", true), MM_DD_EN("MM/dd", true), MM_DD_HH_MM_EN("MM/dd HH:mm", true), MM_DD_HH_MM_SS_EN("MM/dd HH:mm:ss", true), MM_DD_CN("MMæddæ¥", true), MM_DD_HH_MM_CN("MMæddæ¥ HH:mm", true), MM_DD_HH_MM_SS_CN("MMæddæ¥ HH:mm:ss", true) } enum class Week private constructor(name_cn: String, name_en: String, name_enShort: String, number: Int) { MONDAY("ææä¸", "Monday", "Mon.", 1), TUESDAY("ææäº", "Tuesday", "Tues.", 2), WEDNESDAY("ææä¸", "Wednesday", "Wed.", 3), THURSDAY("ææå", "Thursday", "Thur.", 4), FRIDAY("ææäº", "Friday", "Fri.", 5), SATURDAY("ææå ", "Saturday", "Sat.", 6), SUNDAY("æææ¥", "Sunday", "Sun.", 7); var chineseName: String internal set var aname: String internal set var shortName: String internal set var number: Int = 0 internal set init { this.chineseName = name_cn this.aname = name_en this.shortName = name_enShort this.number = number } } } src/main/kotlin/com/flightfeather/uav/domain/entity/ElectricMinuteValue.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,229 @@ package com.flightfeather.uav.domain.entity; import java.util.Date; import javax.persistence.*; @Table(name = "el_minutevalue") public class ElectricMinuteValue { @Id @Column(name = "MV_ID") private Integer mvId; @Column(name = "MV_Stat_Code") private String mvStatCode; @Column(name = "MV_Create_Time") private Date mvCreateTime; @Column(name = "MV_Data_Time") private Date mvDataTime; @Column(name = "MV_Electricity_A") private Double mvElectricityA; @Column(name = "MV_Electricity_B") private Double mvElectricityB; @Column(name = "MV_Electricity_C") private Double mvElectricityC; @Column(name = "MV_Voltage_A") private Double mvVoltageA; @Column(name = "MV_Voltage_B") private Double mvVoltageB; @Column(name = "MV_Voltage_C") private Double mvVoltageC; @Column(name = "MV_Power_A") private Double mvPowerA; @Column(name = "MV_Power_B") private Double mvPowerB; @Column(name = "MV_Power_C") private Double mvPowerC; /** * @return MV_ID */ public Integer getMvId() { return mvId; } /** * @param mvId */ public void setMvId(Integer mvId) { this.mvId = mvId; } /** * @return MV_Stat_Code */ public String getMvStatCode() { return mvStatCode; } /** * @param mvStatCode */ public void setMvStatCode(String mvStatCode) { this.mvStatCode = mvStatCode == null ? null : mvStatCode.trim(); } /** * @return MV_Create_Time */ public Date getMvCreateTime() { return mvCreateTime; } /** * @param mvCreateTime */ public void setMvCreateTime(Date mvCreateTime) { this.mvCreateTime = mvCreateTime; } /** * @return MV_Data_Time */ public Date getMvDataTime() { return mvDataTime; } /** * @param mvDataTime */ public void setMvDataTime(Date mvDataTime) { this.mvDataTime = mvDataTime; } /** * @return MV_Electricity_A */ public Double getMvElectricityA() { return mvElectricityA; } /** * @param mvElectricityA */ public void setMvElectricityA(Double mvElectricityA) { this.mvElectricityA = mvElectricityA; } /** * @return MV_Electricity_B */ public Double getMvElectricityB() { return mvElectricityB; } /** * @param mvElectricityB */ public void setMvElectricityB(Double mvElectricityB) { this.mvElectricityB = mvElectricityB; } /** * @return MV_Electricity_C */ public Double getMvElectricityC() { return mvElectricityC; } /** * @param mvElectricityC */ public void setMvElectricityC(Double mvElectricityC) { this.mvElectricityC = mvElectricityC; } /** * @return MV_Voltage_A */ public Double getMvVoltageA() { return mvVoltageA; } /** * @param mvVoltageA */ public void setMvVoltageA(Double mvVoltageA) { this.mvVoltageA = mvVoltageA; } /** * @return MV_Voltage_B */ public Double getMvVoltageB() { return mvVoltageB; } /** * @param mvVoltageB */ public void setMvVoltageB(Double mvVoltageB) { this.mvVoltageB = mvVoltageB; } /** * @return MV_Voltage_C */ public Double getMvVoltageC() { return mvVoltageC; } /** * @param mvVoltageC */ public void setMvVoltageC(Double mvVoltageC) { this.mvVoltageC = mvVoltageC; } /** * @return MV_Power_A */ public Double getMvPowerA() { return mvPowerA; } /** * @param mvPowerA */ public void setMvPowerA(Double mvPowerA) { this.mvPowerA = mvPowerA; } /** * @return MV_Power_B */ public Double getMvPowerB() { return mvPowerB; } /** * @param mvPowerB */ public void setMvPowerB(Double mvPowerB) { this.mvPowerB = mvPowerB; } /** * @return MV_Power_C */ public Double getMvPowerC() { return mvPowerC; } /** * @param mvPowerC */ public void setMvPowerC(Double mvPowerC) { this.mvPowerC = mvPowerC; } } src/main/kotlin/com/flightfeather/uav/domain/mapper/ElectricMinuteValueMapper.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,8 @@ package com.flightfeather.uav.domain.mapper import com.flightfeather.uav.domain.MyMapper import com.flightfeather.uav.domain.entity.ElectricMinuteValue import org.apache.ibatis.annotations.Mapper @Mapper interface ElectricMinuteValueMapper : MyMapper<ElectricMinuteValue?> src/main/kotlin/com/flightfeather/uav/repository/ElectricRepository.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,8 @@ package com.flightfeather.uav.repository import com.flightfeather.uav.socket.bean.ElectricMessage interface ElectricRepository { fun saveData(electricMessage: ElectricMessage): Int } src/main/kotlin/com/flightfeather/uav/repository/impl/ElectricDapImpl.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,30 @@ package com.flightfeather.uav.repository.impl import com.flightfeather.uav.domain.entity.ElectricMinuteValue import com.flightfeather.uav.domain.mapper.ElectricMinuteValueMapper import com.flightfeather.uav.repository.ElectricRepository import com.flightfeather.uav.socket.bean.ElectricMessage import org.springframework.stereotype.Repository import java.util.* @Repository class ElectricDapImpl(val electricMinuteValueMapper: ElectricMinuteValueMapper) : ElectricRepository { override fun saveData(electricMessage: ElectricMessage): Int { val minuteValue = ElectricMinuteValue().apply { mvStatCode = electricMessage.mn mvCreateTime = Date() mvDataTime = electricMessage.dataTime mvElectricityA = electricMessage.electricityA mvElectricityB = electricMessage.electricityB mvElectricityC = electricMessage.electricityC mvVoltageA = electricMessage.voltageA mvVoltageB = electricMessage.voltageB mvVoltageC = electricMessage.voltageC mvPowerA = electricMessage.powerA mvPowerB = electricMessage.powerB mvPowerC = electricMessage.powerC } return electricMinuteValueMapper.insert(minuteValue) } } src/main/kotlin/com/flightfeather/uav/socket/DeviceSession.kt
@@ -12,9 +12,10 @@ class DeviceSession { companion object{ private const val DEFAULT_DEVICE = "default_device" } private val deviceMap = ConcurrentHashMap<String, ChannelHandlerContext?>() private val typeMap = ConcurrentHashMap<String, List<AirTypeData>>() private const val DEFAULT_DEVICE = "default_device" fun saveDevice(deviceCode: String?, channel: ChannelHandlerContext?) { deviceCode?.let { @@ -42,7 +43,6 @@ deviceCode == null -> typeMap[DEFAULT_DEVICE] typeMap.containsKey(deviceCode) -> typeMap[deviceCode] else -> null } } } } src/main/kotlin/com/flightfeather/uav/socket/ServerHandler.kt
@@ -1,5 +1,6 @@ package com.flightfeather.uav.socket import com.flightfeather.uav.socket.processor.BaseProcessor import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelInboundHandlerAdapter import io.netty.util.AttributeKey @@ -8,38 +9,34 @@ import java.util.* class ServerHandler : ChannelInboundHandlerAdapter() { companion object { private const val TAG = "UAV" } class ServerHandler(private val processor: BaseProcessor) : ChannelInboundHandlerAdapter() { val attributeKey = AttributeKey.valueOf<String>("deviceCode") val messageManager = MessageManager() override fun channelRegistered(ctx: ChannelHandlerContext?) { super.channelRegistered(ctx) println() println("------${TAG}ç«¯å£æIPè¿æ¥ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") println("------ã${processor.tag}ãIPè¿æ¥ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") // ctx?.fireChannelActive() } override fun channelActive(ctx: ChannelHandlerContext?) { println() println("------${TAG}ç«¯å£æIPæ¿æ´»ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") println("------ã${processor.tag}ãIPæ¿æ´»ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") super.channelActive(ctx) } override fun channelRead(ctx: ChannelHandlerContext?, msg: Any?) { super.channelRead(ctx, msg) println("------ã${processor.tag}ãæ¶å°çåå§æ°æ®ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") var str = "" when (msg) { is ByteArray -> { val sb = StringBuilder() if (msg is ByteArray) { println() println("------${TAG}æ¶å°çåå§æ°æ®ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") msg.forEach { val a: Int = if (it < 0) { var a = 0 a = if (it < 0) { it + 256 } else { it.toInt() @@ -49,16 +46,20 @@ } else { a.toString(16) } print("$s ") sb.append(s).append(" ") } sb.deleteCharAt(sb.length - 1) str = sb.toString() } val str = sb.toString() if (str.isNotEmpty()) { messageManager.dealStringMsg(str, ctx) is String -> str = msg } println(str) if (str.isNotEmpty()) { processor.dealStringMsg(str, ctx) } } override fun channelReadComplete(ctx: ChannelHandlerContext?) { @@ -66,7 +67,7 @@ } override fun channelInactive(ctx: ChannelHandlerContext?) { println("------${TAG}ç«¯å£æIP䏿´»å¨ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") println("------ã${processor.tag}ãç«¯å£æIP䏿´»å¨ï¼[ip:${ctx?.channel()?.remoteAddress()}] ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}") super.channelInactive(ctx) } src/main/kotlin/com/flightfeather/uav/socket/UAVByteDataDecoder.kt
@@ -1,10 +1,9 @@ package com.flightfeather.uav.socket import com.flightfeather.uav.socket.decoder.impl.DataPackageDecoderImpl import com.flightfeather.uav.socket.decoder.DataPackageDecoder import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.ByteToMessageDecoder import java.lang.StringBuilder /** * @author riku @@ -14,13 +13,13 @@ class UAVByteDataDecoder : ByteToMessageDecoder() { companion object { const val BASE_LENGTH = DataPackageDecoderImpl.HEAD_BYTES + DataPackageDecoderImpl.COMMAND_UNIT_BYTES + DataPackageDecoderImpl.DEVICE_CODE_BYTES + DataPackageDecoderImpl.DATA_LENGTH + DataPackageDecoderImpl.BCC_BYTES const val BASE_LENGTH = DataPackageDecoder.HEAD_BYTES + DataPackageDecoder.COMMAND_UNIT_BYTES + DataPackageDecoder.DEVICE_CODE_BYTES + DataPackageDecoder.DATA_LENGTH + DataPackageDecoder.BCC_BYTES const val HEAD1 = 0x01.toByte() const val COMMAND_1 = 0x01.toByte() const val COMMAND_2 = 0x01.toByte() const val HEAD_LENGTH = DataPackageDecoderImpl.HEAD_BYTES + DataPackageDecoderImpl.COMMAND_UNIT_BYTES + DataPackageDecoderImpl.DEVICE_CODE_BYTES const val HEAD_LENGTH = DataPackageDecoder.HEAD_BYTES + DataPackageDecoder.COMMAND_UNIT_BYTES + DataPackageDecoder.DEVICE_CODE_BYTES } override fun decode(p0: ChannelHandlerContext?, p1: ByteBuf?, p2: MutableList<Any>?) { @@ -74,14 +73,14 @@ //æ°æ®åå çé¿åº¦ val length = getDataUnitLength(it, dataList) // å¤æè¯·æ±æ°æ®åå æ°æ®å[LENGTH_BYTES]个åèçæ ¡éªç æ¯å¦å°é½ if (it.readableBytes() < length + DataPackageDecoderImpl.BCC_BYTES) { if (it.readableBytes() < length + DataPackageDecoder.BCC_BYTES) { // è¿å读æé it.readerIndex(beginReader) return } //è¯»åæ°æ®åå åæ ¡éªç æ°æ® ByteArray(length + DataPackageDecoderImpl.BCC_BYTES).apply { ByteArray(length + DataPackageDecoder.BCC_BYTES).apply { it.readBytes(this) }.forEach {b -> dataList.add(b) src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt
@@ -1,11 +1,14 @@ package com.flightfeather.uav.socket import com.flightfeather.uav.socket.processor.BaseProcessor import io.netty.bootstrap.ServerBootstrap import io.netty.channel.ChannelHandler import io.netty.channel.ChannelInitializer import io.netty.channel.ChannelOption import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.socket.nio.NioServerSocketChannel import io.netty.channel.socket.nio.NioSocketChannel import io.netty.handler.codec.LineBasedFrameDecoder import io.netty.handler.codec.string.StringDecoder import io.netty.handler.codec.string.StringEncoder import java.nio.charset.Charset @@ -19,8 +22,12 @@ private val bossGroup = NioEventLoopGroup() private val workerGroup = NioEventLoopGroup() fun startServer(port: Int) { initialize()?.bind(port)?.sync() fun startUnderwayServer(port: Int, processor: BaseProcessor) { underwayServer(processor)?.bind(port)?.sync() } fun startElectricServer(port: Int, processor: BaseProcessor) { electricServer(processor)?.bind(port)?.sync() } fun stopServer() { @@ -28,8 +35,7 @@ workerGroup.shutdownGracefully() } private fun initialize(): ServerBootstrap? { private fun newServer(childHandler: ChannelHandler): ServerBootstrap? { try { return ServerBootstrap() .group(bossGroup, workerGroup) @@ -37,19 +43,36 @@ .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("decoder", StringDecoder()) ?.addLast(UAVByteDataDecoder()) ?.addLast("encoder", StringEncoder(Charset.forName("UTF-8"))) ?.addLast(ServerHandler()) } }) .childHandler(childHandler) } catch (e: Throwable) { e.printStackTrace() } return null } /** * ç¨çµéæå¡ç«¯ */ private fun electricServer(processor: BaseProcessor): ServerBootstrap? = newServer(object : ChannelInitializer<NioSocketChannel>() { override fun initChannel(p0: NioSocketChannel?) { p0?.pipeline() ?.addLast("lineDecoder", LineBasedFrameDecoder(1024)) ?.addLast("stringDecoder", StringDecoder()) ?.addLast("encoder", StringEncoder(Charset.forName("UTF-8"))) ?.addLast(ServerHandler(processor)) } }) /** * å¤åæ°èµ°èªæå¡ç«¯ */ private fun underwayServer(processor: BaseProcessor):ServerBootstrap? = newServer(object : ChannelInitializer<NioSocketChannel>() { override fun initChannel(p0: NioSocketChannel?) { p0?.pipeline() ?.addLast(UAVByteDataDecoder()) ?.addLast("encoder", StringEncoder(Charset.forName("UTF-8"))) ?.addLast(ServerHandler(processor)) } }) } src/main/kotlin/com/flightfeather/uav/socket/bean/BaseDataPackage.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,4 @@ package com.flightfeather.uav.socket.bean open class BaseDataPackage { } src/main/kotlin/com/flightfeather/uav/socket/bean/BaseMessage.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,87 @@ package com.flightfeather.uav.socket.bean import java.text.SimpleDateFormat import java.util.* /** * @author riku * Date: 2020/9/10 */ open class BaseMessage { var head: String = "" var length: String = "" var qn: String = "" var st: String = "" var cn: String = "" var pw: String = "" var mn: String = "" var flag: String = "" var cp: String = "" var extra: String = "" var crc: String = "" open fun newMessage() { head = "##" qn = SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(Date()) } fun parse2Str():String { val str = "QN=$qn;ST=$st;CN=$cn;PW=$pw;MN=$mn;Flag=$flag;CP=&&${cp}&&$extra" return "$head${getLength(str.length)}$str${getCrc(str.toByteArray(), str.length)}\r\n" } /** * crc计ç®å·¥å ·ç±» * @param bufData æ°æ®æ®µå符串转åçbyte[], * @param bufLen çé¿åº¦ * @return CRCç ï¼4åè */ fun getCrc(bufData: ByteArray, bufLen: Int): String? { var crc = 0x0000ffff val polynomial = 0x0000a001 var j: Int if (bufLen == 0) { return null } var i: Int = 0 while (i < bufLen) { crc = crc xor (bufData[i].toInt() and 0x000000ff) j = 0 while (j < 8) { if (crc and 0x00000001 != 0) { crc = crc shr 1 crc = crc xor polynomial } else { crc = crc shr 1 } j++ } i++ } var strCRC = Integer.toHexString(crc).toString() if (strCRC.length < 4) { strCRC += "0" } return strCRC } fun getLength(length: Int): String { val size = StringBuilder() when { length >= 100 -> { size.append("0") } length >= 10 -> { size.append("00") } length >= 0 -> { size.append("000") } } size.append(length) return size.toString() } } src/main/kotlin/com/flightfeather/uav/socket/bean/ElectricMessage.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.flightfeather.uav.socket.bean import java.util.* class ElectricMessage : BaseMessage() { var dataTime: Date? = null var electricityA: Double = -1.0 var electricityB: Double = -1.0 var electricityC: Double = -1.0 var voltageA: Double = -1.0 var voltageB: Double = -1.0 var voltageC: Double = -1.0 var powerA: Double = -1.0 var powerB: Double = -1.0 var powerC: Double = -1.0 } src/main/kotlin/com/flightfeather/uav/socket/decoder/AirDataDecoder.kt
@@ -1,7 +1,6 @@ package com.flightfeather.uav.socket.decoder import com.flightfeather.uav.socket.bean.AirDataPackage import com.flightfeather.uav.socket.decoder.impl.DataPackageDecoderImpl /** * 空æ°è´¨éå¤åæ°æ°æ®è§£ç å¨ @@ -29,7 +28,7 @@ } } private val dataPackageDecoder: DataPackageDecoder = DataPackageDecoderImpl() private val dataPackageDecoder: DataPackageDecoder = DataPackageDecoder() fun decode(msg: String): AirDataPackage { val list = dataPackageDecoder.toStringList(msg) src/main/kotlin/com/flightfeather/uav/socket/decoder/BaseDataDecoder.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,109 @@ package com.flightfeather.uav.socket.decoder import com.flightfeather.uav.common.utils.CommonUtil import com.flightfeather.uav.socket.bean.BaseMessage import java.text.SimpleDateFormat import java.util.* /** * @author riku * Date: 2020/9/10 */ typealias Decode<T> = (m: T, s: String) -> Unit abstract class BaseDataDecoder<T : BaseMessage> { companion object { const val INVALID_VALUE = -1.0 } private var isInit = false private lateinit var message: T abstract fun messageClass(): Class<T> abstract fun getCpDecode(): List<Decode<T>> private val decodeList = mutableListOf<Decode<T>>() private val getHead: Decode<T> = {m, s -> m.head = s.substring(0, 2) } private val getLength: Decode<T> = {m, s -> m.length = s.substring(2, 6) } private val getQN: Decode<T> = {m, s -> m.qn = getData(s, "QN=", ";") } private val getST: Decode<T> = {m, s -> m.st = getData(s, "ST=", ";") } private val getCN: Decode<T> = {m, s -> m.cn = getData(s, "CN=", ";") } private val getPW: Decode<T> = {m, s -> m.pw = getData(s, "PW=", ";") } private val getMN: Decode<T> = {m, s -> m.mn = getData(s, "MN=", ";") } private val getCP: Decode<T> = {m, s -> m.cp = getData(s, "CP=&&", "&&") } private val getExtra:Decode<T> = {m, s -> val start = s.lastIndexOf("&&") val end = s.length - 4 m.extra = s.substring(start, end).substring(2) } private val getCrc: Decode<T> = {m, s -> m.crc = s.substring(s.length - 4, s.length) } protected fun getData(msg: String, start: String, end: String) = CommonUtil.getSubStr(msg, start, end)?.substring(start.length) ?: "" private fun init() { if (!isInit) { decodeList.add(getHead) decodeList.add(getLength) decodeList.add(getQN) decodeList.add(getST) decodeList.add(getCN) decodeList.add(getPW) decodeList.add(getMN) decodeList.add(getCP) decodeList.add(getExtra) decodeList.add(getCrc) decodeList.addAll(this.getCpDecode()) isInit = true } message = this.messageClass().newInstance() } fun decode(msg: String): T { init() decodeList.forEach { try { it.invoke(message, msg) } catch (e: Exception) { println("${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}: å½ä»¤æ æ³è·å[${it.javaClass.name}]") } } return message } } src/main/kotlin/com/flightfeather/uav/socket/decoder/DataPackageDecoder.kt
@@ -16,22 +16,103 @@ * 2 æ°æ®åå é¿åº¦ * åæ°ç¬¬2 æ ¡éªç */ interface DataPackageDecoder { class DataPackageDecoder { fun getHead(b: List<String>): String? companion object { // æ°æ®å¤´ const val HEAD_BYTES = 1 // çæµåæ°ç¡®è®¤æä»¤ä½ const val COMMAND_UNIT_BYTES = 1 // 设å¤ç±»å const val DEVICE_CODE_BYTES = 6 // æ¬æ¬¡çæµç空æ°å åæ°é const val DATA_LENGTH = 1 // æ ¡éª const val BCC_BYTES = 2 } fun getCommandUnit(b: List<String>): Int? private val dataUnitDecoder: DataUnitDecoder = DataUnitDecoder() fun getDeviceCode(b: List<String>): String? fun getDataTime(b: List<String>): Date fun getHead(b: List<String>): String? { return if (b.isNotEmpty()) { val s = StringBuilder() repeat(HEAD_BYTES) { s.append(b[it]) } s.toString() } else { null } } fun getDataLength(b: List<String>): Int fun getCommandUnit(b: List<String>): Int? = if (b.size >= (HEAD_BYTES + COMMAND_UNIT_BYTES)) { val s = StringBuilder() repeat(COMMAND_UNIT_BYTES) { s.append(b[HEAD_BYTES + it]) } s.toString().toIntOrNull(16) } else { null } fun getDataUnit(b: List<String>): List<DataUnit> fun getDeviceCode(b: List<String>): String? = if (b.size >= (HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES)) { //2021/1/7 '0A'代表车载设å¤ï¼'0B'代表æ 人æºè®¾å¤ï¼'0C'ä¸ºç½æ ¼åçæµ val s = StringBuilder() repeat(DEVICE_CODE_BYTES) { s.append(b[HEAD_BYTES + COMMAND_UNIT_BYTES + it]) } s.toString() } else { null } fun getCheckCode(b: List<String>): Int? fun getDataTime(b: List<String>): Date { // FIXME: 2021/1/7 éæ ·æ¶é´åçæµå åä¸åæ¾å¨äºæ°æ®é¨åï¼æ¤å¤ä¸ååè§£æ return Date() } fun toStringList(msg: String): List<String> fun getDataLength(b: List<String>): Int { if (b.size <= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH) return 0 val hexNum = b[HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES] return hexNum.toIntOrNull(16) ?: 0 } fun getDataUnit(b: List<String>): List<DataUnit> { if (getDataLength(b) == 0 || b.size <= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH) { return emptyList() } val unit = mutableListOf<String>() val start = HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + DATA_LENGTH for (i in start..b.size - 1 - BCC_BYTES) { unit.add(b[i]) } dataUnitDecoder.run { return when (getCommandUnit(b)) { AirCommandUnit.Confirm.value -> getAirConfirmData(unit, getDeviceCode(b)) AirCommandUnit.AirData.value -> getAirData(unit, getDeviceCode(b)) else -> emptyList() } } } fun getCheckCode(b: List<String>): Int? { return if (b.size >= HEAD_BYTES + COMMAND_UNIT_BYTES + DEVICE_CODE_BYTES + BCC_BYTES) { val hexNum = "${b[b.size - 2]}${b[b.size - 1]}" hexNum.toIntOrNull(16) } else { null } } fun toStringList(msg: String): List<String> { return msg.split(" ") } } src/main/kotlin/com/flightfeather/uav/socket/decoder/DataUnitDecoder.kt
@@ -2,6 +2,9 @@ import com.flightfeather.uav.socket.bean.* import com.flightfeather.uav.socket.eunm.AirCommandUnit import com.flightfeather.uav.socket.eunm.FactorType import org.slf4j.LoggerFactory import java.text.SimpleDateFormat import java.util.* /** @@ -12,10 +15,160 @@ * æ°æ®åå æç §å½ä»¤åå çç±»åå ±æä»¥ä¸å ç§ç±»åï¼ * å½ä»¤åå @see [AirCommandUnit] */ interface DataUnitDecoder { class DataUnitDecoder { fun getAirConfirmData(b: List<String>, deviceCode: String?): List<AirTypeData> private val logger = LoggerFactory.getLogger(javaClass.name) fun getAirData(b: List<String>, deviceCode: String?): List<AirData> private val types = mutableMapOf<String?, MutableList<AirTypeData>>() fun getAirConfirmData(b: List<String>, deviceCode: String?): List<AirTypeData> { val resultList = mutableListOf<AirTypeData>() b.forEach { FactorType.getByIndex(it.toInt(16))?.let { f-> resultList.add(AirTypeData(f)) } } if (!types.containsKey(deviceCode)) { types[deviceCode] = mutableListOf() } types[deviceCode]?.clear() types[deviceCode]?.addAll(resultList) return resultList } fun getAirData(b: List<String>, deviceCode: String?): List<AirData> { val resultList = mutableListOf<AirData>() if (!types.containsKey(deviceCode)) { return resultList } var i = 0 types[deviceCode]?.forEach { if (i > b.size - it.factorType.byteLength) { return@forEach } when (it.factorType) { FactorType.LNG -> { val valid = b[i].toInt(16).toChar()//ç»çº¬åº¦æ¯å¦ææï¼ææ: A; æ æ: Vï¼ //ç»çº¬åº¦åå§å¼ï¼ä¾ï¼121°30.0411â²ï¼å ¶ä¸ 121 对åºa1ï¼30对åºb1ï¼04对åºb2ï¼11对åºb3 val a1 = b[i + 1].toInt(16)//度 val b1 = b[i + 2].toInt(16)//åï¼æ´æ°ï¼ var b2 = b[i + 3].toInt(16).toDouble()//åï¼å°æ°é¨åå两ä½ï¼ var b3 = b[i + 4].toInt(16).toDouble()//åï¼å°æ°é¨åå两ä½ï¼ // var b2 = "${b[i + 3]}${b[i + 4]}".toInt(16).toDouble() b2 /= 100 b3 /= 10000 val lng = a1 + (b1 + b2 + b3) / 60 val s = b[i + 5].toInt(16).toChar() resultList.add(AirData().apply { factorId = it.factorType.value?.toString() factorName = it.factorType.des factorData = lng statusList = listOf(valid.toString(), s.toString()) }) } FactorType.LAT -> { val a1 = b[i].toInt(16) val b1 = b[i + 1].toInt(16) var b2 = b[i + 2].toInt(16).toDouble()//åï¼å°æ°é¨åå两ä½ï¼ var b3 = b[i + 3].toInt(16).toDouble()//åï¼å°æ°é¨åå两ä½ï¼ b2 /= 100 b3 /= 10000 val lat = a1 + (b1 + b2 + b3) / 60 val s = b[i + 4].toInt(16).toChar() resultList.add(AirData().apply { factorId = it.factorType.value.toString() factorName = it.factorType.des factorData = lat statusList = listOf(s.toString()) }) } FactorType.TIME -> { val year = b[i].toInt(16).toString().run { numberFormat(this) } val month = b[i + 1].toInt(16).toString().run { numberFormat(this) } val day = b[i + 2].toInt(16).toString().run { numberFormat(this) } val hour = b[i + 3].toInt(16).toString().run { numberFormat(this) } val minute = b[i + 4].toInt(16).toString().run { numberFormat(this) } val second = b[i + 5].toInt(16).toString().run { numberFormat(this) } val date = "20$year-$month-$day $hour:$minute:$second" val time = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(date).time resultList.add(AirData().apply { factorId = it.factorType.value.toString() factorName = it.factorType.des factorData = time.toDouble() statusList = listOf(date) }) } else -> { when (it.factorType.byteLength) { AirDataPackage.FACTOR_BIT_LENGTH_2 -> { val a1 = "${b[i]}${b[i + 1]}".toInt(16) var b1 = b[i + 2].toInt(16).toDouble() while (b1 >= 1) { b1 /= 10 } val data1 = a1 + b1 resultList.add(AirData().apply { factorId = it.factorType.value?.toString() factorName = it.factorType.des factorData = data1 }) } AirDataPackage.FACTOR_BIT_LENGTH_1 -> { //æ°æ®å®é å¼ï¼3ä½åèè¡¨ç¤ºï¼ val a1 = "${b[i]}${b[i + 1]}".toInt(16) var b1 = b[i + 2].toInt(16).toDouble() while (b1 >= 1) { b1 /= 10 } val data1 = a1 + b1 //æ°æ®ç©çéï¼3ä½åèè¡¨ç¤ºï¼ val a2 = "${b[i+3]}${b[i + 4]}".toInt(16) var b2 = b[i + 5].toInt(16).toDouble() while (b2 >= 1) { b2 /= 10 } val data2 = a2 + b2 resultList.add(AirData().apply { factorId = it.factorType.value?.toString() factorName = it.factorType.des factorData = data1 physicalQuantity = data2 }) } AirDataPackage.FACTOR_BIT_LENGTH_3 -> { val data = "${b[i]}${b[i + 1]}".toInt(16) resultList.add(AirData().apply { factorId = it.factorType.value.toString() factorName = it.factorType.des factorData = data.toDouble() }) } } } } i += it.factorType.byteLength } return resultList } private fun numberFormat(num: String) = if (num.length < 2) { "0$num" } else { num } } src/main/kotlin/com/flightfeather/uav/socket/decoder/ElectricDataDecoder.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,85 @@ package com.flightfeather.uav.socket.decoder import com.flightfeather.uav.common.utils.DateUtil import com.flightfeather.uav.socket.bean.ElectricMessage import org.springframework.stereotype.Component @Component class ElectricDataDecoder:BaseDataDecoder<ElectricMessage>() { private val dateUtil = DateUtil() override fun messageClass(): Class<ElectricMessage> = ElectricMessage::class.java override fun getCpDecode(): List<Decode<ElectricMessage>> = listOf( getDataTime, getElectricityA, getElectricityB, getElectricityC, getVoltageA, getVoltageB, getVoltageC, getPowerA, getPowerB, getPowerC ) private val getDataTime: Decode<ElectricMessage> = { e, s -> val time = getData(s, "DataTime=", ";") time.let { val date = if (it.length > "yyyyMMddHHmmss".length) { dateUtil.StringToDate(it, "yyyyMMddHHmmssSSS") } else { dateUtil.StringToDate(it, "yyyyMMddHHmmss") } e.dataTime = date } } private val getElectricityA: Decode<ElectricMessage> = { e, s -> getData(s, "550-Rtd=", ";").let { e.electricityA = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getElectricityB: Decode<ElectricMessage> = { e, s -> getData(s, "551-Rtd=", ";").let { e.electricityB = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getElectricityC: Decode<ElectricMessage> = { e, s -> getData(s, "552-Rtd=", ";").let { e.electricityC = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getVoltageA: Decode<ElectricMessage> = { e, s -> getData(s, "553-Rtd=", ";").let { e.voltageA = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getVoltageB: Decode<ElectricMessage> = { e, s -> getData(s, "554-Rtd=", ";").let { e.voltageB = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getVoltageC: Decode<ElectricMessage> = { e, s -> getData(s, "555-Rtd=", ";").let { e.voltageC = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getPowerA: Decode<ElectricMessage> = { e, s -> getData(s, "556-Rtd=", ";").let { e.powerA = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getPowerB: Decode<ElectricMessage> = { e, s -> getData(s, "557-Rtd=", ";").let { e.powerB = it.toDoubleOrNull() ?: INVALID_VALUE } } private val getPowerC: Decode<ElectricMessage> = { e, s -> getData(s, "558-Rtd=", ";").let { e.powerC = it.toDoubleOrNull() ?: INVALID_VALUE } } } src/main/kotlin/com/flightfeather/uav/socket/decoder/impl/DataPackageDecoderImpl.kt
ÎļþÒÑɾ³ý src/main/kotlin/com/flightfeather/uav/socket/decoder/impl/DataUnitDecoderImpl.kt
ÎļþÒÑɾ³ý src/main/kotlin/com/flightfeather/uav/socket/processor/BaseProcessor.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package com.flightfeather.uav.socket.processor import com.flightfeather.uav.common.utils.FileUtil import com.flightfeather.uav.socket.DeviceSession import io.netty.channel.ChannelHandlerContext import java.text.SimpleDateFormat import java.util.* abstract class BaseProcessor { abstract var tag: String val deviceSession = DeviceSession() abstract fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) /** * ä¿åè³txtææ¬ */ fun saveToTxt(msg: String) { val data = "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}]data=> $msg" FileUtil.instance?.saveObdData(data) } } src/main/kotlin/com/flightfeather/uav/socket/processor/ElectricProcessor.kt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,48 @@ package com.flightfeather.uav.socket.processor import com.flightfeather.uav.repository.ElectricRepository import com.flightfeather.uav.socket.bean.BaseMessage import com.flightfeather.uav.socket.bean.ElectricMessage import com.flightfeather.uav.socket.decoder.ElectricDataDecoder import io.netty.channel.ChannelHandlerContext import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component import javax.annotation.PostConstruct /** * å¤çç¨çµésocketæ¥æ¶çæ¶æ¯ * @author riku */ @Component class ElectricProcessor() : BaseProcessor() { companion object { private lateinit var instance: ElectricProcessor } @Autowired lateinit var electricRepository: ElectricRepository @Autowired lateinit var electricDataDecoder: ElectricDataDecoder @PostConstruct fun init() { instance = this } override var tag: String = "ç¨çµé" override fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) { //è§£å val packageData = electricDataDecoder.decode(msg) deviceSession.saveDevice(packageData.mn, ctx) saveToTxt(msg) saveToDataBase(packageData, msg) } private fun saveToDataBase(message: BaseMessage, msg: String) { if (message is ElectricMessage) { instance.electricRepository.saveData(message) } } } src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt
ÎļþÃû´Ó src/main/kotlin/com/flightfeather/uav/socket/MessageManager.kt ÐÞ¸Ä @@ -1,10 +1,9 @@ package com.flightfeather.uav.socket package com.flightfeather.uav.socket.processor import com.flightfeather.uav.common.utils.FileUtil import com.flightfeather.uav.repository.* import com.flightfeather.uav.socket.bean.* import com.flightfeather.uav.repository.AirDataRepository import com.flightfeather.uav.socket.bean.AirDataPackage import com.flightfeather.uav.socket.decoder.AirDataDecoder import com.flightfeather.uav.socket.decoder.impl.DataPackageDecoderImpl import com.flightfeather.uav.socket.decoder.DataPackageDecoder import com.flightfeather.uav.socket.eunm.AirCommandUnit import io.netty.channel.ChannelHandlerContext import org.springframework.beans.factory.annotation.Autowired @@ -20,10 +19,10 @@ */ @Component class MessageManager{ class UnderwayProcessor : BaseProcessor() { companion object{ private lateinit var instance: MessageManager private lateinit var instance: UnderwayProcessor private const val TAG = "UAV" } @@ -32,35 +31,27 @@ lateinit var airDataRepository: AirDataRepository val airDataDecoder = AirDataDecoder.instance val dataPackageDecoder = DataPackageDecoderImpl() val dataPackageDecoder = DataPackageDecoder() @PostConstruct fun init() { instance = this airDataRepository = this.airDataRepository } fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) { override var tag: String = "èµ°èªçæµ" override fun dealStringMsg(msg: String, ctx: ChannelHandlerContext?) { //è§£å val packageData = airDataDecoder.decode(msg) if (bccCheck(msg)) { //ä¿å DeviceSession.saveDevice(packageData.deviceCode, ctx) deviceSession.saveDevice(packageData.deviceCode, ctx) saveToTxt(msg) saveToDataBase(packageData) } else { println("------${TAG}æ°æ®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) } /** src/main/resources/application.yml
@@ -8,6 +8,10 @@ url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false username: dronemonitor password: dronemonitor_hackxrnomxm # url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false # username: root # password: 123456 hikari: maximum-pool-size: 500 minimum-idle: 20 src/main/resources/generator/generatorConfig.xml
@@ -46,6 +46,7 @@ </javaClientGenerator> <!-- è¦çæç表 tableNameæ¯æ°æ®åºä¸ç表åæè§å¾å domainObjectNameæ¯å®ä½ç±»å--> <!-- <table tableName="air_real_time_data" domainObjectName="RealTimeData" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>--> <table tableName="mission" domainObjectName="Mission" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <!-- <table tableName="mission" domainObjectName="Mission" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>--> <table tableName="el_minutevalue" domainObjectName="ElectricMinuteValue" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> </context> </generatorConfiguration> src/main/resources/mapper/ElectricMinuteValueMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,30 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.flightfeather.uav.domain.mapper.ElectricMinuteValueMapper"> <resultMap id="BaseResultMap" type="com.flightfeather.uav.domain.entity.ElectricMinuteValue"> <!-- WARNING - @mbg.generated --> <id column="MV_ID" jdbcType="INTEGER" property="mvId" /> <result column="MV_Stat_Code" jdbcType="VARCHAR" property="mvStatCode" /> <result column="MV_Create_Time" jdbcType="TIMESTAMP" property="mvCreateTime" /> <result column="MV_Data_Time" jdbcType="TIMESTAMP" property="mvDataTime" /> <result column="MV_Electricity_A" jdbcType="DOUBLE" property="mvElectricityA" /> <result column="MV_Electricity_B" jdbcType="DOUBLE" property="mvElectricityB" /> <result column="MV_Electricity_C" jdbcType="DOUBLE" property="mvElectricityC" /> <result column="MV_Voltage_A" jdbcType="DOUBLE" property="mvVoltageA" /> <result column="MV_Voltage_B" jdbcType="DOUBLE" property="mvVoltageB" /> <result column="MV_Voltage_C" jdbcType="DOUBLE" property="mvVoltageC" /> <result column="MV_Power_A" jdbcType="DOUBLE" property="mvPowerA" /> <result column="MV_Power_B" jdbcType="DOUBLE" property="mvPowerB" /> <result column="MV_Power_C" jdbcType="DOUBLE" property="mvPowerC" /> </resultMap> <sql id="Base_Column_List"> <!-- WARNING - @mbg.generated --> MV_ID, MV_Stat_Code, MV_Create_Time, MV_Data_Time, MV_Electricity_A, MV_Electricity_B, MV_Electricity_C, MV_Voltage_A, MV_Voltage_B, MV_Voltage_C, MV_Power_A, MV_Power_B, MV_Power_C </sql> </mapper> src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt
ÎļþÃû´Ó src/test/kotlin/com/flightfeather/uav/socket/MessageManagerTest.kt ÐÞ¸Ä @@ -1,14 +1,15 @@ package com.flightfeather.uav.socket import com.flightfeather.uav.socket.processor.UnderwayProcessor import org.junit.Test /** * @author riku * Date: 2019/9/16 */ class MessageManagerTest { class UnderwayProcessorTest { private val messageManager = MessageManager() private val messageManager = UnderwayProcessor() @Test fun bccCheck() {