diff --git a/modules/mogo-module-share/src/main/java/com/mogo/module/share/StrategyShareProvider.kt b/modules/mogo-module-share/src/main/java/com/mogo/module/share/StrategyShareProvider.kt index 2a15148a56..9f2f99b2cb 100644 --- a/modules/mogo-module-share/src/main/java/com/mogo/module/share/StrategyShareProvider.kt +++ b/modules/mogo-module-share/src/main/java/com/mogo/module/share/StrategyShareProvider.kt @@ -35,8 +35,7 @@ class StrategyShareProvider : IProvider { // if(!DebugConfig.isLauncher()) { apis.registerCenterApi.registerMogoLocationListener(MogoServicePaths.PATH_STRATEGY_SHARE) { // Logger.d(S_TAG,"定位发生变化,准备记录速度: ${it.speed}") - blockStrategy.recordSpeed(it.speed * 3.6F) - blockStrategy.recordLocation(it.latitude, it.longitude) + blockStrategy.recordSpeed(it.speed * 3.6F, it.latitude, it.longitude) } apis.adasControllerApi.addAdasDataCallback { diff --git a/modules/mogo-module-share/src/main/java/com/mogo/module/share/strategyreceiver/BlockStrategy.kt b/modules/mogo-module-share/src/main/java/com/mogo/module/share/strategyreceiver/BlockStrategy.kt index 19a7b967f5..6bb1360d4f 100644 --- a/modules/mogo-module-share/src/main/java/com/mogo/module/share/strategyreceiver/BlockStrategy.kt +++ b/modules/mogo-module-share/src/main/java/com/mogo/module/share/strategyreceiver/BlockStrategy.kt @@ -17,9 +17,12 @@ import com.mogo.service.share.TanluUploadParams import com.mogo.utils.logger.Logger import com.mogo.utils.network.RequestOptions import com.mogo.utils.network.utils.GsonUtil +import com.mogo.utils.storage.SharedPrefsMgr import io.reactivex.schedulers.Schedulers import okhttp3.MediaType import okhttp3.RequestBody +import java.util.* +import kotlin.collections.ArrayList /** @@ -35,6 +38,21 @@ private const val TAG = "BlockUploadStrategy" private const val DISTANCE_RECORD_TIME = 3 * 60 * 1000L +private const val MORNING_PEAK_START_MINUTE = 7 * 60 + 30 +private const val MORNING_PEAK_STOP_MINUTE = 9 * 60 + 30 + +private const val NIGHT_PEAK_START_MINUTE = 17 * 60 + 30 +private const val NIGHT_PEAK_STOP_MINUTE = 19 * 60 + 30 + +private const val DISTANCE_MORNING_PEAK_COUNT = "DISTANCE_MORNING_PEAK_COUNT" +private const val DISTANCE_NIGHT_PEAK_COUNT = "DISTANCE_NIGHT_PEAK_COUNT" +private const val DISTANCE_NORMAL_COUNT = "DISTANCE_NORMAL_COUNT" + + +private const val SPEED_MORNING_PEAK_COUNT = "SPEED_MORNING_PEAK_COUNT" +private const val SPEED_NIGHT_PEAK_COUNT = "SPEED_NIGHT_PEAK_COUNT" +private const val SPEED_NORMAL_COUNT = "SPEED _NORMAL_COUNT" + /** * 用于计算拥堵策略 */ @@ -61,9 +79,17 @@ class BlockStrategy(private val context: Context, private val apis: IMogoService * 停车标志为累加超过[STOP_FLAG_THRESHOLD]判定为停车,不是拥堵,舍弃掉整个两分钟数据,不进行上报, * 否则上报服务端,返回是否抓取视频 * + * * 距离策略上报 + * + * 1. 过去3分钟,行驶距离<1km,大于30m + * 2. 前车距离<5m,获取不到前车距离时,默认此项满足 + * 3. 当前车速<40km/h + * + * 满足上述条件,自动上报拥堵 + * * @param speed 当前速度,单位需要是Km/h */ - fun recordSpeed(speed: Float) { + fun recordSpeed(speed: Float, lat: Double, lon: Double) { currentSpeed = speed.toInt() val current = SystemClock.uptimeMillis() if (startRecordTime == 0L) { @@ -82,7 +108,27 @@ class BlockStrategy(private val context: Context, private val apis: IMogoService stopFlag = 0 } - if (current - startRecordTime >= SPEED_RECORD_TIME_INTERVAL) { + if (lastLat == 0.0) { + // 定位初始化,只判断一个就行了 + lastLon = lon + lastLat = lat + } else { + // 记录行进距离 + tripDistance += com.mogo.module.service.Utils.calculateLineDistance(lastLon, lastLat, lon, lat).toInt() + lastLon = lon + lastLat = lat + } + + if (current - startRecordTime >= DISTANCE_RECORD_TIME) { + + var blockFromSpeed = false + var blockFromDistance = false + + var latLonFromSpeed: MogoLatLng? = null + var latLonFromDistance: MogoLatLng? = null + + val p = TanluUploadParams(IMogoTanluProvider.TYPE_BLOCK, IMogoTanluProvider.UPLOAD_FROM_STRATEGY_BLOCK_AUTO) + // 到达时间限制,上报速度,数据清空 if (stopFlag < STOP_FLAG_THRESHOLD) { // 停车标志位小于阈值,判定不是停车,计算平均值,进行上报 @@ -92,12 +138,85 @@ class BlockStrategy(private val context: Context, private val apis: IMogoService } val ave = sum / speedCacheList.size Logger.d(TAG, "平均速度为: $ave") + blockFromSpeed = true // 上报平均速度 - uploadAverageSpeed(ave) + val location = ServiceApisManager.serviceApis.mapServiceApi.getSingletonLocationClient(context).lastKnowLocation + latLonFromSpeed = MogoLatLng(location.latitude, location.longitude) } else { Logger.d(TAG, "判定为停车,不进行上报") } + + // 超过阈值,准备判断是否拥堵 + if (tripDistance in 100..1000 && isClose() && currentSpeed < 40) { + Logger.d(TAG, "根据距离,判定为拥堵,准备上报, tripDistance: $tripDistance, frontDistance: $frontDistance, currentSpeed: $currentSpeed") + latLonFromDistance = MogoLatLng(lat, lon) + blockFromDistance = true + } else { + Logger.d(TAG, "根据距离,没有判定为拥堵, tripDistance: $tripDistance, frontDistance: $frontDistance, currentSpeed: $currentSpeed") + } + tripDistance = 0 + lastLat = 0.0 + lastLon = 0.0 startRecordTime = 0 + + if (blockFromDistance || blockFromSpeed) { + Logger.d(TAG, "判定拥堵,准备上报 blockFromDistance: $blockFromDistance, blockFromSpeed: $blockFromSpeed") + if (isMorningPeak()) { + val distanceMorningCount = SharedPrefsMgr.getInstance(context).getInt(DISTANCE_MORNING_PEAK_COUNT, 0) + val speedMorningCount = SharedPrefsMgr.getInstance(context).getInt(SPEED_MORNING_PEAK_COUNT, 0) + if (blockFromDistance && distanceMorningCount < 2) { + Logger.d(TAG, "按距离策略上报早高峰") + SharedPrefsMgr.getInstance(context).putInt(DISTANCE_MORNING_PEAK_COUNT, distanceMorningCount + 1) + p.location = latLonFromDistance + apis.analyticsApi.track("v2x_share_autoUpload", mapOf("type" to 1)) + apis.tanluApi.uploadRoadCondition(p) + return + } + if (blockFromSpeed && speedMorningCount < 2) { + Logger.d(TAG, "按速度策略上报早高峰") + SharedPrefsMgr.getInstance(context).putInt(SPEED_MORNING_PEAK_COUNT, speedMorningCount + 1) + p.location = latLonFromSpeed + apis.tanluApi.uploadRoadCondition(p) + return + } + } else if (isNightPeak()) { + val distanceNightCount = SharedPrefsMgr.getInstance(context).getInt(DISTANCE_NIGHT_PEAK_COUNT, 0) + val speedNightCount = SharedPrefsMgr.getInstance(context).getInt(SPEED_NIGHT_PEAK_COUNT, 0) + if (blockFromDistance && distanceNightCount < 3) { + Logger.d(TAG, "按距离策略上报晚高峰") + SharedPrefsMgr.getInstance(context).putInt(DISTANCE_NIGHT_PEAK_COUNT, distanceNightCount + 1) + p.location = latLonFromDistance + apis.analyticsApi.track("v2x_share_autoUpload", mapOf("type" to 1)) + apis.tanluApi.uploadRoadCondition(p) + return + } + if (blockFromSpeed && speedNightCount < 3) { + Logger.d(TAG, "按速度策略上报晚高峰") + SharedPrefsMgr.getInstance(context).putInt(SPEED_NIGHT_PEAK_COUNT, speedNightCount + 1) + p.location = latLonFromSpeed + apis.tanluApi.uploadRoadCondition(p) + return + } + } else { + val distanceNormalCount = SharedPrefsMgr.getInstance(context).getInt(DISTANCE_NORMAL_COUNT, 0) + val speedNormalCount = SharedPrefsMgr.getInstance(context).getInt(SPEED_NORMAL_COUNT, 0) + if (blockFromDistance && distanceNormalCount < 5) { + Logger.d(TAG, "按距离策略上报一般时段") + SharedPrefsMgr.getInstance(context).putInt(DISTANCE_NORMAL_COUNT, distanceNormalCount + 1) + p.location = latLonFromDistance + apis.analyticsApi.track("v2x_share_autoUpload", mapOf("type" to 1)) + apis.tanluApi.uploadRoadCondition(p) + return + } + if (blockFromSpeed && speedNormalCount < 5) { + Logger.d(TAG, "按速度策略上报早高峰") + SharedPrefsMgr.getInstance(context).putInt(SPEED_NORMAL_COUNT, speedNormalCount + 1) + p.location = latLonFromSpeed + apis.tanluApi.uploadRoadCondition(p) + return + } + } + } } } @@ -109,82 +228,37 @@ class BlockStrategy(private val context: Context, private val apis: IMogoService */ private var tripDistance: Int = 0 - /** - * 距离策略上报 - * - * 1. 过去3分钟,行驶距离<1km,大于30m - * 2. 前车距离<5m,获取不到前车距离时,默认此项满足 - * 3. 当前车速<40km/h - * - * 满足上述条件,自动上报拥堵 - */ - fun recordLocation(lat: Double, lon: Double) { - if (lastLat == 0.0) { - // 定位初始化,只判断一个就行了 - lastLon = lon - lastLat = lat - } else { - // 记录行进距离 - tripDistance += com.mogo.module.service.Utils.calculateLineDistance(lastLon, lastLat, lon, lat).toInt() - lastLon = lon - lastLat = lat - val current = SystemClock.uptimeMillis() - if (startRecordDistanceTime == 0L) { - startRecordDistanceTime = current - } - - if (current - startRecordDistanceTime >= DISTANCE_RECORD_TIME) { - // 超过阈值,准备判断是否拥堵 - startRecordDistanceTime = 0L - if (tripDistance in 100..1000 && isClose() && currentSpeed < 40) { - Logger.d(TAG, "根据距离,判定为拥堵,准备上报, tripDistance: $tripDistance, frontDistance: $frontDistance, currentSpeed: $currentSpeed") - val p = TanluUploadParams(IMogoTanluProvider.TYPE_BLOCK, IMogoTanluProvider.UPLOAD_FROM_STRATEGY_BLOCK_AUTO) - val latLon = MogoLatLng(lat, lon) - p.location = latLon - // 疑似拥堵埋点上报 - apis.analyticsApi.track("v2x_share_autoUpload", mapOf("type" to 1)) - apis.tanluApi.uploadRoadCondition(p) - } else { - Logger.d(TAG, "根据距离,没有判定为拥堵, tripDistance: $tripDistance, frontDistance: $frontDistance, currentSpeed: $currentSpeed") - } - tripDistance = 0 - lastLat = 0.0 - lastLon = 0.0 - } - } - } - /** * 没有有效前车距离或者前车距离小于5m */ private fun isClose(): Boolean { val r = (frontDistance in 1..4) || (frontDistance == -1) - Logger.d(TAG,"r: $r") + Logger.d(TAG, "r: $r") return r } - private fun uploadAverageSpeed(average: Float) { - val params = ArrayMap() - params["speed"] = average.toInt() - val body = RequestBody.create(MediaType.parse("Content-type:application/json;charset=UTF-8"), GsonUtil.jsonFromObject(params)) - apis.networkApi.create(ShareApiService::class.java, HttpConstant.getNetHost()).sendAverageSpeedForBlockStrategy(body, Utils.getSn()).subscribeOn(Schedulers.io()).subscribe(object : SubscribeImpl(RequestOptions.create(context)) { - override fun onSuccess(response: AverateSpeedResponse?) { - super.onSuccess(response) - response?.let { - Logger.d(TAG, "收到服务端返回结果: $it") - // 收到服务端回调,视情况进行视频上报 - if (it.result.upload) { - val p = TanluUploadParams(it.result.poiType, IMogoTanluProvider.UPLOAD_FROM_STRATEGY_BLOCK_AUTO) - val location = ServiceApisManager.serviceApis.mapServiceApi.getSingletonLocationClient(context).lastKnowLocation - val latLon = MogoLatLng(location.latitude, location.longitude) - p.location = latLon - apis.tanluApi.uploadRoadCondition(p) - } - } - } - - }) - } +// private fun uploadAverageSpeed(average: Float) { +// val params = ArrayMap() +// params["speed"] = average.toInt() +// val body = RequestBody.create(MediaType.parse("Content-type:application/json;charset=UTF-8"), GsonUtil.jsonFromObject(params)) +// apis.networkApi.create(ShareApiService::class.java, HttpConstant.getNetHost()).sendAverageSpeedForBlockStrategy(body, Utils.getSn()).subscribeOn(Schedulers.io()).subscribe(object : SubscribeImpl(RequestOptions.create(context)) { +// override fun onSuccess(response: AverateSpeedResponse?) { +// super.onSuccess(response) +// response?.let { +// Logger.d(TAG, "收到服务端返回结果: $it") +// // 收到服务端回调,视情况进行视频上报 +// if (it.result.upload) { +// val p = TanluUploadParams(it.result.poiType, IMogoTanluProvider.UPLOAD_FROM_STRATEGY_BLOCK_AUTO) +// val location = ServiceApisManager.serviceApis.mapServiceApi.getSingletonLocationClient(context).lastKnowLocation +// val latLon = MogoLatLng(location.latitude, location.longitude) +// p.location = latLon +// apis.tanluApi.uploadRoadCondition(p) +// } +// } +// } +// +// }) +// } companion object { const val MSG_FRONT_DISTANCE_CHECK = 1001 @@ -207,4 +281,22 @@ class BlockStrategy(private val context: Context, private val apis: IMogoService frontDistance = distance handler.sendEmptyMessageDelayed(MSG_FRONT_DISTANCE_CHECK, FRONT_DISTANCE_CHECK_DELAY) } + + /** + * 是否是早高峰 + */ + private fun isMorningPeak(): Boolean { + val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + val minute = Calendar.getInstance().get(Calendar.MINUTE) + hour * 60 + return minute in MORNING_PEAK_START_MINUTE..MORNING_PEAK_STOP_MINUTE + } + + /** + * 是否在晚高峰 + */ + private fun isNightPeak(): Boolean { + val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + val minute = Calendar.getInstance().get(Calendar.MINUTE) + hour * 60 + return minute in NIGHT_PEAK_START_MINUTE..NIGHT_PEAK_STOP_MINUTE + } } \ No newline at end of file