diff --git a/app/src/main/java/com/casic/detector/common/extensions/Double.kt b/app/src/main/java/com/casic/detector/common/extensions/Double.kt new file mode 100644 index 0000000..a91efd0 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Double.kt @@ -0,0 +1,21 @@ +package com.casic.detector.common.extensions + +/** + * 经纬度转度分格式,ddmm.mmmm + * + * longitude: 116.25980833333332 + * latitude: 39.912785 + * + * 转换后的纬度 = dd + (mm.mmmm/60) + * 转换后的经度 = ddd + (mm.mmmm/60) + * */ +fun Double.convert(): String { + //整数部分,即度数 + val degree = this.toInt() + + //小数部分 + val temp = this - degree + val mm = "%.4f".format(temp * 60) + + return "$degree$mm" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Double.kt b/app/src/main/java/com/casic/detector/common/extensions/Double.kt new file mode 100644 index 0000000..a91efd0 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Double.kt @@ -0,0 +1,21 @@ +package com.casic.detector.common.extensions + +/** + * 经纬度转度分格式,ddmm.mmmm + * + * longitude: 116.25980833333332 + * latitude: 39.912785 + * + * 转换后的纬度 = dd + (mm.mmmm/60) + * 转换后的经度 = ddd + (mm.mmmm/60) + * */ +fun Double.convert(): String { + //整数部分,即度数 + val degree = this.toInt() + + //小数部分 + val temp = this - degree + val mm = "%.4f".format(temp * 60) + + return "$degree$mm" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Location.kt b/app/src/main/java/com/casic/detector/common/extensions/Location.kt new file mode 100644 index 0000000..70392b8 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Location.kt @@ -0,0 +1,67 @@ +package com.casic.detector.common.extensions + +import android.location.Location +import com.casic.detector.common.utils.LocaleConstant +import com.pengxh.kt.lite.extensions.appendZero +import com.pengxh.kt.lite.utils.SaveKeyValues +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import java.util.TimeZone + +/** + * 组装千寻报文 + *
+ * $GPGGA,000001,3112.518576,N,12127.901251,E,1,8,1,0,M,-32,M,3,0*4B + * $GPGGA,092204.999,4250.5589,N,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F + * + * 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息 + * 字段1:UTC 时间,hhmmss.sss,时分秒格式 + * 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0) + * 字段3:纬度N(北纬)或S(南纬) + * 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0) + * 字段5:经度E(东经)或W(西经) + * 字段6:GPS状态,0=未定位,1=单点定位,2=伪距/SBAS,3=无效PPS,4=RTK固定,5=RTK浮动,6=正在估算 + * 7=手动启动基准站,8=RTK宽巷解,9=伪距(诺瓦泰615) + * 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0) + * 字段8:HDOP水平精度因子(0.5 - 99.9) + * 字段9:海拔高度(-9999.9 - 99999.9) + * 字段10:地球椭球面相对大地水准面的高度 + * 字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) + * 字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空) + * 字段13:校验值 + * */ +fun Location.convertToGPGGA(): String { + /** + * 获取UTC时间 + * */ + val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")) + val sdf = SimpleDateFormat("HHmmss", Locale.CHINA) + sdf.timeZone = TimeZone.getTimeZone("UTC") + // 获取时间(不包含毫秒) + val timeStr = sdf.format(calendar.time) + // 获取毫秒部分 + val millis = calendar[Calendar.MILLISECOND] + // 拼接毫秒部分,注意要转换为字符串并保留三位小数 + val millisStr = "%03d".format(millis) + val utc = "$timeStr.$millisStr" + + val count = SaveKeyValues.getValue(LocaleConstant.SATELLITE_EFFECTIVE_COUNT, 0) as Int + val satelliteCount = if (count >= 12) { + 12 + } else { + count.appendZero() + } + + val formatAltitude = "%.1f".format(altitude) + + //TODO HDOP水平精度因子(0.5 - 99.9)不确定 + val hdop = 1.0 + + //拼接不带校验位的参数 + val temp = + "\$GPGGA,$utc,${latitude.convert()},N,${longitude.convert()},E,1,$satelliteCount,$hdop,$formatAltitude,M,,,,0000*" + + //拼接校验位 + return "$temp${temp.calculateCheckDigit()}\r\n" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Double.kt b/app/src/main/java/com/casic/detector/common/extensions/Double.kt new file mode 100644 index 0000000..a91efd0 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Double.kt @@ -0,0 +1,21 @@ +package com.casic.detector.common.extensions + +/** + * 经纬度转度分格式,ddmm.mmmm + * + * longitude: 116.25980833333332 + * latitude: 39.912785 + * + * 转换后的纬度 = dd + (mm.mmmm/60) + * 转换后的经度 = ddd + (mm.mmmm/60) + * */ +fun Double.convert(): String { + //整数部分,即度数 + val degree = this.toInt() + + //小数部分 + val temp = this - degree + val mm = "%.4f".format(temp * 60) + + return "$degree$mm" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Location.kt b/app/src/main/java/com/casic/detector/common/extensions/Location.kt new file mode 100644 index 0000000..70392b8 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Location.kt @@ -0,0 +1,67 @@ +package com.casic.detector.common.extensions + +import android.location.Location +import com.casic.detector.common.utils.LocaleConstant +import com.pengxh.kt.lite.extensions.appendZero +import com.pengxh.kt.lite.utils.SaveKeyValues +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import java.util.TimeZone + +/** + * 组装千寻报文 + * + * $GPGGA,000001,3112.518576,N,12127.901251,E,1,8,1,0,M,-32,M,3,0*4B + * $GPGGA,092204.999,4250.5589,N,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F + * + * 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息 + * 字段1:UTC 时间,hhmmss.sss,时分秒格式 + * 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0) + * 字段3:纬度N(北纬)或S(南纬) + * 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0) + * 字段5:经度E(东经)或W(西经) + * 字段6:GPS状态,0=未定位,1=单点定位,2=伪距/SBAS,3=无效PPS,4=RTK固定,5=RTK浮动,6=正在估算 + * 7=手动启动基准站,8=RTK宽巷解,9=伪距(诺瓦泰615) + * 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0) + * 字段8:HDOP水平精度因子(0.5 - 99.9) + * 字段9:海拔高度(-9999.9 - 99999.9) + * 字段10:地球椭球面相对大地水准面的高度 + * 字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) + * 字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空) + * 字段13:校验值 + * */ +fun Location.convertToGPGGA(): String { + /** + * 获取UTC时间 + * */ + val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")) + val sdf = SimpleDateFormat("HHmmss", Locale.CHINA) + sdf.timeZone = TimeZone.getTimeZone("UTC") + // 获取时间(不包含毫秒) + val timeStr = sdf.format(calendar.time) + // 获取毫秒部分 + val millis = calendar[Calendar.MILLISECOND] + // 拼接毫秒部分,注意要转换为字符串并保留三位小数 + val millisStr = "%03d".format(millis) + val utc = "$timeStr.$millisStr" + + val count = SaveKeyValues.getValue(LocaleConstant.SATELLITE_EFFECTIVE_COUNT, 0) as Int + val satelliteCount = if (count >= 12) { + 12 + } else { + count.appendZero() + } + + val formatAltitude = "%.1f".format(altitude) + + //TODO HDOP水平精度因子(0.5 - 99.9)不确定 + val hdop = 1.0 + + //拼接不带校验位的参数 + val temp = + "\$GPGGA,$utc,${latitude.convert()},N,${longitude.convert()},E,1,$satelliteCount,$hdop,$formatAltitude,M,,,,0000*" + + //拼接校验位 + return "$temp${temp.calculateCheckDigit()}\r\n" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt new file mode 100644 index 0000000..d9156da --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt @@ -0,0 +1,18 @@ +package com.casic.detector.common.utils.tcp + +enum class ConnectState { + /** + * 连接成功 + */ + SUCCESS, + + /** + * 关闭连接 + */ + CLOSED, + + /** + * 连接失败 + */ + ERROR +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Double.kt b/app/src/main/java/com/casic/detector/common/extensions/Double.kt new file mode 100644 index 0000000..a91efd0 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Double.kt @@ -0,0 +1,21 @@ +package com.casic.detector.common.extensions + +/** + * 经纬度转度分格式,ddmm.mmmm + * + * longitude: 116.25980833333332 + * latitude: 39.912785 + * + * 转换后的纬度 = dd + (mm.mmmm/60) + * 转换后的经度 = ddd + (mm.mmmm/60) + * */ +fun Double.convert(): String { + //整数部分,即度数 + val degree = this.toInt() + + //小数部分 + val temp = this - degree + val mm = "%.4f".format(temp * 60) + + return "$degree$mm" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Location.kt b/app/src/main/java/com/casic/detector/common/extensions/Location.kt new file mode 100644 index 0000000..70392b8 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Location.kt @@ -0,0 +1,67 @@ +package com.casic.detector.common.extensions + +import android.location.Location +import com.casic.detector.common.utils.LocaleConstant +import com.pengxh.kt.lite.extensions.appendZero +import com.pengxh.kt.lite.utils.SaveKeyValues +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import java.util.TimeZone + +/** + * 组装千寻报文 + * + * $GPGGA,000001,3112.518576,N,12127.901251,E,1,8,1,0,M,-32,M,3,0*4B + * $GPGGA,092204.999,4250.5589,N,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F + * + * 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息 + * 字段1:UTC 时间,hhmmss.sss,时分秒格式 + * 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0) + * 字段3:纬度N(北纬)或S(南纬) + * 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0) + * 字段5:经度E(东经)或W(西经) + * 字段6:GPS状态,0=未定位,1=单点定位,2=伪距/SBAS,3=无效PPS,4=RTK固定,5=RTK浮动,6=正在估算 + * 7=手动启动基准站,8=RTK宽巷解,9=伪距(诺瓦泰615) + * 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0) + * 字段8:HDOP水平精度因子(0.5 - 99.9) + * 字段9:海拔高度(-9999.9 - 99999.9) + * 字段10:地球椭球面相对大地水准面的高度 + * 字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) + * 字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空) + * 字段13:校验值 + * */ +fun Location.convertToGPGGA(): String { + /** + * 获取UTC时间 + * */ + val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")) + val sdf = SimpleDateFormat("HHmmss", Locale.CHINA) + sdf.timeZone = TimeZone.getTimeZone("UTC") + // 获取时间(不包含毫秒) + val timeStr = sdf.format(calendar.time) + // 获取毫秒部分 + val millis = calendar[Calendar.MILLISECOND] + // 拼接毫秒部分,注意要转换为字符串并保留三位小数 + val millisStr = "%03d".format(millis) + val utc = "$timeStr.$millisStr" + + val count = SaveKeyValues.getValue(LocaleConstant.SATELLITE_EFFECTIVE_COUNT, 0) as Int + val satelliteCount = if (count >= 12) { + 12 + } else { + count.appendZero() + } + + val formatAltitude = "%.1f".format(altitude) + + //TODO HDOP水平精度因子(0.5 - 99.9)不确定 + val hdop = 1.0 + + //拼接不带校验位的参数 + val temp = + "\$GPGGA,$utc,${latitude.convert()},N,${longitude.convert()},E,1,$satelliteCount,$hdop,$formatAltitude,M,,,,0000*" + + //拼接校验位 + return "$temp${temp.calculateCheckDigit()}\r\n" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt new file mode 100644 index 0000000..d9156da --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt @@ -0,0 +1,18 @@ +package com.casic.detector.common.utils.tcp + +enum class ConnectState { + /** + * 连接成功 + */ + SUCCESS, + + /** + * 关闭连接 + */ + CLOSED, + + /** + * 连接失败 + */ + ERROR +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt new file mode 100644 index 0000000..b452461 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt @@ -0,0 +1,13 @@ +package com.casic.detector.common.utils.tcp + +interface OnSocketConnectListener { + /** + * 当接收到系统消息 + */ + fun onMessageResponse(data: ByteArray) + + /** + * 当连接状态发生变化时调用 + */ + fun onServiceConnectStatusChanged(status: ConnectState) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Double.kt b/app/src/main/java/com/casic/detector/common/extensions/Double.kt new file mode 100644 index 0000000..a91efd0 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Double.kt @@ -0,0 +1,21 @@ +package com.casic.detector.common.extensions + +/** + * 经纬度转度分格式,ddmm.mmmm + * + * longitude: 116.25980833333332 + * latitude: 39.912785 + * + * 转换后的纬度 = dd + (mm.mmmm/60) + * 转换后的经度 = ddd + (mm.mmmm/60) + * */ +fun Double.convert(): String { + //整数部分,即度数 + val degree = this.toInt() + + //小数部分 + val temp = this - degree + val mm = "%.4f".format(temp * 60) + + return "$degree$mm" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/extensions/Location.kt b/app/src/main/java/com/casic/detector/common/extensions/Location.kt new file mode 100644 index 0000000..70392b8 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/extensions/Location.kt @@ -0,0 +1,67 @@ +package com.casic.detector.common.extensions + +import android.location.Location +import com.casic.detector.common.utils.LocaleConstant +import com.pengxh.kt.lite.extensions.appendZero +import com.pengxh.kt.lite.utils.SaveKeyValues +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale +import java.util.TimeZone + +/** + * 组装千寻报文 + * + * $GPGGA,000001,3112.518576,N,12127.901251,E,1,8,1,0,M,-32,M,3,0*4B + * $GPGGA,092204.999,4250.5589,N,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F + * + * 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息 + * 字段1:UTC 时间,hhmmss.sss,时分秒格式 + * 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0) + * 字段3:纬度N(北纬)或S(南纬) + * 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0) + * 字段5:经度E(东经)或W(西经) + * 字段6:GPS状态,0=未定位,1=单点定位,2=伪距/SBAS,3=无效PPS,4=RTK固定,5=RTK浮动,6=正在估算 + * 7=手动启动基准站,8=RTK宽巷解,9=伪距(诺瓦泰615) + * 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0) + * 字段8:HDOP水平精度因子(0.5 - 99.9) + * 字段9:海拔高度(-9999.9 - 99999.9) + * 字段10:地球椭球面相对大地水准面的高度 + * 字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) + * 字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空) + * 字段13:校验值 + * */ +fun Location.convertToGPGGA(): String { + /** + * 获取UTC时间 + * */ + val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")) + val sdf = SimpleDateFormat("HHmmss", Locale.CHINA) + sdf.timeZone = TimeZone.getTimeZone("UTC") + // 获取时间(不包含毫秒) + val timeStr = sdf.format(calendar.time) + // 获取毫秒部分 + val millis = calendar[Calendar.MILLISECOND] + // 拼接毫秒部分,注意要转换为字符串并保留三位小数 + val millisStr = "%03d".format(millis) + val utc = "$timeStr.$millisStr" + + val count = SaveKeyValues.getValue(LocaleConstant.SATELLITE_EFFECTIVE_COUNT, 0) as Int + val satelliteCount = if (count >= 12) { + 12 + } else { + count.appendZero() + } + + val formatAltitude = "%.1f".format(altitude) + + //TODO HDOP水平精度因子(0.5 - 99.9)不确定 + val hdop = 1.0 + + //拼接不带校验位的参数 + val temp = + "\$GPGGA,$utc,${latitude.convert()},N,${longitude.convert()},E,1,$satelliteCount,$hdop,$formatAltitude,M,,,,0000*" + + //拼接校验位 + return "$temp${temp.calculateCheckDigit()}\r\n" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt new file mode 100644 index 0000000..d9156da --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/ConnectState.kt @@ -0,0 +1,18 @@ +package com.casic.detector.common.utils.tcp + +enum class ConnectState { + /** + * 连接成功 + */ + SUCCESS, + + /** + * 关闭连接 + */ + CLOSED, + + /** + * 连接失败 + */ + ERROR +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt new file mode 100644 index 0000000..b452461 --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/OnSocketConnectListener.kt @@ -0,0 +1,13 @@ +package com.casic.detector.common.utils.tcp + +interface OnSocketConnectListener { + /** + * 当接收到系统消息 + */ + fun onMessageResponse(data: ByteArray) + + /** + * 当连接状态发生变化时调用 + */ + fun onServiceConnectStatusChanged(status: ConnectState) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/common/utils/tcp/SocketChannelHandler.kt b/app/src/main/java/com/casic/detector/common/utils/tcp/SocketChannelHandler.kt new file mode 100644 index 0000000..1a5a99f --- /dev/null +++ b/app/src/main/java/com/casic/detector/common/utils/tcp/SocketChannelHandler.kt @@ -0,0 +1,72 @@ +package com.casic.detector.common.utils.tcp + +import android.os.Looper +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.lifecycle.lifecycleScope +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.SimpleChannelInboundHandler +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class SocketChannelHandler(private val listener: OnSocketConnectListener) : + SimpleChannelInboundHandler