1+ package com.tencent.iot.explorer.link.kitlink.activity
2+
3+ import android.os.Handler
4+ import android.os.Message
5+ import android.text.TextUtils
6+ import android.view.View
7+ import com.alibaba.fastjson.JSONObject
8+ import com.tencent.iot.explorer.link.R
9+ import com.tencent.iot.explorer.link.core.auth.IoTAuth
10+ import com.tencent.iot.explorer.link.core.auth.callback.MyCallback
11+ import com.tencent.iot.explorer.link.core.auth.entity.DeviceEntity
12+ import com.tencent.iot.explorer.link.core.auth.response.BaseResponse
13+ import com.tencent.iot.explorer.link.core.link.entity.*
14+ import com.tencent.iot.explorer.link.core.link.exception.TCLinkException
15+ import com.tencent.iot.explorer.link.core.link.listener.BleDeviceConnectionListener
16+ import com.tencent.iot.explorer.link.core.link.service.BleConfigService
17+ import com.tencent.iot.explorer.link.core.log.L
18+ import com.tencent.iot.explorer.link.mvp.IPresenter
19+ import com.tencent.iot.explorer.link.retrofit.DownloadRequest
20+ import com.tencent.iot.explorer.link.retrofit.DownloadRequest.OnDownloadListener
21+ import kotlinx.android.synthetic.main.activity_ble_otadownload.*
22+ import kotlinx.android.synthetic.main.menu_back_layout.*
23+ import kotlinx.coroutines.*
24+ import java.io.*
25+
26+
27+ class BleOTADownloadActivity : PActivity (), CoroutineScope by MainScope() {
28+ val MSG_DOWNLOAD_REFRESH = 0
29+ val MSG_DOWNLOAD_SUCCESS = 1
30+ val MSG_DOWNLOAD_FAILED = 2
31+ val MSG_UPLOAD_REFRESH = 3
32+ val MSG_UPLOAD_SUCCESS = 4
33+ val MSG_UPLOAD_FAILED = 5
34+
35+ private var TAG = BleOTADownloadActivity ::class .java.simpleName
36+ private var deviceEntity: DeviceEntity ? = null
37+ private var connectBleJob: Job ? = null
38+
39+ private var targetVersion: String? = null // 要升级到的ota版本
40+ @Volatile
41+ private var downloadprogress: Int = 0 // 下载进度值
42+ private var otaFilePath: String? = null // 下载固件时本地的存储路径
43+
44+ private var mtusize = 0
45+ @Volatile
46+ private var uploadprogress: Int = 0 // 写入进度值
47+
48+ override fun getPresenter (): IPresenter ? {
49+ return null
50+ }
51+
52+ override fun onResume () {
53+ super .onResume()
54+ BleConfigService .get().connetionListener = bleDeviceConnectionListener
55+ }
56+
57+ override fun getContentView (): Int {
58+ return R .layout.activity_ble_otadownload
59+ }
60+
61+ override fun initView () {
62+ tv_title.text = getString(R .string.firmware_update)
63+ stopScanBleDev(true )
64+ deviceEntity = get(" device" )
65+ mtusize = get(" mtusize" ) ? : 0
66+ downloadDeviceOTAInfo()
67+ }
68+
69+ override fun setListener () {
70+ iv_back.setOnClickListener { finish() }
71+ tv_finish.setOnClickListener { finish() }
72+ }
73+
74+
75+ private fun startScanBleDev () {
76+ ble_connect_layout.visibility = View .VISIBLE
77+ BleConfigService .get().startScanBluetoothDevices()
78+ search_ble_dev_layout.visibility = View .VISIBLE
79+ search_reault_layout.visibility = View .GONE
80+ }
81+
82+ private fun stopScanBleDev (connected : Boolean ) {
83+ launch(Dispatchers .Main ) {
84+ ble_connect_layout.visibility = View .VISIBLE
85+ BleConfigService .get().stopScanBluetoothDevices()
86+ search_ble_dev_layout.visibility = View .GONE
87+ search_reault_layout.visibility = View .VISIBLE
88+ if (connected) {
89+ search_reault_layout.setBackgroundResource(R .color.blue_006EFF)
90+ retry_connect.setTextColor(this @BleOTADownloadActivity.resources.getColor(R .color.white))
91+ retry_connect.setText(R .string.break_ble_connect)
92+ retry_connect.setOnClickListener {
93+ BleConfigService .get().bluetoothGatt?.let {
94+ it?.close()
95+ stopScanBleDev(false )
96+ }
97+ }
98+ } else {
99+ search_reault_layout.setBackgroundResource(R .color.red_E65A59)
100+ retry_connect.setTextColor(this @BleOTADownloadActivity.resources.getColor(R .color.white))
101+ retry_connect.setText(R .string.scanning_retry)
102+ retry_connect.setOnClickListener { startScanBleDev() }
103+ }
104+ }
105+ }
106+
107+ private var bleDeviceConnectionListener = object : BleDeviceConnectionListener {
108+ override fun onBleDeviceFounded (bleDevice : BleDevice ) {
109+ if (bleDevice.productId == deviceEntity?.ProductId && ! TextUtils .isEmpty(bleDevice.productId)) {
110+ // && bleDevice.devName == deviceEntity?.DeviceName) {
111+ BleConfigService .get().bluetoothGatt = BleConfigService .get().connectBleDeviceAndGetLocalPsk(bleDevice, deviceEntity?.ProductId , deviceEntity?.DeviceName )
112+ } else if (! TextUtils .isEmpty(bleDevice.bindTag)) {
113+ deviceEntity?.let {
114+ if (bleDevice.bindTag == BleConfigService .bytesToHex(BleConfigService .getBindTag(it.ProductId , it.DeviceName ))) {
115+ BleConfigService .get().bluetoothGatt = BleConfigService .get().connectBleDeviceAndGetLocalPsk(bleDevice, deviceEntity?.ProductId , deviceEntity?.DeviceName )
116+ }
117+ }
118+ }
119+ }
120+
121+ override fun onBleDeviceConnected () {
122+ launch {
123+ BleConfigService .get().bluetoothGatt?.let {
124+ delay(3000 )
125+ // if (BleConfigService.get().setMtuSize(it, 512)) return@launch
126+ launch (Dispatchers .Main ) {
127+ delay(1000 )
128+ BleConfigService .get().bluetoothGatt?.let {
129+ BleConfigService .get().stopScanBluetoothDevices()
130+ if (! BleConfigService .get().connectSubDevice(it)) {
131+ stopScanBleDev(false )
132+ return @launch
133+ } else {
134+
135+ }
136+ }
137+ }
138+ }
139+ }
140+ }
141+ override fun onBleDeviceDisconnected (exception : TCLinkException ) {
142+ stopScanBleDev(false )
143+ launch (Dispatchers .Main ) {
144+ startScanBleDev()
145+ }
146+ }
147+ override fun onBleDeviceInfo (bleDeviceInfo : BleDeviceInfo ) {}
148+ override fun onBleSetWifiModeResult (success : Boolean ) {}
149+ override fun onBleSendWifiInfoResult (success : Boolean ) {}
150+ override fun onBleWifiConnectedInfo (wifiConnectInfo : BleWifiConnectInfo ) {}
151+ override fun onBlePushTokenResult (success : Boolean ) {}
152+ override fun onMtuChanged (mtu : Int , status : Int ) {
153+ L .d(TAG , " onMtuChanged mtu $mtu status $status " )
154+ }
155+ override fun onBleBindSignInfo (bleDevBindCondition : BleDevBindCondition ) {}
156+ override fun onBleSendSignInfo (bleDevSignResult : BleDevSignResult ) {
157+ stopScanBleDev(true )
158+ connectBleJob?.cancel()
159+ }
160+ override fun onBleUnbindSignInfo (signInfo : String ) {}
161+ override fun onBlePropertyValue (bleDeviceProperty : BleDeviceProperty ) {}
162+ override fun onBleControlPropertyResult (result : Int ) {}
163+ override fun onBleRequestCurrentProperty () {}
164+ override fun onBleNeedPushProperty (eventId : Int , bleDeviceProperty : BleDeviceProperty ) {}
165+ override fun onBleReportActionResult (reason : Int , actionId : Int , bleDeviceProperty : BleDeviceProperty ) {}
166+ override fun onBleDeviceFirmwareVersion (firmwareVersion : BleDeviceFirmwareVersion ) {
167+ if (firmwareVersion.mtuFlag == 1 ) { // 是否设置 mtu 当 mtu flag为 1 时,进行 MTU 设置;当 mtu flag 为 0 时,不设置 MTU
168+ BleConfigService .get().setMtuSize(BleConfigService .get().bluetoothGatt, firmwareVersion.mtuSize)
169+ }
170+ if (targetVersion.equals(firmwareVersion.version)) { // ble设备重启后,firmware版本和目标版本一致,判定ota升级成功
171+ launch(Dispatchers .Main ) {
172+ L .d(TAG , " ota升级成功~" )
173+ rl_ota_progress.visibility = View .GONE
174+ rl_ota_success.visibility = View .VISIBLE
175+ tv_finish.visibility = View .VISIBLE
176+ tv_upgrade_success_version.text = getString(R .string.firmware_update_success_version, targetVersion)
177+ }
178+ }
179+ }
180+
181+ override fun onBleDevOtaUpdateResponse (otaUpdateResponse : BleDevOtaUpdateResponse ) {
182+ L .d(TAG , " onBleDevOtaUpdateResponse" )
183+ if (otaUpdateResponse.allowUpdate) {
184+ otaFilePath?.let {
185+ BleConfigService .get().sendOtaFirmwareData(BleConfigService .get().bluetoothGatt,
186+ it, otaUpdateResponse)
187+ }
188+ }
189+ }
190+
191+ override fun onBleDevOtaUpdateResult (success : Boolean , errorCode : Int ) {
192+ if (success) {
193+ handler.sendEmptyMessage(MSG_UPLOAD_SUCCESS )
194+ } else {
195+ handler.sendEmptyMessage(MSG_UPLOAD_FAILED )
196+ }
197+ }
198+
199+ override fun onBleDevOtaReceivedProgressResponse (progress : Int ) {
200+ L .d(TAG ," progress:${progress} " )
201+ uploadprogress = progress
202+ refreshProgress(false )
203+ reportProgress2Cloud(progress, " updating" )
204+ }
205+
206+ override fun onBleDeviceMtuSize (size : Int ) {}
207+ override fun onBleDeviceTimeOut (timeLong : Int ) {}
208+ }
209+
210+ // 上报设备OTA状态进度 (下载、更新升级、烧录) State: downloading updating burning
211+ private fun reportProgress2Cloud (progress : Int , state : String ) {
212+ targetVersion?.let {
213+ IoTAuth .deviceImpl.reportOTAStatus(" ${deviceEntity?.ProductId } /${deviceEntity?.DeviceName } " , state,
214+ it, progress, object : MyCallback {
215+ override fun fail (msg : String? , reqCode : Int ) {}
216+
217+ override fun success (response : BaseResponse , reqCode : Int ) {}
218+ })
219+ }
220+ }
221+
222+ private fun downloadDeviceOTAInfo () {
223+ IoTAuth .deviceImpl.getDeviceOTAInfo(" ${deviceEntity?.ProductId } /${deviceEntity?.DeviceName } " , object : MyCallback {
224+ override fun fail (msg : String? , reqCode : Int ) {
225+
226+ }
227+
228+ override fun success (response : BaseResponse , reqCode : Int ) {
229+ val json = response.data as JSONObject
230+ val firmwareURL = json.getString(" FirmwareURL" )
231+ if (firmwareURL != null ) {
232+ targetVersion = json.getString(" TargetVersion" )
233+ // val uploadVersion = json.getString("UploadVersion")
234+ if (TextUtils .isEmpty(otaFilePath)) {
235+ otaFilePath = cacheDir.absolutePath + " /${deviceEntity?.ProductId } _${deviceEntity?.DeviceName } _${targetVersion} "
236+ }
237+ downloadOtaFirmware(firmwareURL)
238+ }
239+ }
240+ })
241+ }
242+
243+ private fun downloadOtaFirmware (url : String ) {
244+ DownloadRequest .get().download(url, otaFilePath, downloadlistener)
245+ }
246+
247+
248+ var downloadlistener: OnDownloadListener = object : OnDownloadListener {
249+ override fun onDownloadSuccess (requestId : String ) {
250+ handler.sendEmptyMessage(MSG_DOWNLOAD_SUCCESS )
251+ }
252+
253+ override fun onDownloading (requestId : String , progress : Int ) {
254+ downloadprogress = progress
255+ refreshProgress(true )
256+ reportProgress2Cloud(progress, " downloading" )
257+ }
258+
259+ override fun onDownloadFailed (requestId : String ) {
260+ handler.sendEmptyMessage(MSG_DOWNLOAD_FAILED )
261+ }
262+ }
263+
264+
265+ var handler: Handler = object : Handler () {
266+ override fun handleMessage (msg : Message ) {
267+ super .handleMessage(msg)
268+ when (msg.what) {
269+ MSG_DOWNLOAD_REFRESH -> {
270+ if (progress_download != null ) {
271+ progress_download.progress = downloadprogress.toFloat()
272+ tv_upgradeing.text = getString(R .string.firmware_upgrading_tip, downloadprogress) + " %"
273+ }
274+ if (downloadprogress < 100 ) {
275+ L .d(TAG , " downloadprogress:${downloadprogress} , progressBar.max:${progress_download?.max} " )
276+ // onDismisListener.onDownloadProgress(count, progressBar.max as Int)
277+ }
278+ }
279+ MSG_DOWNLOAD_SUCCESS -> {
280+ progress_download?.progress = 100f
281+ L .d(TAG , " onDownloadSuccess:${otaFilePath} " )
282+ reportProgress2Cloud(100 , " downloading" )
283+ otaFilePath?.let {
284+ targetVersion?.let { it1 ->
285+ BleConfigService .get().requestOTAInfo(BleConfigService .get().bluetoothGatt,
286+ it, it1
287+ )
288+ }
289+ }
290+ }
291+ MSG_DOWNLOAD_FAILED -> {
292+ L .d(TAG , " onDownloadFailed:${otaFilePath} " )
293+ }
294+ MSG_UPLOAD_REFRESH -> {
295+ if (progress_download != null ) {
296+ progress_download.progress = uploadprogress.toFloat()
297+ tv_upgradeing.text = getString(R .string.firmware_writing, uploadprogress) + " %"
298+ }
299+ if (downloadprogress < 100 ) {
300+ L .d(TAG , " uploadprogress:${uploadprogress} , progressBar.max:${progress_download?.max} " )
301+ }
302+ }
303+ MSG_UPLOAD_SUCCESS -> {
304+ progress_download?.progress = 100f
305+ L .d(TAG , " onUploadSuccess:${otaFilePath} " )
306+ reportProgress2Cloud(100 , " updating" )
307+ }
308+ MSG_UPLOAD_FAILED -> {
309+ L .d(TAG , " onUpFailed:${otaFilePath} " )
310+ }
311+ }
312+ }
313+ }
314+
315+ private fun refreshProgress (download : Boolean ) { // 通过url下载固件文件,还是写入固件给ble设备
316+ // 进度在 100 以内允许刷新
317+ if (downloadprogress <= 100 ) {
318+ if (download) {
319+ handler.sendEmptyMessage(MSG_DOWNLOAD_REFRESH )
320+ } else {
321+ handler.sendEmptyMessage(MSG_UPLOAD_REFRESH )
322+ }
323+ }
324+ }
325+
326+ }
0 commit comments