diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt index 93948ae..5e19d29 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/constant/Constants.kt @@ -13,10 +13,10 @@ const val DEFAULT_QUERY_TIME_INTERVAL = ONE_HOUR_MS * 6 const val CAMERA_URL = "rtsp://admin:123456@192.168.5.200:554/h264/ch1/main/av_stream" //打开摄像头延时 -const val DELAY_TIME_OPEN_CAMERA = 10 +const val DELAY_TIME_OPEN_CAMERA = 30 //检测重连摄像头延时 -const val DELAY_TIME_CHECK_CAMERA = 5 +const val DELAY_TIME_CHECK_CAMERA = DELAY_TIME_OPEN_CAMERA //检测重连传感器延时 const val DELAY_TIME_CHECK_SENSOR = 5 diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasConstants.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasConstants.kt index 30c5d30..3632e41 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasConstants.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasConstants.kt @@ -1,36 +1,66 @@ package com.yinuo.safetywatcher.watcher.port +import com.yinuo.safetywatcher.watcher.port.cmd.C02 import com.yinuo.safetywatcher.watcher.port.cmd.CH4 +import com.yinuo.safetywatcher.watcher.port.cmd.CH4_LEL2PPMFACTOR +import com.yinuo.safetywatcher.watcher.port.cmd.CL2 import com.yinuo.safetywatcher.watcher.port.cmd.CO +import com.yinuo.safetywatcher.watcher.port.cmd.H2 import com.yinuo.safetywatcher.watcher.port.cmd.H2S - -//气体浓度单位转换系数 -const val TEMPERATURE_COEFFICIENT: Float = (273 + 25) / 273f +import com.yinuo.safetywatcher.watcher.port.cmd.H2_LEL2PPMFACTOR +import com.yinuo.safetywatcher.watcher.port.cmd.HF +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_C02 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_CH4 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_CL2 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_CO +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_H2 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_H2S +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_HF +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_NH3 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_NO +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_NO2 +import com.yinuo.safetywatcher.watcher.port.cmd.MOLECULAR_S02 +import com.yinuo.safetywatcher.watcher.port.cmd.NH3 +import com.yinuo.safetywatcher.watcher.port.cmd.NO +import com.yinuo.safetywatcher.watcher.port.cmd.NO2 +import com.yinuo.safetywatcher.watcher.port.cmd.S02 + +// ppm转mgm3转化率 +const val PPM_TO_MGM3_CONVERSION_RATE = 0.0409f // 后缀 const val MIN_SUFFIX = "min" const val MAX_SUFFIX = "max" // 各个气体报警高低默认值,默认单位 -// ppm -1代表不考虑低值 -const val CO_MIN = -1f - -// 20mg/m3 -const val CO_MAX_MGM3 = 20f - -//vol +const val CO_MIN_MGM3 = 20f +const val CO_MAX_MGM3 = 40f const val O2_MIN = 19.5f const val O2_MAX = 23.5f - -//lel -const val CH4_MIN = -1f -const val CH4_MAX_LEL = 25f - -//ppm -const val H2S_MIN = -1f - -// 10mg/m3 -const val H2S_MAX_MGM3 = 10f +const val CH4_MIN_LEL = 25f +const val CH4_MAX_LEL = 50f +const val H2S_MIN_MGM3 = 10f +const val H2S_MAX_MGM3 = 20f + +const val H2_MIN_LEL = 25f +const val H2_MAX_LEL = 50f +const val NH3_MIN_MGM3 = 20f +const val NH3_MAX_MGM3 = 40f +const val S02_MIN_MGM3 = 5f +const val S02_MAX_MGM3 = 10f +const val CL2_MIN_MGM3 = 1f +const val CL2_MAX_MGM3 = 2f +const val NO2_MIN_MGM3 = 5f +const val NO2_MAX_MGM3 = 10f +const val NO_MIN_PPM = 10f +const val NO_MAX_PPM = 20f +const val HF_MIN_PPM = 2.2f +const val HF_MAX_PPM = 4.4f +const val C02_MIN_PPM = 1000f +const val C02_MAX_PPM = 2000f +//?? TODO VOCS +const val VOCS_MIN_MGM3 = 0.5f +const val VOCS_MAX_MGM3 = 1f // 单位 const val UNIT_VOL = "%VOL" @@ -38,28 +68,6 @@ const val UNIT_PPM = "ppm" const val UNIT_MGM3 = "mg/m3" const val UNIT_LEL = "%LEL" -/** - * 气体分子质量 - */ -const val MOLECULAR_CO = 28 -const val MOLECULAR_H2S = 34 -const val MOLECULAR_CH4 = 16 -const val MOLECULAR_O2 = 32 -const val MOLECULAR_H2 = 2 -const val MOLECULAR_NH3 = 17 -const val MOLECULAR_S02 = 64 -const val MOLECULAR_CL2 = 71 -const val MOLECULAR_NO2 = 46 -const val MOLECULAR_NO = 30 -const val MOLECULAR_HF = 20 -const val MOLECULAR_C02 = 44 - -val molecular_map = hashMapOf( - Pair(CO, MOLECULAR_CO), - Pair(CH4, MOLECULAR_CH4), - Pair(H2S, MOLECULAR_H2S), -) - /** * ppm单位的气体量程 */ @@ -77,14 +85,14 @@ val gas_range_ppm = hashMapOf( * C—污染物以 ppm 表示的浓度值; * M—污染物的分之子量。 * - * CO分子量 = 28 28/22.4 * 1000 - * CH4分子量 = 16 16/22.4 * 50000 - * H2S分子量 = 34 34/22.4 * 100 + * CO分子量 = 28 28 * 1000 * PPM_TO_MGM3_CONVERSION_RATE + * CH4分子量 = 16 16 * 50000 * PPM_TO_MGM3_CONVERSION_RATE + * H2S分子量 = 34 34 * 100 * PPM_TO_MGM3_CONVERSION_RATE */ val gas_range_mgm3 = hashMapOf( - Pair(CO, "0-1250 $UNIT_MGM3"), - Pair(CH4, "0-35714 $UNIT_MGM3"), - Pair(H2S, "0-151 $UNIT_MGM3") + Pair(CO, "0-1145.2 $UNIT_MGM3"), + Pair(CH4, "0-32720 $UNIT_MGM3"), + Pair(H2S, "0-139.06 $UNIT_MGM3") ) /** @@ -92,25 +100,62 @@ val gas_range_mgm3 = hashMapOf( */ const val O2_RANGE = "0-30 $UNIT_VOL" +/** + * 氧气的量程 TODO + */ +const val VOCS_RANGE = "0-30 $UNIT_VOL" // 气体默认阈值表 val default_threshold_map_ppm = hashMapOf( - Pair("${CO}_$MIN_SUFFIX", CO_MIN), + Pair("${CO}_$MIN_SUFFIX", mgm3ToPpm(CO_MIN_MGM3, MOLECULAR_CO)), Pair("${CO}_$MAX_SUFFIX", mgm3ToPpm(CO_MAX_MGM3, MOLECULAR_CO)), - Pair("${CH4}_$MIN_SUFFIX", CH4_MIN), - Pair("${CH4}_$MAX_SUFFIX", ch4Lel2ppm(CH4_MAX_LEL)), - Pair("${H2S}_$MIN_SUFFIX", H2S_MIN), - Pair("${H2S}_$MAX_SUFFIX", mgm3ToPpm(H2S_MAX_MGM3, MOLECULAR_H2S)) + Pair("${CH4}_$MIN_SUFFIX", lel2ppm(CH4_MIN_LEL, CH4_LEL2PPMFACTOR)), + Pair("${CH4}_$MAX_SUFFIX", lel2ppm(CH4_MAX_LEL, CH4_LEL2PPMFACTOR)), + Pair("${H2S}_$MIN_SUFFIX", mgm3ToPpm(H2S_MIN_MGM3, MOLECULAR_H2S)), + Pair("${H2S}_$MAX_SUFFIX", mgm3ToPpm(H2S_MAX_MGM3, MOLECULAR_H2S)), + + Pair("${H2}_$MIN_SUFFIX", lel2ppm(H2_MIN_LEL, H2_LEL2PPMFACTOR)), + Pair("${H2}_$MAX_SUFFIX", lel2ppm(H2_MAX_LEL, H2_LEL2PPMFACTOR)), + Pair("${NH3}_$MIN_SUFFIX", mgm3ToPpm(NH3_MIN_MGM3, MOLECULAR_NH3)), + Pair("${NH3}_$MAX_SUFFIX", mgm3ToPpm(NH3_MAX_MGM3, MOLECULAR_NH3)), + Pair("${S02}_$MIN_SUFFIX", mgm3ToPpm(S02_MIN_MGM3, MOLECULAR_S02)), + Pair("${S02}_$MAX_SUFFIX", mgm3ToPpm(S02_MAX_MGM3, MOLECULAR_S02)), + Pair("${CL2}_$MIN_SUFFIX", mgm3ToPpm(CL2_MIN_MGM3, MOLECULAR_CL2)), + Pair("${CL2}_$MAX_SUFFIX", mgm3ToPpm(CL2_MAX_MGM3, MOLECULAR_CL2)), + Pair("${NO2}_$MIN_SUFFIX", mgm3ToPpm(NO2_MIN_MGM3, MOLECULAR_NO2)), + Pair("${NO2}_$MAX_SUFFIX", mgm3ToPpm(NO2_MAX_MGM3, MOLECULAR_NO2)), + Pair("${NO}_$MIN_SUFFIX", NO_MIN_PPM), + Pair("${NO}_$MAX_SUFFIX", NO_MAX_PPM), + Pair("${HF}_$MIN_SUFFIX", HF_MIN_PPM), + Pair("${HF}_$MAX_SUFFIX", HF_MAX_PPM), + Pair("${C02}_$MIN_SUFFIX", C02_MIN_PPM), + Pair("${C02}_$MAX_SUFFIX", C02_MAX_PPM), ) // 气体默认阈值表 val default_threshold_map_mgm3 = hashMapOf( - Pair("${CO}_$MIN_SUFFIX", CO_MIN), + Pair("${CO}_$MIN_SUFFIX", CO_MIN_MGM3), Pair("${CO}_$MAX_SUFFIX", CO_MAX_MGM3), - Pair("${CH4}_$MIN_SUFFIX", CH4_MIN), - Pair("${CH4}_$MAX_SUFFIX", ppm2mgm3(ch4Lel2ppm(CH4_MAX_LEL), MOLECULAR_CH4)), - Pair("${H2S}_$MIN_SUFFIX", H2S_MIN), - Pair("${H2S}_$MAX_SUFFIX", H2S_MAX_MGM3) + Pair("${CH4}_$MIN_SUFFIX", ppm2mgm3(lel2ppm(CH4_MIN_LEL, CH4_LEL2PPMFACTOR), MOLECULAR_CH4)), + Pair("${CH4}_$MAX_SUFFIX", ppm2mgm3(lel2ppm(CH4_MAX_LEL, CH4_LEL2PPMFACTOR), MOLECULAR_CH4)), + Pair("${H2S}_$MIN_SUFFIX", H2S_MIN_MGM3), + Pair("${H2S}_$MAX_SUFFIX", H2S_MAX_MGM3), + Pair("${H2}_$MIN_SUFFIX", ppm2mgm3(lel2ppm(H2_MIN_LEL, H2_LEL2PPMFACTOR), MOLECULAR_H2)), + Pair("${H2}_$MAX_SUFFIX", ppm2mgm3(lel2ppm(H2_MAX_LEL, H2_LEL2PPMFACTOR), MOLECULAR_H2)), + Pair("${NH3}_$MIN_SUFFIX", NH3_MIN_MGM3), + Pair("${NH3}_$MAX_SUFFIX", NH3_MAX_MGM3), + Pair("${S02}_$MIN_SUFFIX", S02_MIN_MGM3), + Pair("${S02}_$MAX_SUFFIX", S02_MAX_MGM3), + Pair("${CL2}_$MIN_SUFFIX", CL2_MIN_MGM3), + Pair("${CL2}_$MAX_SUFFIX", CL2_MAX_MGM3), + Pair("${NO2}_$MIN_SUFFIX", NO2_MIN_MGM3), + Pair("${NO2}_$MAX_SUFFIX", NO2_MAX_MGM3), + Pair("${NO}_$MIN_SUFFIX", ppm2mgm3(NO_MIN_PPM, MOLECULAR_NO)), + Pair("${NO}_$MAX_SUFFIX", ppm2mgm3(NO_MAX_PPM, MOLECULAR_NO)), + Pair("${HF}_$MIN_SUFFIX", ppm2mgm3(HF_MIN_PPM, MOLECULAR_HF)), + Pair("${HF}_$MAX_SUFFIX", ppm2mgm3(HF_MAX_PPM, MOLECULAR_HF)), + Pair("${C02}_$MIN_SUFFIX", ppm2mgm3(C02_MIN_PPM, MOLECULAR_C02)), + Pair("${C02}_$MAX_SUFFIX", ppm2mgm3(C02_MAX_PPM, MOLECULAR_C02)), ) val default_threshold_map_unit = hashMapOf>( diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasUtilss.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasUtilss.kt index a3f47e2..e58d635 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasUtilss.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/GasUtilss.kt @@ -1,10 +1,21 @@ package com.yinuo.safetywatcher.watcher.port import com.common.commonlib.utils.MMKVUtils +import com.yinuo.safetywatcher.watcher.port.cmd.C02 import com.yinuo.safetywatcher.watcher.port.cmd.CH4 +import com.yinuo.safetywatcher.watcher.port.cmd.CL2 import com.yinuo.safetywatcher.watcher.port.cmd.CO +import com.yinuo.safetywatcher.watcher.port.cmd.GasTypeEnum +import com.yinuo.safetywatcher.watcher.port.cmd.H2 import com.yinuo.safetywatcher.watcher.port.cmd.H2S +import com.yinuo.safetywatcher.watcher.port.cmd.HF +import com.yinuo.safetywatcher.watcher.port.cmd.NH3 +import com.yinuo.safetywatcher.watcher.port.cmd.NO +import com.yinuo.safetywatcher.watcher.port.cmd.NO2 import com.yinuo.safetywatcher.watcher.port.cmd.O2 +import com.yinuo.safetywatcher.watcher.port.cmd.S02 +import com.yinuo.safetywatcher.watcher.port.cmd.VOCS +import com.yinuo.safetywatcher.watcher.port.cmd.getGasTypeEnumByDesc private fun getLowThresHoldKey(gasType: String): String { return "${gasType.uppercase()}_$MIN_SUFFIX" @@ -20,10 +31,10 @@ private fun getHighThresHoldKey(gasType: String): String { */ fun saveLowThreshold(gasType: String, value: Float, localGasUnit: String) { var localValue = value - if (O2 != gasType && UNIT_MGM3 == localGasUnit) { - val molecular = molecular_map[gasType] - molecular?.let { - localValue = mgm3ToPpm(value, it) + if (O2 != gasType && VOCS != gasType && UNIT_MGM3 == localGasUnit) { + val typeEnum = getGasTypeEnumByDesc(gasType) + if (typeEnum.molecular > 0) { + localValue = mgm3ToPpm(value, typeEnum.molecular) } } MMKVUtils.put(getLowThresHoldKey(gasType), localValue) @@ -35,10 +46,10 @@ fun saveLowThreshold(gasType: String, value: Float, localGasUnit: String) { */ fun saveHighThreshold(gasType: String, value: Float, localGasUnit: String) { var localValue = value - if (O2 != gasType && UNIT_MGM3 == localGasUnit) { - val molecular = molecular_map[gasType] - molecular?.let { - localValue = mgm3ToPpm(value, it) + if (O2 != gasType && VOCS != gasType && UNIT_MGM3 == localGasUnit) { + val typeEnum = getGasTypeEnumByDesc(gasType) + if (typeEnum.molecular > 0) { + localValue = mgm3ToPpm(value, typeEnum.molecular) } } MMKVUtils.put(getHighThresHoldKey(gasType), localValue) @@ -55,12 +66,16 @@ fun getGasLowThreshold(gasType: String, unit: String): Float { // 氧气特殊处理 if (O2 == gasType) { return O2_MIN + } else if (VOCS == gasType) { + return VOCS_MIN_MGM3 } return (default_threshold_map_unit[unit])?.get(lowThresholdKey) ?: -1f } else { if (O2 != gasType && UNIT_MGM3 == unit) { - val molecular = molecular_map[gasType] - molecular?.let { localVlaue = ppm2mgm3(localVlaue, it) } + val typeEnum = getGasTypeEnumByDesc(gasType) + if (typeEnum.molecular > 0) { + localVlaue = ppm2mgm3(localVlaue, typeEnum.molecular) + } } } return localVlaue @@ -77,12 +92,16 @@ fun getGasHighThreshold(gasType: String, unit: String): Float { // 氧气特殊处理 if (O2 == gasType) { return O2_MAX + } else if (VOCS == gasType) { + return VOCS_MAX_MGM3 } return (default_threshold_map_unit[unit])?.get(highThresholdKey) ?: -1f } else { if (O2 != gasType && UNIT_MGM3 == unit) { - val molecular = molecular_map[gasType] - molecular?.let { localVlaue = ppm2mgm3(localVlaue, it) } + val typeEnum = getGasTypeEnumByDesc(gasType) + if (typeEnum.molecular > 0) { + localVlaue = ppm2mgm3(localVlaue, typeEnum.molecular) + } } } return localVlaue @@ -95,7 +114,8 @@ fun getGasHighThreshold(gasType: String, unit: String): Float { fun getLocalGasUnit(gasType: String): String { return when (gasType.uppercase()) { O2 -> UNIT_VOL - CO, CH4, H2S -> getDefaultUnit(gasType) + VOCS -> UNIT_VOL // TODO + CO, CH4, H2S, H2, NH3, S02, CL2, NO2, NO, HF, C02 -> getDefaultUnit(gasType) else -> "" } } @@ -118,6 +138,8 @@ fun saveGasUnit(gasType: String, unit: String) { fun getGasRange(gasType: String, gasUnit: String): String { if (gasType == O2) { return O2_RANGE + } else if (gasType == VOCS) { + return VOCS_RANGE } else { if (gasUnit == UNIT_PPM) { return gas_range_ppm[gasType] ?: "" @@ -129,79 +151,38 @@ fun getGasRange(gasType: String, gasUnit: String): String { } fun ppm2mgm3(ppmValue: Float, molecular: Int): Float { - return ppmValue * molecular / (22.4f * TEMPERATURE_COEFFICIENT) + return ppmValue * molecular * PPM_TO_MGM3_CONVERSION_RATE } fun mgm3ToPpm(mValue: Float, molecular: Int): Float { - return mValue * 22.4f * TEMPERATURE_COEFFICIENT / molecular + return mValue / (molecular * PPM_TO_MGM3_CONVERSION_RATE) } -fun ch4Lel2ppm(lelValue: Float): Float { - return lelValue * 10000 / 20f +fun lel2ppm(lelValue: Float, lel2ppmFactor: Float): Float { + return lelValue * lel2ppmFactor } /** * 传感器返回数据气体浓度 单位转换 - * 氧气O2单位固定不用转换 - * 其他三种气体可能需要转换 + * 氧气O2、vocs单位固定不用转换 + * 其他气体可能需要转换 */ fun convertData( - gasType: String, + gasType: GasTypeEnum, value: Float, unit: String, localGasUnit: String ): Float { var retValue = value - if (CH4 == gasType) { - retValue = convertCH4(unit, value, localGasUnit) + // lel需要先转ppm + if (unit == UNIT_LEL) { + retValue = value * gasType.lel2ppmFactor } - // h2s 和 co均只有两种可能场景:ppm->mgm3 mgm3->ppm - else if (H2S == gasType) { - if (UNIT_MGM3 == localGasUnit) { - retValue = ppm2mgm3(retValue, MOLECULAR_H2S) - } else if (UNIT_PPM == localGasUnit) { - retValue = mgm3ToPpm(retValue, MOLECULAR_H2S) - } - } else if (CO == gasType) { - if (UNIT_MGM3 == localGasUnit) { - retValue = ppm2mgm3(retValue, MOLECULAR_CO) - } else if (UNIT_PPM == localGasUnit) { - retValue = mgm3ToPpm(retValue, MOLECULAR_CO) - } + // 有两种可能场景:ppm->mgm3 mgm3->ppm + if (UNIT_MGM3 == localGasUnit) { + retValue = ppm2mgm3(retValue, gasType.molecular) + } else if (UNIT_PPM == localGasUnit) { + retValue = mgm3ToPpm(retValue, gasType.molecular) } return retValue -} - -/** - * ch4 有三种可能单位 lel ppm mg/m3, 其中lel不会作为localGasUnit - * 三种情况: - * 1.lel转ppm或者mgm3 - * 2.ppm转mgm3 - * 3.mgm3转ppm - */ -private fun convertCH4( - unit: String, - value: Float, - localGasUnit: String -): Float { - var ret = value - if (UNIT_LEL == unit) { - // to ppm - ret = ch4Lel2ppm(value) - // 目标是mg/mg3 - if (UNIT_MGM3 == localGasUnit) { - ret = ppm2mgm3(ret, MOLECULAR_CH4) - } - } else if (UNIT_PPM == unit) { - // 目标是mg/mg3 - if (UNIT_MGM3 == localGasUnit) { - ret = ppm2mgm3(ret, MOLECULAR_CH4) - } - } else if (UNIT_MGM3 == unit) { - // 目标是mg/mg3 - if (UNIT_PPM == localGasUnit) { - ret = mgm3ToPpm(ret, MOLECULAR_CH4) - } - } - return ret } \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/ParseHelper.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/ParseHelper.kt index 513b934..af7bae7 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/ParseHelper.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/ParseHelper.kt @@ -10,13 +10,11 @@ import com.common.commonlib.utils.LogUtils import com.common.serialport.utils.HexUtils import com.yinuo.safetywatcher.watcher.constant.GAS_CLOUD_UPLOAD_SIZE_ONCE import com.yinuo.safetywatcher.watcher.net.DevicesApi -import com.yinuo.safetywatcher.watcher.port.cmd.CH4 -import com.yinuo.safetywatcher.watcher.port.cmd.CO import com.yinuo.safetywatcher.watcher.port.cmd.GasPortStatus -import com.yinuo.safetywatcher.watcher.port.cmd.H2S +import com.yinuo.safetywatcher.watcher.port.cmd.GasTypeEnum import com.yinuo.safetywatcher.watcher.port.cmd.O2 import com.yinuo.safetywatcher.watcher.port.cmd.ResponseHelper -import com.yinuo.safetywatcher.watcher.port.cmd.getGasTypeByCode +import com.yinuo.safetywatcher.watcher.port.cmd.getGasTypeEnumByCode import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -32,7 +30,7 @@ object ParseHelper { private val devicesApi by lazy { DevicesApi() } - private val gasMap = hashMapOf() + private val gasMap = hashMapOf() fun parse(it: ByteArray) { try { @@ -40,8 +38,8 @@ object ParseHelper { LogUtils.v("receive msg, ${HexUtils.byteArrToHex(it)}") val gasIndex = it[0].toInt() val status = it[14].toInt() - val gasType = getGasTypeByCode(it[19].toInt()) - if (gasType.isEmpty()) { + val gasType = getGasTypeEnumByCode(it[19].toInt()) + if (gasType == GasTypeEnum.TYPE_UNKNOW) { LogUtils.v("receive msg, unknown gas") return } @@ -74,7 +72,7 @@ object ParseHelper { } } - private fun parseGasData(gasType: String, it: ByteArray) { + private fun parseGasData(type: GasTypeEnum, it: ByteArray) { val unitHex: String = HexUtils.byteArrToHex(it, 3, 3 + 2) val unitToLong: Long = HexUtils.hexToLong(unitHex) // 10000000000000 @@ -108,66 +106,118 @@ object ParseHelper { val rangHex: String = HexUtils.byteArrToHex(it, 11, 11 + 2) val rangHexLong: Long = HexUtils.hexToLong(rangHex) - LogUtils.w("receive msg 单位转换前 $gasType, 浓度 = $value $unit") + LogUtils.w("receive msg 单位转换前 $type.desc, 浓度 = $value $unit") //根据单位进行数值转换 - val localGasUnit = getLocalGasUnit(gasType) + val localGasUnit = getLocalGasUnit(type.desc) if (localGasUnit != unit) { - value = convertData(gasType, value, unit, localGasUnit) - LogUtils.w("receive msg 单位转换后 $gasType, 浓度 = $value $localGasUnit") + value = convertData(type, value, unit, localGasUnit) + LogUtils.w("receive msg 单位转换后 $type.desc, 浓度 = $value $localGasUnit") } - // 存储临时数据 - gasMap[gasType] = " : $value $localGasUnit" // 插入 - insertGasData(gasType, value, localGasUnit) + insertGasData(type, value, localGasUnit) } private fun setOverlayData() { - val valueCo = gasMap[CO] - val valueCH4 = gasMap[CH4] - val valueO2 = gasMap[O2] - val valueH2S = gasMap[H2S] - val builder: StringBuilder = java.lang.StringBuilder() - valueCo?.let { - builder.append(CO).append(valueCo).append("@") - } - valueCH4?.let { - builder.append(CH4).append(valueCH4).append("@") - } - valueO2?.let { - builder.append(O2).append(valueO2).append("@") - } - valueH2S?.let { - builder.append(H2S).append(valueH2S) + gasMap.forEach { item -> + val gas = item.value + val time = gas.time + // 3S内的数据我们认为有效 + if (System.currentTimeMillis() - time <= 3000) { + builder.append(gas.gasName).append(gas.gasValue).append("@") + } } +// val valueCo = gasMap[CO] +// val valueCH4 = gasMap[CH4] +// val valueO2 = gasMap[O2] +// val valueH2S = gasMap[H2S] +// +// valueCo?.let { +// builder.append(CO).append(valueCo).append("@") +// } +// valueCH4?.let { +// builder.append(CH4).append(valueCH4).append("@") +// } +// valueO2?.let { +// builder.append(O2).append(valueO2).append("@") +// } +// valueH2S?.let { +// builder.append(H2S).append(valueH2S) +// } TxtOverlay.setShowTip(builder.toString()) } /** * 插入气体数据 */ - private fun insertGasData(gasType: String, value: Float, unit: String) { + private fun insertGasData(typeEnum: GasTypeEnum, value: Float, unit: String) { GlobalScope.launch(Dispatchers.IO) { // 阈值范围 - val min = getGasLowThreshold(gasType, unit) - val max = getGasHighThreshold(gasType, unit) + val min = getGasLowThreshold(typeEnum.desc, unit) + val max = getGasHighThreshold(typeEnum.desc, unit) // 构造气体数据 val timeMillis = System.currentTimeMillis() - val gas = Gas(timeMillis, gasType, value, unit, min, max) + val gas = Gas(timeMillis, typeEnum.desc, value, unit, min, max) + + // 存储临时数据 + gasMap[typeEnum.desc] = gas + val gasDao = DBUtils.gasDao() gasDao.insert(gas) - // 告警处理 - val warningDao = DBUtils.warningDao() - val warning = warningDao.findLatestByName(gasType) + dealWarning(typeEnum, value, min, max, unit) + + // 设置水印数据 + setOverlayData() + + // 实时数据上传后台 + uploadGasData(gas) + } + } + + private suspend fun dealWarning( + typeEnum: GasTypeEnum, + value: Float, + min: Float, + max: Float, + unit: String + ) { + // 告警处理 + val warningDao = DBUtils.warningDao() + val warning = warningDao.findLatestByName(typeEnum.desc) + // 氧气特殊处理,要在min和max之间,其他其他大于min(一级告警阈值)或者max(二级告警阈值)均报警,max>min。所以判断>min就报警 + if (O2 == typeEnum.desc) { if (value < min || value > max) { if (warning == null || warning.endTime > 0) { warningDao.insert( Warning( - gasType, + typeEnum.desc, + value, + unit, + System.currentTimeMillis(), + min, + max + ) + ) + } else { + warning.gasValue = value + warningDao.update(warning) + } + } else { + warning?.let { + it.endTime = System.currentTimeMillis() + warningDao.update(it) + } + } + } else { + if (value > min) { + if (warning == null || warning.endTime > 0) { + warningDao.insert( + Warning( + typeEnum.desc, value, unit, System.currentTimeMillis(), @@ -185,12 +235,6 @@ object ParseHelper { warningDao.update(it) } } - - // 设置水印数据 - setOverlayData() - - // 实时数据上传后台 - uploadGasData(gas) } } @@ -211,24 +255,24 @@ object ParseHelper { * 更新数据库 */ @OptIn(DelicateCoroutinesApi::class) - private fun updateGasTypeDb(gasName: String, status: Int) { + private fun updateGasTypeDb(type: GasTypeEnum, status: Int) { GlobalScope.launch { val typeDao = DBUtils.gasTypeDao() - val gasType = typeDao.getByName(gasName) + val gasType = typeDao.getByName(type.desc) gasType?.status = status - typeDao.insert(gasType ?: GasType(gasName, status)) + typeDao.insert(gasType ?: GasType(type.desc, status)) } } /** * 启动离线检查 */ - private fun setFlag(index: Int, gasName: String) { + private fun setFlag(index: Int, type: GasTypeEnum) { var flagRunnable = mPortRunnable[index] if (flagRunnable != null) { mHandler.removeCallbacks(flagRunnable) } - flagRunnable = FlagRunnable(gasName) + flagRunnable = FlagRunnable(type) mPortRunnable[index] = flagRunnable // 如果一段时间内没有收到消息,认为连接断开 mHandler.postDelayed(flagRunnable, GasPortUtils.CHECK_TIME) @@ -238,7 +282,7 @@ object ParseHelper { * 离线检查 */ class FlagRunnable( - private val gasName: String + private val gasName: GasTypeEnum ) : Runnable { override fun run() { updateGasTypeDb(gasName, GasPortStatus.OUTLINE) diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasType.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasType.kt deleted file mode 100644 index 845914d..0000000 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasType.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.yinuo.safetywatcher.watcher.port.cmd - -const val CO = "CO" -const val CH4 = "CH4" -const val O2 = "O2" -const val H2S = "H2S" -const val H2 = "H2" -const val NH3 = "NH3" -const val S02 = "S02" -const val CL2 = "CL2" -const val NO2 = "NO2" -const val NO = "NO" -const val HF = "HF" -const val C02 = "C02" -const val VOCs = "VOCs" - -enum class GasType(val code: Int, val desc: String) { - TYPE_CO(5, CO), - TYPE_CH4(11, CH4), - TYPE_O2(67, O2), - TYPE_H2S(52, H2S) -} - -fun getGasTypeByCode(code: Int): String { - val codes = GasType.values(); - codes.forEach { - if (code == it.code) { - return it.desc; - } - } - return "" -} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasTypeEnum.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasTypeEnum.kt new file mode 100644 index 0000000..4d7e740 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/port/cmd/GasTypeEnum.kt @@ -0,0 +1,77 @@ +package com.yinuo.safetywatcher.watcher.port.cmd + +const val CO = "CO" +const val CH4 = "CH4" +const val O2 = "O2" +const val H2S = "H2S" +const val H2 = "H2" +const val NH3 = "NH3" +const val S02 = "S02" +const val CL2 = "CL2" +const val NO2 = "NO2" +const val NO = "NO" +const val HF = "HF" +const val C02 = "C02" +const val VOCS = "VOCS" + +/** + * 气体分子质量 + */ +const val MOLECULAR_CO = 28 +const val MOLECULAR_H2S = 34 +const val MOLECULAR_CH4 = 16 +const val MOLECULAR_O2 = 32 +const val MOLECULAR_H2 = 2 +const val MOLECULAR_NH3 = 17 +const val MOLECULAR_S02 = 64 +const val MOLECULAR_CL2 = 71 +const val MOLECULAR_NO2 = 46 +const val MOLECULAR_NO = 30 +const val MOLECULAR_HF = 20 +const val MOLECULAR_C02 = 44 + +const val CH4_LEL2PPMFACTOR = 500f +const val H2S_LEL2PPMFACTOR = 430f +const val H2_LEL2PPMFACTOR = 400f + +enum class GasTypeEnum( + val code: Int, + val desc: String, + val molecular: Int = -1, + val lel2ppmFactor: Float = 0f +) { + TYPE_CO(5, CO, MOLECULAR_CO), + TYPE_CH4(11, CH4, MOLECULAR_H2S, CH4_LEL2PPMFACTOR), + TYPE_O2(67, O2, MOLECULAR_CH4), + TYPE_H2S(52, H2S, MOLECULAR_O2, H2S_LEL2PPMFACTOR), + TYPE_H2(52, H2, MOLECULAR_H2, H2_LEL2PPMFACTOR), + TYPE_NH3(52, NH3, MOLECULAR_NH3), + TYPE_S02(52, S02, MOLECULAR_S02), + TYPE_CL2(52, CL2, MOLECULAR_CL2), + TYPE_NO2(52, NO2, MOLECULAR_NO2), + TYPE_NO(52, NO, MOLECULAR_NO), + TYPE_HF(52, HF, MOLECULAR_HF), + TYPE_C02(52, C02, MOLECULAR_C02), + TYPE_VOCS(52, VOCS), + TYPE_UNKNOW(-1, "UNKNOW") +} + +fun getGasTypeEnumByCode(code: Int): GasTypeEnum { + val codes = GasTypeEnum.values(); + codes.forEach { + if (code == it.code) { + return it; + } + } + return GasTypeEnum.TYPE_UNKNOW +} + +fun getGasTypeEnumByDesc(desc: String): GasTypeEnum { + val codes = GasTypeEnum.values(); + codes.forEach { + if (desc == it.desc) { + return it; + } + } + return GasTypeEnum.TYPE_UNKNOW +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/QueryDataActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/QueryDataActivity.kt index 352f5d8..0123465 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/QueryDataActivity.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/QueryDataActivity.kt @@ -14,6 +14,7 @@ import com.yinuo.safetywatcher.databinding.ActivityQueryDataBinding import com.yinuo.safetywatcher.watcher.base.BaseActivity import com.yinuo.safetywatcher.watcher.constant.DEFAULT_QUERY_TIME_INTERVAL import com.yinuo.safetywatcher.watcher.constant.TimeStep +import com.yinuo.safetywatcher.watcher.port.cmd.getGasTypeEnumByDesc import com.yinuo.safetywatcher.watcher.port.convertData import com.yinuo.safetywatcher.watcher.port.getLocalGasUnit import com.yinuo.safetywatcher.watcher.ui.adapter.HistoryDataAdapter @@ -218,7 +219,8 @@ class QueryDataActivity : BaseActivity() { val localGasUnit = getLocalGasUnit(it.gasName) val unit = it.unit if (unit != localGasUnit) { - it.gasValue = convertData(it.gasName, it.gasValue, unit, localGasUnit) + val typeEnum = getGasTypeEnumByDesc(it.gasName) + it.gasValue = convertData(typeEnum, it.gasValue, unit, localGasUnit) it.unit = localGasUnit } return it diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/WarnDataAdapter.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/WarnDataAdapter.kt index ac5f99b..7ec3ab9 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/WarnDataAdapter.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/adapter/WarnDataAdapter.kt @@ -14,7 +14,10 @@ class WarnDataAdapter : BaseRvAdapter.BaseViewHolder(binding) { override fun bindView(data: Warning) { binding.tvTime.text = formatTime(data.startTime) - binding.tvSensor.text = "${data.gasName}浓度异常,${data.gasValue} ${data.unit}" + val standardStr = + if (data.gasValue > data.thresholdHigh) "超过高报警值${data.thresholdHigh}" else "超过低报警值${data.thresholdLow}" + binding.tvSensor.text = + "${data.gasName}浓度异常,${data.gasValue} ${data.unit}$standardStr" } private fun formatTime(time: Long): CharSequence? {