diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
new file mode 100644
index 0000000..bf62be5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
new file mode 100644
index 0000000..bf62be5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
new file mode 100644
index 0000000..f092228
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
new file mode 100644
index 0000000..bf62be5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
new file mode 100644
index 0000000..f092228
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_gateway.xml b/app/src/main/res/layout/activity_gateway.xml
new file mode 100644
index 0000000..cc7cacc
--- /dev/null
+++ b/app/src/main/res/layout/activity_gateway.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
new file mode 100644
index 0000000..bf62be5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
new file mode 100644
index 0000000..f092228
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_gateway.xml b/app/src/main/res/layout/activity_gateway.xml
new file mode 100644
index 0000000..cc7cacc
--- /dev/null
+++ b/app/src/main/res/layout/activity_gateway.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_scan_zigbee.xml b/app/src/main/res/layout/activity_scan_zigbee.xml
new file mode 100644
index 0000000..15cdf02
--- /dev/null
+++ b/app/src/main/res/layout/activity_scan_zigbee.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1d57b75..03d3f5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,8 @@
+
+
"智能壁挂炉"
"pc" -> "Wi-Fi智能插排"
"cz" -> "Wi-Fi智能插座"
- "wg2" -> "多功能网关"
+ "wg2" -> "智能网关"
else -> "其他"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
index d1f82d6..7f4b807 100644
--- a/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
+++ b/app/src/main/java/com/casic/br/fragment/DevicePageFragment.kt
@@ -158,6 +158,7 @@
}
selectedCategory.contains("wg2") -> {
//网关
+ requireContext().navigatePageTo(deviceModel.devId)
}
}
} else {
diff --git a/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
new file mode 100644
index 0000000..f435159
--- /dev/null
+++ b/app/src/main/java/com/casic/br/utils/TuyaSubDeviceListener.kt
@@ -0,0 +1,46 @@
+package com.casic.br.utils
+
+import com.tuya.smart.sdk.api.ISubDevListener
+
+open class TuyaSubDeviceListener : ISubDevListener {
+
+ /**
+ * 当设备功能状态变更时的通知
+ *
+ * @param nodeId 子设备 nodeId,子设备 DeviceBean 中的 nodeId 字段
+ * @param dpStr 子设备变更的设备功能数据
+ */
+ override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+
+ }
+
+ /**
+ * 设备移除时的通知
+ */
+ override fun onSubDevRemoved(devId: String?) {
+
+ }
+
+ /**
+ * 新增设备时的通知
+ */
+ override fun onSubDevAdded(devId: String?) {
+
+ }
+
+ /**
+ * 子设备重命名时的通知
+ */
+ override fun onSubDevInfoUpdate(devId: String?) {
+
+ }
+
+ /**
+ * 子设备在线 or 离线状态变更通知
+ */
+ override fun onSubDevStatusChanged(
+ onlineDeviceIds: MutableList?, offlineDeviceIds: MutableList?
+ ) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
new file mode 100644
index 0000000..d3ee472
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/ScanZigbeeActivity.kt
@@ -0,0 +1,182 @@
+package com.casic.br.view
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import androidx.lifecycle.ViewModelProvider
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.utils.DeserializeModel
+import com.casic.br.utils.LoadingDialogHub
+import com.casic.br.vm.DeviceViewModel
+import com.casic.br.widgets.WaterRippleView
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.vm.LoadState
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.home.sdk.builder.TuyaGwSubDevActivatorBuilder
+import com.tuya.smart.sdk.api.ITuyaActivator
+import com.tuya.smart.sdk.api.ITuyaSmartActivatorListener
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.*
+import kotlinx.android.synthetic.main.activity_scan_zigbee.deviceLogoView
+import kotlinx.android.synthetic.main.activity_scan_zigbee.rootView
+import kotlinx.android.synthetic.main.include_base_title.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+
+class ScanZigbeeActivity : KotlinBaseActivity() {
+
+ private val kTag = "ScanZigbeeActivity"
+ private var isRunning = true
+ private lateinit var singleThreadExecutor: ExecutorService
+ private lateinit var deviceId: String
+ private lateinit var deviceViewModel: DeviceViewModel
+ private lateinit var subDevActivator: ITuyaActivator
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceBean: DeviceBean
+
+ override fun initLayoutView(): Int = R.layout.activity_scan_zigbee
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ initLayoutImmersionBar(rootView)
+ leftBackView.setOnClickListener { finish() }
+ titleView.text = String.format("搜索Zigbee设备")
+ }
+
+ override fun observeRequestState() {
+ deviceViewModel.loadState.observe(this, {
+ when (it) {
+ LoadState.Success -> {
+ LoadingDialogHub.dismiss()
+ navigatePageTo()
+ }
+ else -> {
+ "添加失败,请重新绑定".show(this)
+ LoadingDialogHub.dismiss()
+ }
+ }
+ })
+ }
+
+ override fun initData() {
+ //只有一个核心线程,当被占用时,其他的任务需要进入队列等待
+ singleThreadExecutor = Executors.newSingleThreadExecutor()
+ waterRippleView.setOnAnimationStartListener(object :
+ WaterRippleView.OnAnimationStartListener {
+ override fun onStart(view: WaterRippleView?) {
+ view?.start()
+ //开启线程搜索设备
+ Log.d(kTag, "onStart: 开始线程")
+ singleThreadExecutor.execute(searchRunnable)
+ isRunning = true
+ }
+ })
+
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java]
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val configBuilder = TuyaGwSubDevActivatorBuilder().setDevId(deviceId)
+ .setListener(object : ITuyaSmartActivatorListener {
+ override fun onError(errorCode: String?, errorMsg: String?) {
+ Log.e(kTag, "onError: $errorMsg")
+ }
+
+ override fun onActiveSuccess(devResp: DeviceBean?) {
+ if (devResp == null) {
+ Log.e(kTag, "onActiveSuccess: 无法扫描到涂鸦Zigbee模组")
+ return
+ }
+ deviceBean = devResp
+ tipsView.text = String.format("已搜索到Zigbee设备,基本信息如下")
+ logoViewLayout.visibility = View.VISIBLE
+ Glide.with(this@ScanZigbeeActivity)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+ deviceNameView.text = String.format("产品名称:${deviceBean.name}")
+
+ //将绑定的设备存入自己的数据库
+ weakReferenceHandler.sendEmptyMessage(2022101902)
+ }
+
+ override fun onStep(step: String?, data: Any?) {
+
+ }
+ })
+
+ subDevActivator = TuyaHomeSdk.getActivatorInstance().newGwSubDevActivator(configBuilder)
+ subDevActivator.start()
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101902) {
+ LoadingDialogHub.show(this, "设备绑定成功,开始同步服务器数据")
+ object : CountDownTimer(5000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ deviceViewModel.addDevice(deviceBean, DeserializeModel.getUserModel()!!)
+ }
+ }.start()
+ }
+ true
+ }
+
+ override fun initEvent() {
+
+ }
+
+ private val searchRunnable = Runnable {
+ while (true) {
+ try {
+ if (!isRunning) {
+ Log.d(kTag, "run: 设备搜索线程休眠中...")
+ Thread.sleep(Long.MAX_VALUE)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ Log.d(kTag, "run: 设备搜索线程运行中...")
+ try {
+ //搜索设备
+ Thread.sleep(1000)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ subDevActivator.stop()
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ isRunning = false
+ waterRippleView.stop()
+ subDevActivator.stop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ subDevActivator.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
index d853d48..4d22582 100644
--- a/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/CookerActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.cooker.ControlPageFragment
import com.casic.br.fragment.cooker.ServicePageFragment
import com.casic.br.fragment.cooker.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
index d0267c1..435a2fe 100644
--- a/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/FireplaceActivity.kt
@@ -10,6 +10,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.fireplace.ControlPageFragment
import com.casic.br.fragment.fireplace.ServicePageFragment
import com.casic.br.fragment.fireplace.StatusPageFragment
@@ -69,7 +70,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐壁挂炉"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
index 344ac9a..68a0785 100644
--- a/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/PowerStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -21,10 +22,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_cooker.*
import kotlinx.android.synthetic.main.activity_power_strip.*
-import kotlinx.android.synthetic.main.activity_power_strip.rootView
-import kotlinx.android.synthetic.main.fragment_device_cooker_control.*
import kotlinx.android.synthetic.main.include_device_title.*
/**
@@ -63,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
deviceBean.dpName.entries.forEach {
when (it.key) {
"1" -> firstNameView.text = it.value
diff --git a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
index 90292cc..c02c881 100644
--- a/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/RangeHoodActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.rangehood.ControlPageFragment
import com.casic.br.fragment.rangehood.ServicePageFragment
import com.casic.br.fragment.rangehood.StatusPageFragment
@@ -73,7 +74,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐油烟机"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
index 122ef71..4ea83fc 100644
--- a/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/SingleStripActivity.kt
@@ -6,6 +6,7 @@
import com.casic.br.R
import com.casic.br.extensions.createCommand
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.utils.CommandManager
import com.casic.br.utils.TuyaDeviceListener
import com.gyf.immersionbar.ImmersionBar
@@ -60,6 +61,7 @@
return
}
Log.d(kTag, deviceBean.dps.toJson())
+ titleView.text = deviceBean.toChineseTypeName()
changeViewStatus(deviceBean.dps["1"] as Boolean)
deviceInstance.registerDevListener(object : TuyaDeviceListener() {
diff --git a/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
new file mode 100644
index 0000000..5ab7f58
--- /dev/null
+++ b/app/src/main/java/com/casic/br/view/device/SmartGatewayActivity.kt
@@ -0,0 +1,285 @@
+package com.casic.br.view.device
+
+import android.graphics.Color
+import android.os.Handler
+import android.util.Log
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import com.casic.br.R
+import com.casic.br.adapter.AddedDeviceAdapter
+import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.selectCategory
+import com.casic.br.extensions.toChineseTypeName
+import com.casic.br.view.ScanZigbeeActivity
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.Constant
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.BottomActionSheet
+import com.tuya.smart.android.device.bean.UpgradeInfoBean
+import com.tuya.smart.home.sdk.TuyaHomeSdk
+import com.tuya.smart.sdk.api.*
+import com.tuya.smart.sdk.bean.DeviceBean
+import kotlinx.android.synthetic.main.activity_gateway.*
+import kotlinx.android.synthetic.main.include_device_title.*
+import java.util.*
+
+/**
+ * 智能网关
+ * TODO 数据上报暂缓
+ * */
+class SmartGatewayActivity : KotlinBaseActivity() {
+
+ private val kTag = "SmartGatewayActivity"
+ private val context = this@SmartGatewayActivity
+ private var dataBeans: MutableList = ArrayList()
+ private var isRefresh = false
+ private lateinit var deviceId: String
+ private lateinit var weakReferenceHandler: WeakReferenceHandler
+ private lateinit var deviceAdapter: AddedDeviceAdapter
+ private lateinit var tuyaOTA: ITuyaOta
+ private lateinit var deviceInstance: ITuyaDevice //网关本身
+ private lateinit var deviceSubInstance: ITuyaGateway //网关下属设备
+
+ override fun initLayoutView(): Int = R.layout.activity_gateway
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun setupTopBarLayout() {
+ initLayoutImmersionBar(rootView)
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ deviceId = intent.getStringExtra(Constant.INTENT_PARAM)!!
+ tuyaOTA = TuyaHomeSdk.newOTAInstance(deviceId)
+ //控制设备前必须初始家庭化数据,每次 App 活跃期间,初始化一次即可。
+ deviceInstance = TuyaHomeSdk.newDeviceInstance(deviceId)
+ deviceSubInstance = TuyaHomeSdk.newGatewayInstance(deviceId)
+
+ weakReferenceHandler = WeakReferenceHandler(callback)
+
+ val deviceBean = TuyaHomeSdk.getDataInstance().getDeviceBean(deviceId)
+ if (deviceBean == null) {
+ "查询设备信息失败,请检查设备是否已离线".show(this)
+ return
+ }
+ deviceStateView.text = if (deviceBean.isOnline) {
+ "设备在线"
+ } else {
+ "设备已离线"
+ }
+ titleView.text = deviceBean.toChineseTypeName()
+ Glide.with(this)
+ .load(deviceBean.iconUrl)
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(R.mipmap.load_image_error)
+ .into(deviceLogoView)
+// deviceSubInstance.registerSubDevListener(object :TuyaSubDeviceListener(){
+// override fun onSubDevDpUpdate(nodeId: String?, dps: String?) {
+// Log.d(kTag, "onDpUpdate: $dps")
+// }
+// })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ deviceSubInstance.getSubDevList(object : ITuyaDataCallback> {
+ override fun onSuccess(result: MutableList) {
+ when {
+ isRefresh -> {
+ dataBeans.clear()
+ dataBeans = result
+ isRefresh = false
+ }
+ else -> {
+ dataBeans = result
+ }
+ }
+ weakReferenceHandler.sendEmptyMessage(2022101901)
+ }
+
+ override fun onError(errorCode: String?, errorMessage: String?) {
+ Log.d(kTag, "onError: $errorMessage")
+ }
+ })
+ }
+
+ private val callback = Handler.Callback {
+ if (it.what == 2022101901) {
+ if (isRefresh) {
+ deviceAdapter.notifyDataSetChanged()
+ } else {
+ deviceAdapter = AddedDeviceAdapter(this, dataBeans)
+ deviceRecyclerView.adapter = deviceAdapter
+ deviceAdapter.setOnItemClickListener(object :
+ AddedDeviceAdapter.OnItemClickListener {
+ override fun onAddDeviceClick() {
+ navigatePageTo(deviceId)
+ }
+
+ override fun onItemClick(position: Int) {
+ // 需要根据设备类型显示不同的页面
+ val deviceModel = dataBeans[position]
+ val selectedCategory = deviceModel.selectCategory()
+ Log.d(kTag, "设备类型: $selectedCategory")
+ when {
+// selectedCategory.contains("rs") -> {
+// //热水器
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("yyj") -> {
+// //油烟机
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("bgl") -> {
+// //壁挂炉
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("rqz") -> {
+// //燃气灶
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("pc") -> {
+// //排插
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("cz") -> {
+// //插座
+// navigatePageTo(deviceModel.devId)
+// }
+// selectedCategory.contains("wg2") -> {
+// //网关
+// navigatePageTo(deviceModel.devId)
+// }
+ }
+ }
+
+ override fun onButtonClick(position: Int) {
+ moreOperate(position)
+ }
+ })
+ }
+ }
+ true
+ }
+
+ private fun moreOperate(clickPosition: Int) {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("删除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object :
+ BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> TuyaHomeSdk.newDeviceInstance(dataBeans[clickPosition].devId)
+ .removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ dataBeans.removeAt(clickPosition)
+ deviceAdapter.notifyItemRemoved(clickPosition)
+ deviceAdapter.notifyItemRangeChanged(
+ clickPosition, dataBeans.size - clickPosition
+ )
+ }
+ })
+ }
+ }
+ }).build().show()
+ }
+
+ override fun initEvent() {
+ rightOperateView.setOnClickListener {
+ BottomActionSheet.Builder()
+ .setContext(this)
+ .setActionItemTitle(arrayListOf("固件升级", "移除设备"))
+ .setItemTextColor(Color.BLUE)
+ .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener {
+ override fun onActionItemClick(position: Int) {
+ when (position) {
+ 0 -> {
+ tuyaOTA.getOtaInfo(object : IGetOtaInfoCallback {
+ override fun onSuccess(upgradeInfoBeans: MutableList?) {
+ if (upgradeInfoBeans.isNullOrEmpty()) {
+ "无新版本可用".show(context)
+ }
+ val mainModel = upgradeInfoBeans!![0]
+ when (mainModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "主联网模组无新版本可用".show(context)
+ }
+
+ val mcuModel = upgradeInfoBeans[1]
+ when (mcuModel.upgradeStatus) {
+ 1 -> updateVersion()
+ 2 -> {
+
+ }
+ else -> "MCU模块无新版本可用".show(context)
+ }
+ }
+
+ override fun onFailure(code: String?, error: String?) {
+
+ }
+ })
+ }
+ 1 -> deviceInstance.removeDevice(object : IResultCallback {
+ override fun onError(code: String?, error: String?) {
+ Log.d(kTag, "onError: $error")
+ }
+
+ override fun onSuccess() {
+ finish()
+ }
+ })
+ }
+ }
+ })
+ .build().show()
+ }
+ }
+
+ private fun updateVersion() {
+ AlertControlDialog.Builder()
+ .setContext(this)
+ .setTitle("版本升级")
+ .setMessage("有新版本可以升级,是否升级?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onCancelClick() {
+ tuyaOTA.startOta()
+ }
+
+ override fun onConfirmClick() {
+
+ }
+ })
+ .build().show()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ deviceInstance.unRegisterDevListener()
+ deviceInstance.onDestroy()
+
+ deviceSubInstance.unRegisterSubDevListener()
+ deviceSubInstance.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
index 007593e..0aa82f6 100644
--- a/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
+++ b/app/src/main/java/com/casic/br/view/device/WaterHeaterActivity.kt
@@ -11,6 +11,7 @@
import com.casic.br.R
import com.casic.br.adapter.TabPagerAdapter
import com.casic.br.extensions.initLayoutImmersionBar
+import com.casic.br.extensions.toChineseTypeName
import com.casic.br.fragment.waterheater.ControlPageFragment
import com.casic.br.fragment.waterheater.ServicePageFragment
import com.casic.br.fragment.waterheater.StatusPageFragment
@@ -30,12 +31,7 @@
import com.tuya.smart.sdk.api.IResultCallback
import com.tuya.smart.sdk.api.ITuyaDevice
import com.tuya.smart.sdk.api.ITuyaOta
-import kotlinx.android.synthetic.main.activity_range_hood.*
import kotlinx.android.synthetic.main.activity_water_heater.*
-import kotlinx.android.synthetic.main.activity_water_heater.deviceLogoView
-import kotlinx.android.synthetic.main.activity_water_heater.deviceTabLayout
-import kotlinx.android.synthetic.main.activity_water_heater.deviceViewPager
-import kotlinx.android.synthetic.main.activity_water_heater.rootView
import kotlinx.android.synthetic.main.include_device_title.*
import java.util.*
@@ -73,7 +69,7 @@
"查询设备信息失败,请检查设备是否已离线".show(this)
return
}
- titleView.text = "万家乐热水器"
+ titleView.text = deviceBean.toChineseTypeName()
Glide.with(this)
.load(deviceBean.iconUrl)
.placeholder(R.mipmap.load_image_error)
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
deleted file mode 100644
index bf62be5..0000000
--- a/app/src/main/res/drawable/bg_stroke_layout_gray_circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
new file mode 100644
index 0000000..5e05c18
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
new file mode 100644
index 0000000..bf62be5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_gray_circle_7.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
new file mode 100644
index 0000000..f092228
--- /dev/null
+++ b/app/src/main/res/drawable/bg_stroke_layout_main_circle_1.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_gateway.xml b/app/src/main/res/layout/activity_gateway.xml
new file mode 100644
index 0000000..cc7cacc
--- /dev/null
+++ b/app/src/main/res/layout/activity_gateway.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_scan_zigbee.xml b/app/src/main/res/layout/activity_scan_zigbee.xml
new file mode 100644
index 0000000..15cdf02
--- /dev/null
+++ b/app/src/main/res/layout/activity_scan_zigbee.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_single_strip.xml b/app/src/main/res/layout/activity_single_strip.xml
index 8790073..8fc949d 100644
--- a/app/src/main/res/layout/activity_single_strip.xml
+++ b/app/src/main/res/layout/activity_single_strip.xml
@@ -17,7 +17,7 @@