desc:云平台数据同步

main
xiaowusky 2 years ago
parent eb1be18330
commit 2c2d2b0fac

@ -87,17 +87,17 @@ object TestUtils {
} }
fun testUploadFile(uploadApi: UploadFileApi, video: Video, commonDialog: CommonDialog?) { fun testUploadFile(uploadApi: UploadFileApi, video: Video, commonDialog: CommonDialog?) {
val path = video.path // val path = video.path
uploadApi.singleUpload(path, System.currentTimeMillis(), object : // uploadApi.singleUpload(path, System.currentTimeMillis(), object :
RequestResultCallBack<BaseResponse>() { // RequestResultCallBack<BaseResponse>() {
override fun onResult(result: BaseResponse) { // override fun onResult(result: BaseResponse) {
commonDialog?.dismiss() // commonDialog?.dismiss()
} // }
//
override fun onError(error: String?) { // override fun onError(error: String?) {
commonDialog?.dismiss() // commonDialog?.dismiss()
} // }
}) // })
} }
fun testExportExcel(context: Context, datas: MutableList<Gas>, commonDialog: CommonDialog?) { fun testExportExcel(context: Context, datas: MutableList<Gas>, commonDialog: CommonDialog?) {

@ -77,6 +77,7 @@ abstract class BaseActivity : AppCompatActivity() {
fun closeLoadingDialog() { fun closeLoadingDialog() {
loadingDialog?.dismiss() loadingDialog?.dismiss()
loadingDialog = null
} }
open val isHome: Boolean = false open val isHome: Boolean = false
@ -132,4 +133,9 @@ abstract class BaseActivity : AppCompatActivity() {
fun tryFocusBackArea() { fun tryFocusBackArea() {
baseBinding.topBar.tryFocusBackArea() baseBinding.topBar.tryFocusBackArea()
} }
override fun onDestroy() {
super.onDestroy()
closeLoadingDialog()
}
} }

@ -21,4 +21,4 @@ const val DELAY_TIME_CHECK_CAMERA = 5
const val NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android" const val NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"
// 云同步时20条数据已上传 // 云同步时20条数据已上传
const val GAS_CLOUD_UPLOAD_SIZE_ONCE = 20; const val GAS_CLOUD_UPLOAD_SIZE_ONCE = 20

@ -42,24 +42,23 @@ class DevicesApi : BaseObserve<DevicesApi.Api>(Api::class.java) {
observe(api.updateTrafficInfo(trafficReqInfo), null) observe(api.updateTrafficInfo(trafficReqInfo), null)
} }
fun uploadGasData( suspend fun uploadGasData(
gasList: List<Gas> = emptyList(), gasList: List<Gas> = emptyList()
callBack: RequestResultCallBack<BaseResponse> ): BaseResponse {
) {
val detections = arrayListOf<GasReqBean>() val detections = arrayListOf<GasReqBean>()
gasList.forEach { gasList.forEach {
detections.add(GasReqBean(it)) detections.add(GasReqBean(it))
} }
val gasReq = GasRequest(detections = detections) val gasReq = GasRequest(detections = detections)
observe(api.uploadGasData(gasReq), callBack) return api.uploadGasData(gasReq)
} }
fun getDetectionLastTime(callBack: RequestResultCallBack<LastTimeResponse>) { suspend fun getDetectionLastTime() : LastTimeResponse{
observe(api.getDetectionLastTime(LztekUtil.getSn()), callBack) return api.getDetectionLastTime(LztekUtil.getSn())
} }
fun getVideoLastTime(callBack: RequestResultCallBack<LastTimeResponse>) { suspend fun getVideoLastTime(): LastTimeResponse {
observe(api.getVideoLastTime(LztekUtil.getSn()), callBack) return api.getVideoLastTime(LztekUtil.getSn())
} }
interface Api { interface Api {
@ -78,14 +77,14 @@ class DevicesApi : BaseObserve<DevicesApi.Api>(Api::class.java) {
@Headers("baseurl:host") @Headers("baseurl:host")
@POST("/api/device/addDetection") @POST("/api/device/addDetection")
fun uploadGasData(@Body body: GasRequest): Observable<BaseResponse> suspend fun uploadGasData(@Body body: GasRequest): BaseResponse
@Headers("baseurl:host") @Headers("baseurl:host")
@GET("/api/device/getDetectionLastTime") @GET("/api/device/getDetectionLastTime")
fun getDetectionLastTime(@Query("deviceSn") sn: String): Observable<LastTimeResponse> suspend fun getDetectionLastTime(@Query("deviceSn") sn: String): LastTimeResponse
@Headers("baseurl:host") @Headers("baseurl:host")
@GET("/api/device/getVideoLastTime") @GET("/api/device/getVideoLastTime")
fun getVideoLastTime(@Query("deviceSn") sn: String): Observable<LastTimeResponse> suspend fun getVideoLastTime(@Query("deviceSn") sn: String): LastTimeResponse
} }
} }

@ -2,9 +2,7 @@ package com.yinuo.safetywatcher.watcher.net
import com.common.commonlib.net.BaseObserve import com.common.commonlib.net.BaseObserve
import com.common.commonlib.net.bean.BaseResponse import com.common.commonlib.net.bean.BaseResponse
import com.common.commonlib.net.callback.RequestResultCallBack
import com.yinuo.safetywatcher.watcher.utils.LztekUtil import com.yinuo.safetywatcher.watcher.utils.LztekUtil
import io.reactivex.rxjava3.core.Observable
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
@ -24,25 +22,21 @@ const val FORM_DATA = "multipart/form-data";
*/ */
class UploadFileApi : BaseObserve<UploadFileApi.Api>(Api::class.java) { class UploadFileApi : BaseObserve<UploadFileApi.Api>(Api::class.java) {
open fun singleUpload( suspend fun singleUpload(
path: String, path: String,
videoTime: Long, videoTime: Long
callBack: RequestResultCallBack<BaseResponse> ): BaseResponse {
) { return api.singleUpload(makeParamsMaps(videoTime), makeFileBodyPart(path))
observe(
api.singleUpload(makeParamsMaps(videoTime), makeFileBodyPart(path)),
callBack
)
} }
interface Api { interface Api {
@Headers("baseurl:host") @Headers("baseurl:host")
@Multipart @Multipart
@POST("/common/uploadVideo") @POST("/common/uploadVideo")
fun singleUpload( suspend fun singleUpload(
@PartMap params: Map<String, @JvmSuppressWildcards RequestBody>, @PartMap params: Map<String, @JvmSuppressWildcards RequestBody>,
@Part file: MultipartBody.Part @Part file: MultipartBody.Part
): Observable<BaseResponse> ): BaseResponse
} }
private fun makeFileBodyPart(path: String): MultipartBody.Part { private fun makeFileBodyPart(path: String): MultipartBody.Part {

@ -6,20 +6,18 @@ import android.view.View
import com.common.commonlib.db.DBUtils import com.common.commonlib.db.DBUtils
import com.common.commonlib.db.entity.Gas import com.common.commonlib.db.entity.Gas
import com.common.commonlib.db.entity.Video import com.common.commonlib.db.entity.Video
import com.common.commonlib.net.bean.BaseResponse
import com.common.commonlib.net.callback.RequestResultCallBack
import com.yinuo.library.vlc.utils.LogUtils import com.yinuo.library.vlc.utils.LogUtils
import com.yinuo.safetywatcher.R import com.yinuo.safetywatcher.R
import com.yinuo.safetywatcher.TestUtils
import com.yinuo.safetywatcher.databinding.ActivityCloudBinding import com.yinuo.safetywatcher.databinding.ActivityCloudBinding
import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity
import com.yinuo.safetywatcher.watcher.bean.LastTimeResponse
import com.yinuo.safetywatcher.watcher.constant.GAS_CLOUD_UPLOAD_SIZE_ONCE import com.yinuo.safetywatcher.watcher.constant.GAS_CLOUD_UPLOAD_SIZE_ONCE
import com.yinuo.safetywatcher.watcher.net.DevicesApi import com.yinuo.safetywatcher.watcher.net.DevicesApi
import com.yinuo.safetywatcher.watcher.net.UploadFileApi import com.yinuo.safetywatcher.watcher.net.UploadFileApi
import com.yinuo.safetywatcher.watcher.utils.showToast
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean
class CloudActivity : NoOptionsActivity() { class CloudActivity : NoOptionsActivity() {
private val mBinding: ActivityCloudBinding by lazy { private val mBinding: ActivityCloudBinding by lazy {
@ -34,7 +32,10 @@ class CloudActivity : NoOptionsActivity() {
DevicesApi() DevicesApi()
} }
override fun getTopBarTitle(): String? { private var uploadingGas = AtomicBoolean(false)
private var uploadingVideo = AtomicBoolean(false)
override fun getTopBarTitle(): String {
return getString(R.string.cloud) return getString(R.string.cloud)
} }
@ -45,14 +46,32 @@ class CloudActivity : NoOptionsActivity() {
override fun initView() { override fun initView() {
mBinding.apply { mBinding.apply {
syncSensor.setOnClickListener { syncSensor.setOnClickListener {
if (uploadingGas.get()) {
showToast(getString(R.string.repeat_click_sync_tip))
return@setOnClickListener
}
showLoadingDialog() showLoadingDialog()
uploadSensorData() GlobalScope.launch {
uploadSensorData()
closeLoadingDialog()
}
} }
syncVedio.setOnClickListener { syncVedio.setOnClickListener {
if (uploadingVideo.get()) {
showToast(getString(R.string.repeat_click_sync_tip))
return@setOnClickListener
}
showLoadingDialog() showLoadingDialog()
uploadVideo() GlobalScope.launch {
uploadVideo()
closeLoadingDialog()
}
} }
syncOnce.setOnClickListener { syncOnce.setOnClickListener {
if (uploadingGas.get() && uploadingVideo.get()) {
showToast(getString(R.string.repeat_click_sync_tip))
return@setOnClickListener
}
showLoadingDialog() showLoadingDialog()
uploadOnece() uploadOnece()
} }
@ -60,98 +79,92 @@ class CloudActivity : NoOptionsActivity() {
} }
private fun uploadOnece() { private fun uploadOnece() {
uploadSensorData() GlobalScope.launch {
uploadVideo() uploadSensorData()
uploadVideo()
closeLoadingDialog()
}
} }
private fun uploadVideo() { private suspend fun uploadVideo() {
// 1.拿到云端最新数据时间 if (!uploadingVideo.get()) {
devicesApi.getVideoLastTime(object : RequestResultCallBack<LastTimeResponse>() { uploadingVideo.set(true)
override fun onResult(result: LastTimeResponse) { // 1.拿到云端最新数据时间
if (result.isOk()) { val timeResponse = devicesApi.getVideoLastTime()
val cloudTime = result.data if (timeResponse.isOk()) {
// 2. 拿到待上传文件列表 上传 val cloudTime = timeResponse.data
getFileListAndUpload(cloudTime) // 2. 拿到待上传文件列表 上传
} else { getFileListAndUpload(cloudTime)
LogUtils.e("getVideoLastTime error code = ${result.code}") LogUtils.v("uploadVideo ok")
} } else {
} LogUtils.e("getVideoLastTime error code = ${timeResponse.code}")
override fun onError(error: String?) {
LogUtils.e(error)
} }
}) uploadingVideo.set(false)
}
} }
private fun uploadSensorData() { private suspend fun uploadSensorData() {
// 1.拿到云端最新数据时间 if (!uploadingGas.get()) {
devicesApi.getVideoLastTime(object : RequestResultCallBack<LastTimeResponse>() { uploadingGas.set(true)
override fun onResult(result: LastTimeResponse) { // 1.拿到云端最新数据时间
if (result.isOk()) { val lastTimeResponse = devicesApi.getDetectionLastTime()
val cloudTime = result.data if (lastTimeResponse.isOk()) {
// 2. 查询本地数据库中该时间之后的数据 val cloudTime = lastTimeResponse.data
// 3. 上传数据给服务器 // 2. 查询本地数据库中该时间之后的数据
getSensorDataUpload(cloudTime) // 3. 上传数据给服务器
} else { getSensorDataUpload(cloudTime)
LogUtils.e("getVideoLastTime error code = ${result.code}") LogUtils.v("uploadSensorData ok")
} } else {
} LogUtils.e("getVideoLastTime error code = ${lastTimeResponse.code}")
override fun onError(error: String?) {
LogUtils.e(error)
} }
}) uploadingGas.set(false)
}
} }
private fun getSensorDataUpload(cloudTime: Long) { private suspend fun getSensorDataUpload(cloudTime: Long) {
GlobalScope.launch { val gasList = DBUtils.gasDao().getAllBySyncFlagOrTime(false, cloudTime)
val gasList = DBUtils.gasDao().getAllBySyncFlagOrTime(false, cloudTime) val tempList = arrayListOf<Gas>()
val tempList = arrayListOf<Gas>() gasList.forEach {
gasList.forEach { tempList.add(it)
tempList.add(it) if (tempList.size == GAS_CLOUD_UPLOAD_SIZE_ONCE) {
if (tempList.size == GAS_CLOUD_UPLOAD_SIZE_ONCE) { val response = devicesApi.uploadGasData(tempList)
val cloneList: ArrayList<Gas> = tempList.clone() as ArrayList<Gas> if (response.isOk()) {
devicesApi.uploadGasData(cloneList, UploadGasCallback(tempList)) val gasDao = DBUtils.gasDao()
tempList.clear() tempList.forEach { gas ->
gas.syncFlag = true
gasDao.update(gas)
}
} }
} tempList.clear()
if (tempList.isNotEmpty()) {
devicesApi.uploadGasData(tempList, UploadGasCallback(tempList))
} }
} }
} if (tempList.isNotEmpty()) {
val response = devicesApi.uploadGasData(tempList)
private fun getFileListAndUpload(cloudTime: Long) { if (response.isOk()) {
GlobalScope.launch { val gasDao = DBUtils.gasDao()
val videoDao = DBUtils.videoDao() tempList.forEach {
val videoList = videoDao.getAllByTime(cloudTime, System.currentTimeMillis()) it.syncFlag = true
// 上传 gasDao.update(it)
videoList.forEach { }
uploadFile(it)
} }
} }
} }
private fun uploadFile(video: Video) { private suspend fun getFileListAndUpload(cloudTime: Long) {
TestUtils.testUploadFile(uploadApi, video, loadingDialog) val videoDao = DBUtils.videoDao()
} val videoList = videoDao.getAllByTime(cloudTime, System.currentTimeMillis())
// 上传
class UploadGasCallback(private val upLoadList: ArrayList<Gas>) : videoList.forEach {
RequestResultCallBack<BaseResponse>() { uploadFile(it)
override fun onResult(result: BaseResponse) {
GlobalScope.launch {
if (result.isOk()) {
val gasDao = DBUtils.gasDao()
upLoadList.forEach {
it.syncFlag = true
gasDao.update(it)
}
}
}
} }
}
override fun onError(error: String?) { private suspend fun uploadFile(video: Video) {
LogUtils.e("UploadGasCallback $error") val response = uploadApi.singleUpload(video.path, video.time)
if (response.isOk()) {
val videoDaoImpl = DBUtils.videoDao()
video.uploaded = true
videoDaoImpl.update(video)
} }
} }
} }

@ -57,4 +57,5 @@
<string name="export_data_tip">数据导出中</string> <string name="export_data_tip">数据导出中</string>
<string name="connecting_camera">正在连接摄像头...</string> <string name="connecting_camera">正在连接摄像头...</string>
<string name="repeat_click_sync_tip">正在同步中,请勿重复点击</string>
</resources> </resources>

@ -4,7 +4,7 @@ import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import com.common.commonlib.db.entity.Gas import androidx.room.Update
import com.common.commonlib.db.entity.Video import com.common.commonlib.db.entity.Video
@Dao @Dao
@ -23,4 +23,7 @@ interface VideoDao {
@Delete @Delete
suspend fun delete(video: Video) suspend fun delete(video: Video)
@Update
suspend fun update(video: Video)
} }
Loading…
Cancel
Save