485除湿机
This commit is contained in:
+2
-2
@@ -10,8 +10,8 @@ android {
|
|||||||
applicationId "com.example.iot_controlhost"
|
applicationId "com.example.iot_controlhost"
|
||||||
minSdkVersion 25
|
minSdkVersion 25
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 157
|
versionCode 158
|
||||||
versionName "3.5.0.157"
|
versionName "3.5.0.158"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
ndk {
|
ndk {
|
||||||
moduleName "mcu"
|
moduleName "mcu"
|
||||||
|
|||||||
@@ -247,6 +247,38 @@ public class SerialPortUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送无需设备返回的串口指令。
|
||||||
|
* 例如部分广播控制命令只写入总线,不会回传响应帧。
|
||||||
|
*/
|
||||||
|
public boolean sendSerialDataNoResponse(Device device, String data) {
|
||||||
|
boolean isSensor = device instanceof Sensor;
|
||||||
|
if (!isStart || outputStream == null) {
|
||||||
|
MyLog.appError("串口未打开但尝试发送数据");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] sendData = DataUtils.HexToByteArr(data);
|
||||||
|
outputStream.write(sendData);
|
||||||
|
outputStream.flush();
|
||||||
|
T = "T:" + data;
|
||||||
|
R = "R:无返回";
|
||||||
|
if (isSensor) {
|
||||||
|
MyLog.sensor(T);
|
||||||
|
MyLog.sensor(R);
|
||||||
|
} else {
|
||||||
|
MyLog.controller(T);
|
||||||
|
MyLog.controller(R);
|
||||||
|
}
|
||||||
|
device.setFailTimes(0);
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
device.addFailTimes();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isStart() {
|
public boolean isStart() {
|
||||||
return isStart;
|
return isStart;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,12 @@ import com.example.iot_controlhost.R;
|
|||||||
import com.example.iot_controlhost.base.BaseRecyclerAdapter;
|
import com.example.iot_controlhost.base.BaseRecyclerAdapter;
|
||||||
import com.example.iot_controlhost.databinding.ItemControllerAutoBinding;
|
import com.example.iot_controlhost.databinding.ItemControllerAutoBinding;
|
||||||
import com.example.iot_controlhost.model.Result;
|
import com.example.iot_controlhost.model.Result;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.model.controller.relay.Relay;
|
import com.example.iot_controlhost.model.controller.relay.Relay;
|
||||||
import com.example.iot_controlhost.model.sensor.GasSensor;
|
import com.example.iot_controlhost.model.sensor.GasSensor;
|
||||||
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
||||||
|
import com.example.iot_controlhost.ui.dialog.Dehumidifier485Dialog;
|
||||||
import com.example.iot_controlhost.utils.DialogUtil;
|
import com.example.iot_controlhost.utils.DialogUtil;
|
||||||
import com.example.iot_controlhost.utils.MyQueue;
|
import com.example.iot_controlhost.utils.MyQueue;
|
||||||
import com.example.iot_controlhost.utils.global.AutoModelSet;
|
import com.example.iot_controlhost.utils.global.AutoModelSet;
|
||||||
@@ -27,22 +30,18 @@ import java.util.List;
|
|||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手动控制继电器下的设备
|
* 自动页面控制设备列表。
|
||||||
* 用于主界面显示
|
|
||||||
*
|
|
||||||
* @Author:DuanKaiji
|
|
||||||
*/
|
*/
|
||||||
public class AutoControllerAdapter extends BaseRecyclerAdapter<Relay, ItemControllerAutoBinding> {
|
public class AutoControllerAdapter extends BaseRecyclerAdapter<Controller, ItemControllerAutoBinding> {
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
public AutoControllerAdapter(Context context, List<Relay> dataList, Class<ItemControllerAutoBinding> bindingClass) {
|
public AutoControllerAdapter(Context context, List<Controller> dataList, Class<ItemControllerAutoBinding> bindingClass) {
|
||||||
super(dataList, bindingClass);
|
super(dataList, bindingClass);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void bindData(ItemControllerAutoBinding binding, Relay device) {
|
protected void bindData(ItemControllerAutoBinding binding, Controller device) {
|
||||||
TransitionManager.beginDelayedTransition(binding.layoutRoot, new Fade());
|
TransitionManager.beginDelayedTransition(binding.layoutRoot, new Fade());
|
||||||
if ("未配置".equals(device.getName())) {
|
if ("未配置".equals(device.getName())) {
|
||||||
binding.cardNo.setVisibility(View.VISIBLE);
|
binding.cardNo.setVisibility(View.VISIBLE);
|
||||||
@@ -59,17 +58,15 @@ public class AutoControllerAdapter extends BaseRecyclerAdapter<Relay, ItemContro
|
|||||||
binding.tvInfo.setText(null);
|
binding.tvInfo.setText(null);
|
||||||
}
|
}
|
||||||
changeState(binding, device);
|
changeState(binding, device);
|
||||||
binding.tvController.setText(device.getName());
|
binding.tvController.setText(getDisplayName(device));
|
||||||
if (AutoModelSet.isAutoHumidity() && RoomController.DEVICE_NAME[2].equals(device.getName())//加湿器
|
if (isAutoControlled(device)) {
|
||||||
|| AutoModelSet.isAutoHumidity() && RoomController.DEVICE_NAME[16].equals(device.getName()) //除湿器
|
|
||||||
|| AutoModelSet.isAutoVentilator() && RoomController.DEVICE_NAME[12].equals(device.getName()) //换气扇
|
|
||||||
|| AutoModelSet.isAutoEven() && RoomController.DEVICE_NAME[7].equals(device.getName()) //匀风扇
|
|
||||||
|| AutoModelSet.isAutoDisinfect() && RoomController.DEVICE_NAME[8].equals(device.getName()) //消毒灯
|
|
||||||
|| !AutoModelSet.getAirExchangeMode().equals(SpinnerList.AIR_EXCHANGE_MODES[0]) && RoomController.DEVICE_NAME[13].equals(device.getName()) //新风
|
|
||||||
) {
|
|
||||||
binding.cardController.setOnClickListener(v -> Toasty.info(mContext, "该设备由自动控制系统接管中").show());
|
binding.cardController.setOnClickListener(v -> Toasty.info(mContext, "该设备由自动控制系统接管中").show());
|
||||||
} else {
|
} else {
|
||||||
binding.cardController.setOnClickListener(view -> {
|
binding.cardController.setOnClickListener(view -> {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
new Dehumidifier485Dialog(mContext, (Dehumidifier485) device).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
DialogUtil.showLoadingDialog(mContext, mContext.getString(R.string.in_operate));
|
DialogUtil.showLoadingDialog(mContext, mContext.getString(R.string.in_operate));
|
||||||
MyQueue.start(MyQueue.TYPE_CONTROLLER, new QueueIOUITask<Result>() {
|
MyQueue.start(MyQueue.TYPE_CONTROLLER, new QueueIOUITask<Result>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -97,34 +94,85 @@ public class AutoControllerAdapter extends BaseRecyclerAdapter<Relay, ItemContro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeState(ItemControllerAutoBinding binding, Relay device) {
|
private boolean isAutoControlled(Controller device) {
|
||||||
|
return AutoModelSet.isAutoHumidity() && RoomController.DEVICE_NAME[2].equals(device.getName())
|
||||||
|
|| AutoModelSet.isAutoHumidity() && RoomController.DEVICE_NAME[16].equals(device.getName())
|
||||||
|
|| AutoModelSet.isAutoHumidity() && device instanceof Dehumidifier485
|
||||||
|
|| AutoModelSet.isAutoVentilator() && RoomController.DEVICE_NAME[12].equals(device.getName())
|
||||||
|
|| AutoModelSet.isAutoEven() && RoomController.DEVICE_NAME[7].equals(device.getName())
|
||||||
|
|| AutoModelSet.isAutoDisinfect() && RoomController.DEVICE_NAME[8].equals(device.getName())
|
||||||
|
|| !AutoModelSet.getAirExchangeMode().equals(SpinnerList.AIR_EXCHANGE_MODES[0]) && RoomController.DEVICE_NAME[13].equals(device.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeState(ItemControllerAutoBinding binding, Controller device) {
|
||||||
if (device.isPowerSupply()) {
|
if (device.isPowerSupply()) {
|
||||||
binding.tvState.setText("运行中");
|
binding.tvState.setText("运行中");
|
||||||
binding.ivController.setImageResource(device.getIconOpen());
|
binding.ivController.setImageResource(getIconOpen(device));
|
||||||
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_open));
|
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_open));
|
||||||
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_on));
|
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_on));
|
||||||
binding.cardController.setBackgroundColor(Color.parseColor("#00BDF4"));
|
binding.cardController.setBackgroundColor(getOpenColor(device));
|
||||||
binding.ivController.setImageDrawable(mContext.getDrawable(device.getIconOpen()));
|
binding.ivController.setImageDrawable(mContext.getDrawable(getIconOpen(device)));
|
||||||
binding.tvState.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvState.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
binding.tvController.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvController.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
binding.tvPower.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvPower.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
} else {
|
} else {
|
||||||
// 地暖在超过最大温度限制后会自动断电,此时状态显示为“高温保护”而非“未启动”
|
if (device.getName().equals(RoomSetting.getFloorName()) && RoomSensor.getFloorTemperature() > AutoModelSet.getAutoFlorMaxTemp()) {
|
||||||
if(device.getName().equals(RoomSetting.getFloorName()) && RoomSensor.getFloorTemperature() > AutoModelSet.getAutoFlorMaxTemp()) {
|
|
||||||
binding.tvState.setText("高温保护中");
|
binding.tvState.setText("高温保护中");
|
||||||
} else {
|
} else {
|
||||||
binding.tvState.setText("未启动");
|
binding.tvState.setText("未启动");
|
||||||
}
|
}
|
||||||
binding.ivController.setImageResource(device.getIconClose());
|
binding.ivController.setImageResource(getIconClose(device));
|
||||||
binding.cardController.setBackgroundColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#33DCE3E3" : "#F2F0F1"));
|
binding.cardController.setBackgroundColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#33DCE3E3" : "#F2F0F1"));
|
||||||
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_close));
|
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_close));
|
||||||
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_off));
|
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_off));
|
||||||
binding.ivController.setImageDrawable(mContext.getDrawable(device.getIconClose()));
|
binding.ivController.setImageDrawable(mContext.getDrawable(getIconClose(device)));
|
||||||
binding.tvState.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvState.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
binding.tvController.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvController.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
binding.tvPower.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvPower.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
}
|
}
|
||||||
binding.tvPower.setVisibility(RoomController.relay.getModel().equals(RoomController.relay.getModels()[2]) ? View.VISIBLE : View.GONE);
|
if (device instanceof Dehumidifier485) {
|
||||||
binding.tvPower.setText("实时功率:" + device.getPower() + "w");
|
Dehumidifier485 dehumidifier = (Dehumidifier485) device;
|
||||||
|
binding.tvPower.setVisibility(View.VISIBLE);
|
||||||
|
binding.tvPower.setText("环境湿度:" + dehumidifier.getEnvironmentHumidityText());
|
||||||
|
} else if (device instanceof Relay && RoomController.relay.getModel().equals(RoomController.relay.getModels()[2])) {
|
||||||
|
binding.tvPower.setVisibility(View.VISIBLE);
|
||||||
|
binding.tvPower.setText("实时功率:" + ((Relay) device).getPower() + "w");
|
||||||
|
} else {
|
||||||
|
binding.tvPower.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconOpen(Controller device) {
|
||||||
|
if (device instanceof Relay) {
|
||||||
|
return ((Relay) device).getIconOpen();
|
||||||
|
}
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return R.mipmap.ven_open;
|
||||||
|
}
|
||||||
|
return R.mipmap.open;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconClose(Controller device) {
|
||||||
|
if (device instanceof Relay) {
|
||||||
|
return ((Relay) device).getIconClose();
|
||||||
|
}
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return R.mipmap.ven_close;
|
||||||
|
}
|
||||||
|
return R.mipmap.close;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getOpenColor(Controller device) {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return Color.parseColor("#00A1FF");
|
||||||
|
}
|
||||||
|
return Color.parseColor("#00BDF4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDisplayName(Controller device) {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return ((Dehumidifier485) device).getDisplayName();
|
||||||
|
}
|
||||||
|
return device.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+61
-17
@@ -8,13 +8,15 @@ import com.example.iot_controlhost.R;
|
|||||||
import com.example.iot_controlhost.base.BaseRecyclerAdapter;
|
import com.example.iot_controlhost.base.BaseRecyclerAdapter;
|
||||||
import com.example.iot_controlhost.databinding.ItemControllerBinding;
|
import com.example.iot_controlhost.databinding.ItemControllerBinding;
|
||||||
import com.example.iot_controlhost.model.Result;
|
import com.example.iot_controlhost.model.Result;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.model.controller.relay.Relay;
|
import com.example.iot_controlhost.model.controller.relay.Relay;
|
||||||
import com.example.iot_controlhost.model.sensor.GasSensor;
|
import com.example.iot_controlhost.model.sensor.GasSensor;
|
||||||
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
||||||
|
import com.example.iot_controlhost.ui.dialog.Dehumidifier485Dialog;
|
||||||
import com.example.iot_controlhost.utils.DialogUtil;
|
import com.example.iot_controlhost.utils.DialogUtil;
|
||||||
import com.example.iot_controlhost.utils.MyQueue;
|
import com.example.iot_controlhost.utils.MyQueue;
|
||||||
import com.example.iot_controlhost.utils.global.RoomController;
|
import com.example.iot_controlhost.utils.global.RoomController;
|
||||||
import com.example.iot_controlhost.utils.global.RoomSensor;
|
|
||||||
import com.example.iot_controlhost.utils.global.RoomSetting;
|
import com.example.iot_controlhost.utils.global.RoomSetting;
|
||||||
import com.example.iot_controlhost.utils.log.UserLog;
|
import com.example.iot_controlhost.utils.log.UserLog;
|
||||||
|
|
||||||
@@ -23,21 +25,18 @@ import java.util.List;
|
|||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手动控制继电器下的设备
|
* 手动控制设备列表。
|
||||||
* 用于主界面显示
|
|
||||||
*
|
|
||||||
* @Author:DuanKaiji
|
|
||||||
*/
|
*/
|
||||||
public class ManualControllerAdapter extends BaseRecyclerAdapter<Relay, ItemControllerBinding> {
|
public class ManualControllerAdapter extends BaseRecyclerAdapter<Controller, ItemControllerBinding> {
|
||||||
Context mContext;
|
Context mContext;
|
||||||
|
|
||||||
public ManualControllerAdapter(Context context, List<Relay> dataList, Class<ItemControllerBinding> bindingClass) {
|
public ManualControllerAdapter(Context context, List<Controller> dataList, Class<ItemControllerBinding> bindingClass) {
|
||||||
super(dataList, bindingClass);
|
super(dataList, bindingClass);
|
||||||
this.mContext = context;
|
this.mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void bindData(ItemControllerBinding binding, Relay device) {
|
protected void bindData(ItemControllerBinding binding, Controller device) {
|
||||||
if (device.getName().equals(RoomController.fan.getName())) {
|
if (device.getName().equals(RoomController.fan.getName())) {
|
||||||
binding.tvInfo.setText(GasSensor.getQualityAir());
|
binding.tvInfo.setText(GasSensor.getQualityAir());
|
||||||
binding.tvInfo.setTextColor(GasSensor.getQualityAirColor());
|
binding.tvInfo.setTextColor(GasSensor.getQualityAirColor());
|
||||||
@@ -45,8 +44,12 @@ public class ManualControllerAdapter extends BaseRecyclerAdapter<Relay, ItemCont
|
|||||||
binding.tvInfo.setText(null);
|
binding.tvInfo.setText(null);
|
||||||
}
|
}
|
||||||
changeState(binding, device);
|
changeState(binding, device);
|
||||||
binding.tvController.setText(device.getName());
|
binding.tvController.setText(getDisplayName(device));
|
||||||
binding.cardController.setOnClickListener(view -> {
|
binding.cardController.setOnClickListener(view -> {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
new Dehumidifier485Dialog(mContext, (Dehumidifier485) device).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
DialogUtil.showLoadingDialog(mContext, mContext.getString(R.string.in_operate));
|
DialogUtil.showLoadingDialog(mContext, mContext.getString(R.string.in_operate));
|
||||||
MyQueue.start(MyQueue.TYPE_CONTROLLER, new QueueIOUITask<Result>() {
|
MyQueue.start(MyQueue.TYPE_CONTROLLER, new QueueIOUITask<Result>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -73,7 +76,7 @@ public class ManualControllerAdapter extends BaseRecyclerAdapter<Relay, ItemCont
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeState(ItemControllerBinding binding, Relay device) {
|
private void changeState(ItemControllerBinding binding, Controller device) {
|
||||||
if ("未配置".equals(device.getName())) {
|
if ("未配置".equals(device.getName())) {
|
||||||
binding.cardNo.setVisibility(View.VISIBLE);
|
binding.cardNo.setVisibility(View.VISIBLE);
|
||||||
binding.cardYes.setVisibility(View.GONE);
|
binding.cardYes.setVisibility(View.GONE);
|
||||||
@@ -84,27 +87,68 @@ public class ManualControllerAdapter extends BaseRecyclerAdapter<Relay, ItemCont
|
|||||||
}
|
}
|
||||||
if (device.isPowerSupply()) {
|
if (device.isPowerSupply()) {
|
||||||
binding.tvState.setText("运行中");
|
binding.tvState.setText("运行中");
|
||||||
binding.ivController.setImageResource(device.getIconOpen());
|
binding.ivController.setImageResource(getIconOpen(device));
|
||||||
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_open));
|
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_open));
|
||||||
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_on));
|
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_on));
|
||||||
binding.cardController.setBackgroundColor(Color.parseColor("#00BDF4"));
|
binding.cardController.setBackgroundColor(getOpenColor(device));
|
||||||
binding.ivController.setImageDrawable(mContext.getDrawable(device.getIconOpen()));
|
binding.ivController.setImageDrawable(mContext.getDrawable(getIconOpen(device)));
|
||||||
binding.tvState.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvState.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
binding.tvController.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvController.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
binding.tvPower.setTextColor(Color.parseColor("#FFFFFF"));
|
binding.tvPower.setTextColor(Color.parseColor("#FFFFFF"));
|
||||||
} else {
|
} else {
|
||||||
binding.tvState.setText("未启动");
|
binding.tvState.setText("未启动");
|
||||||
binding.ivController.setImageResource(device.getIconClose());
|
binding.ivController.setImageResource(getIconClose(device));
|
||||||
binding.cardController.setBackgroundColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#33DCE3E3" : "#F2F0F1"));
|
binding.cardController.setBackgroundColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#33DCE3E3" : "#F2F0F1"));
|
||||||
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_close));
|
binding.ivPower.setBackground(mContext.getDrawable(R.drawable.bg_controller_close));
|
||||||
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_off));
|
binding.ivPower.setImageDrawable(mContext.getDrawable(R.mipmap.switch_off));
|
||||||
binding.ivController.setImageDrawable(mContext.getDrawable(device.getIconClose()));
|
binding.ivController.setImageDrawable(mContext.getDrawable(getIconClose(device)));
|
||||||
binding.tvState.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvState.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
binding.tvController.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvController.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
binding.tvPower.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
binding.tvPower.setTextColor(Color.parseColor(RoomSetting.isDarkTheme() ? "#FFFFFF" : "#3A3A3A"));
|
||||||
}
|
}
|
||||||
binding.tvPower.setVisibility(RoomController.relay.getModel().equals(RoomController.relay.getModels()[2]) ? View.VISIBLE : View.GONE);
|
if (device instanceof Dehumidifier485) {
|
||||||
binding.tvPower.setText("实时功率:" + device.getPower() + "w");
|
Dehumidifier485 dehumidifier = (Dehumidifier485) device;
|
||||||
|
binding.tvPower.setVisibility(View.VISIBLE);
|
||||||
|
binding.tvPower.setText("环境湿度:" + dehumidifier.getEnvironmentHumidityText());
|
||||||
|
} else if (device instanceof Relay && RoomController.relay.getModel().equals(RoomController.relay.getModels()[2])) {
|
||||||
|
binding.tvPower.setVisibility(View.VISIBLE);
|
||||||
|
binding.tvPower.setText("实时功率:" + ((Relay) device).getPower() + "w");
|
||||||
|
} else {
|
||||||
|
binding.tvPower.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getIconOpen(Controller device) {
|
||||||
|
if (device instanceof Relay) {
|
||||||
|
return ((Relay) device).getIconOpen();
|
||||||
|
}
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return R.mipmap.ven_open;
|
||||||
|
}
|
||||||
|
return R.mipmap.open;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconClose(Controller device) {
|
||||||
|
if (device instanceof Relay) {
|
||||||
|
return ((Relay) device).getIconClose();
|
||||||
|
}
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return R.mipmap.ven_close;
|
||||||
|
}
|
||||||
|
return R.mipmap.close;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getOpenColor(Controller device) {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return Color.parseColor("#00A1FF");
|
||||||
|
}
|
||||||
|
return Color.parseColor("#00BDF4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDisplayName(Controller device) {
|
||||||
|
if (device instanceof Dehumidifier485) {
|
||||||
|
return ((Dehumidifier485) device).getDisplayName();
|
||||||
|
}
|
||||||
|
return device.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,17 @@ public abstract class Controller extends Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行不等待设备响应的指令。
|
||||||
|
*/
|
||||||
|
protected boolean executeInstructionsNoResponse(String instruction, String operateContent) {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MyLog.controller("操作" + name + ":" + operateContent);
|
||||||
|
return serialPortUtil.sendSerialDataNoResponse(this, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPowerSupply() {
|
public boolean isPowerSupply() {
|
||||||
return powerSupply;
|
return powerSupply;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,434 @@
|
|||||||
|
package com.example.iot_controlhost.model.controller;
|
||||||
|
|
||||||
|
import com.blankj.utilcode.util.StringUtils;
|
||||||
|
import com.example.iot_controlhost.base.SetAddress;
|
||||||
|
import com.example.iot_controlhost.utils.MMKVUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 西奈 485 除湿机控制器。
|
||||||
|
*/
|
||||||
|
public class Dehumidifier485 extends Controller implements SetAddress {
|
||||||
|
|
||||||
|
public static final int MODE_DEHUMIDIFY = 0;
|
||||||
|
public static final int MODE_VENTILATION = 1;
|
||||||
|
|
||||||
|
public static final int FAN_LOW = 0;
|
||||||
|
public static final int FAN_MIDDLE = 1;
|
||||||
|
public static final int FAN_HIGH = 2;
|
||||||
|
|
||||||
|
public static final String[] BAUD_LIST = {"4800", "9600", "19200", "115200"};
|
||||||
|
public static final String[] FAN_SPEED_NAMES = {"低风", "中风", "高风"};
|
||||||
|
public static final String[] WORK_MODE_NAMES = {"除湿", "通风"};
|
||||||
|
public static final String[] ADDRESS_LIST = buildAddressList();
|
||||||
|
|
||||||
|
private static final int REG_POWER = 0x0000;
|
||||||
|
private static final int REG_TARGET_HUMIDITY = 0x0001;
|
||||||
|
private static final int REG_TARGET_TEMPERATURE = 0x0002;
|
||||||
|
private static final int REG_FAN_SPEED = 0x0003;
|
||||||
|
private static final int REG_WORK_MODE = 0x0004;
|
||||||
|
private static final int REG_SET_ADDRESS = 0x0009;
|
||||||
|
private static final int REG_SET_BAUD = 0x000E;
|
||||||
|
private static final int REG_BROADCAST_POWER = 0x00EE;
|
||||||
|
|
||||||
|
private final String TARGET_HUMIDITY = name + "targetHumidity";
|
||||||
|
private final String TARGET_TEMPERATURE = name + "targetTemperature";
|
||||||
|
private final String FAN_SPEED = name + "fanSpeed";
|
||||||
|
private final String WORK_MODE = name + "workMode";
|
||||||
|
|
||||||
|
private Integer environmentHumidity;
|
||||||
|
private Integer environmentTemperature;
|
||||||
|
private Integer coilTemperature1;
|
||||||
|
private Integer coilTemperature2;
|
||||||
|
private int workStatus;
|
||||||
|
private int faultCode;
|
||||||
|
private String lastTestState = "未测试";
|
||||||
|
|
||||||
|
public Dehumidifier485(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return "485除湿";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setPowerSupply(boolean state) {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean result;
|
||||||
|
if ("00".equals(getAddress())) {
|
||||||
|
result = sendBroadcastPower(getAddress(), state, true);
|
||||||
|
} else {
|
||||||
|
result = writeRegister(getAddress(), REG_POWER, state ? 1 : 0, true);
|
||||||
|
}
|
||||||
|
if (result) {
|
||||||
|
powerSupply = state;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setTargetHumidity(int humidity) {
|
||||||
|
if (humidity < 5 || humidity > 99) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean result = writeRegister(getAddress(), REG_TARGET_HUMIDITY, humidity, true);
|
||||||
|
if (result) {
|
||||||
|
setTargetHumidityCache(humidity);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTargetHumidity() {
|
||||||
|
return MMKVUtil.get(TARGET_HUMIDITY, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetHumidityCache(int humidity) {
|
||||||
|
MMKVUtil.put(TARGET_HUMIDITY, limit(humidity, 5, 99));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setTargetTemperature(int temperature) {
|
||||||
|
if (temperature < 5 || temperature > 70) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean result = writeRegister(getAddress(), REG_TARGET_TEMPERATURE, temperature, true);
|
||||||
|
if (result) {
|
||||||
|
setTargetTemperatureCache(temperature);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTargetTemperature() {
|
||||||
|
return MMKVUtil.get(TARGET_TEMPERATURE, 26);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetTemperatureCache(int temperature) {
|
||||||
|
MMKVUtil.put(TARGET_TEMPERATURE, limit(temperature, 5, 70));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setFanSpeed(int fanSpeed) {
|
||||||
|
if (fanSpeed < FAN_LOW || fanSpeed > FAN_HIGH) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean result = writeRegister(getAddress(), REG_FAN_SPEED, fanSpeed, true);
|
||||||
|
if (result) {
|
||||||
|
setFanSpeedCache(fanSpeed);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFanSpeed() {
|
||||||
|
return MMKVUtil.get(FAN_SPEED, FAN_HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFanSpeedCache(int fanSpeed) {
|
||||||
|
MMKVUtil.put(FAN_SPEED, limit(fanSpeed, FAN_LOW, FAN_HIGH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFanSpeedName() {
|
||||||
|
int fanSpeed = getFanSpeed();
|
||||||
|
return fanSpeed >= FAN_LOW && fanSpeed <= FAN_HIGH ? FAN_SPEED_NAMES[fanSpeed] : "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setWorkMode(int workMode) {
|
||||||
|
if (workMode < MODE_DEHUMIDIFY || workMode > MODE_VENTILATION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean result = writeRegister(getAddress(), REG_WORK_MODE, workMode, true);
|
||||||
|
if (result) {
|
||||||
|
setWorkModeCache(workMode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWorkMode() {
|
||||||
|
return MMKVUtil.get(WORK_MODE, MODE_DEHUMIDIFY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkModeCache(int workMode) {
|
||||||
|
MMKVUtil.put(WORK_MODE, limit(workMode, MODE_DEHUMIDIFY, MODE_VENTILATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWorkModeName() {
|
||||||
|
int workMode = getWorkMode();
|
||||||
|
return workMode >= MODE_DEHUMIDIFY && workMode <= MODE_VENTILATION ? WORK_MODE_NAMES[workMode] : "未知";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean readState() {
|
||||||
|
if (!isAvailable() || "00".equals(getAddress())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return readState(getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean readState(String address) {
|
||||||
|
if (StringUtils.isEmpty(address) || "00".equals(address)) {
|
||||||
|
lastTestState = "00 地址用于广播或读取设备地址,不能读取运行状态";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String str = address + "0300000014";
|
||||||
|
String instruction = str + getCRC(str);
|
||||||
|
String result = serialPortUtil.sendAndReceiveSerialData(this, instruction);
|
||||||
|
if (StringUtils.isEmpty(result)) {
|
||||||
|
lastTestState = "读取状态失败";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean parsed = parseState(result);
|
||||||
|
lastTestState = parsed ? getDetailState() : "状态数据解析失败";
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readCurrentAddress() {
|
||||||
|
String str = "002500DF0001";
|
||||||
|
String instruction = str + getCRC(str);
|
||||||
|
String result = serialPortUtil.sendAndReceiveSerialData(this, instruction);
|
||||||
|
if (StringUtils.isEmpty(result) || result.length() < 12) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return result.substring(6, 8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
if (!isAvailable()) {
|
||||||
|
return "未正确配置";
|
||||||
|
}
|
||||||
|
if (!isPowerSupply()) {
|
||||||
|
return "未启动";
|
||||||
|
}
|
||||||
|
String humidityText = environmentHumidity == null ? "" : " 湿度" + environmentHumidity + "%";
|
||||||
|
return "运行中 " + getWorkModeName() + humidityText + " 目标" + getTargetHumidity() + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDetailState() {
|
||||||
|
return "电源:" + (isPowerSupply() ? "开启" : "关闭")
|
||||||
|
+ "\n目标湿度:" + getTargetHumidity() + "%"
|
||||||
|
+ "\n目标温度:" + getTargetTemperature() + "℃"
|
||||||
|
+ "\n风速:" + getFanSpeedName()
|
||||||
|
+ "\n模式:" + getWorkModeName()
|
||||||
|
+ "\n环境湿度:" + getEnvironmentHumidityText()
|
||||||
|
+ "\n环境温度:" + getEnvironmentTemperatureText()
|
||||||
|
+ "\n工作状态:" + getWorkStatusText()
|
||||||
|
+ "\n故障:" + getFaultText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnvironmentHumidityText() {
|
||||||
|
return environmentHumidity == null ? "--" : environmentHumidity + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnvironmentTemperatureText() {
|
||||||
|
return environmentTemperature == null ? "--" : environmentTemperature + "℃";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFaultText() {
|
||||||
|
if (faultCode == 0) {
|
||||||
|
return "正常";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
appendFault(builder, 0, "温湿度传感器故障");
|
||||||
|
appendFault(builder, 1, "化霜温度1故障");
|
||||||
|
appendFault(builder, 2, "化霜温度2故障");
|
||||||
|
appendFault(builder, 3, "高压保护");
|
||||||
|
appendFault(builder, 4, "低压保护");
|
||||||
|
appendFault(builder, 5, "相序保护");
|
||||||
|
appendFault(builder, 6, "缺相保护");
|
||||||
|
appendFault(builder, 7, "超温保护");
|
||||||
|
appendFault(builder, 8, "电源电压超高保护");
|
||||||
|
appendFault(builder, 9, "水满告警");
|
||||||
|
appendFault(builder, 10, "漏氟保护");
|
||||||
|
return builder.length() == 0 ? "未知故障:" + faultCode : builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWorkStatusText() {
|
||||||
|
if (workStatus == 0) {
|
||||||
|
return "待机";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
appendStatus(builder, 0, "除湿");
|
||||||
|
appendStatus(builder, 1, "化霜");
|
||||||
|
appendStatus(builder, 2, "制冷");
|
||||||
|
appendStatus(builder, 3, "制热");
|
||||||
|
return builder.length() == 0 ? "运行中" : builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return isEnable() && !StringUtils.isEmpty(getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getModels() {
|
||||||
|
return new String[]{"西奈 Z101/Z102/Z103/X86 485除湿机"};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setAddressToNewAddress(String model, String oldAddress, String oldBaud, String newAddress) {
|
||||||
|
if (!model.equals(getModels()[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int addressValue = parseHex(newAddress, -1);
|
||||||
|
if (addressValue < 1 || addressValue > 99) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ("00".equals(oldAddress)) {
|
||||||
|
return writeRegisterNoResponse(oldAddress, REG_SET_ADDRESS, addressValue);
|
||||||
|
}
|
||||||
|
return writeRegister(oldAddress, REG_SET_ADDRESS, addressValue, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setBaudToNewBaud(String model, String oldAddress, String newBaud) {
|
||||||
|
if (!model.equals(getModels()[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int baudValue;
|
||||||
|
switch (newBaud) {
|
||||||
|
case "4800":
|
||||||
|
baudValue = 1;
|
||||||
|
break;
|
||||||
|
case "9600":
|
||||||
|
baudValue = 2;
|
||||||
|
break;
|
||||||
|
case "19200":
|
||||||
|
baudValue = 3;
|
||||||
|
break;
|
||||||
|
case "115200":
|
||||||
|
baudValue = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ("00".equals(oldAddress)) {
|
||||||
|
return writeRegisterNoResponse(oldAddress, REG_SET_BAUD, baudValue);
|
||||||
|
}
|
||||||
|
return writeRegister(oldAddress, REG_SET_BAUD, baudValue, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(String deviceModel, String deviceAddress) {
|
||||||
|
if (!deviceModel.equals(getModels()[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ("00".equals(deviceAddress)) {
|
||||||
|
String address = readCurrentAddress();
|
||||||
|
lastTestState = address == null ? "读取设备地址失败" : "当前设备地址:" + address;
|
||||||
|
return address != null;
|
||||||
|
}
|
||||||
|
return readState(deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTestState() {
|
||||||
|
return lastTestState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean parseState(String result) {
|
||||||
|
try {
|
||||||
|
if (result.length() < 90 || !"03".equals(result.substring(2, 4))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int byteCount = parseHex(result.substring(4, 6), -1);
|
||||||
|
if (byteCount < 40) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int power = getRegister(result, 0);
|
||||||
|
powerSupply = power == 1;
|
||||||
|
setTargetHumidityCache(getRegister(result, 1));
|
||||||
|
setTargetTemperatureCache(getRegister(result, 2));
|
||||||
|
setFanSpeedCache(getRegister(result, 3));
|
||||||
|
setWorkModeCache(getRegister(result, 4));
|
||||||
|
workStatus = getRegister(result, 5);
|
||||||
|
int humidity = getRegister(result, 6);
|
||||||
|
environmentHumidity = humidity == 0x00FF ? null : humidity;
|
||||||
|
int temperature = getRegister(result, 7);
|
||||||
|
environmentTemperature = temperature == 0x00FF ? null : toSigned16(temperature);
|
||||||
|
faultCode = getRegister(result, 8);
|
||||||
|
int coil1 = getRegister(result, 10);
|
||||||
|
coilTemperature1 = coil1 == 0x00FF ? null : toSigned16(coil1);
|
||||||
|
int coil2 = getRegister(result, 11);
|
||||||
|
coilTemperature2 = coil2 == 0x00FF ? null : toSigned16(coil2);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRegister(String result, int index) {
|
||||||
|
int start = 6 + index * 4;
|
||||||
|
return parseHex(result.substring(start, start + 4), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeRegister(String address, int register, int value, boolean checkAvailable) {
|
||||||
|
if (checkAvailable && !isAvailable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String str = address + "06" + String.format("%04X", register) + String.format("%04X", value);
|
||||||
|
String instruction = str + getCRC(str);
|
||||||
|
return instruction.equals(serialPortUtil.sendAndReceiveSerialData(this, instruction));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeRegisterNoResponse(String address, int register, int value) {
|
||||||
|
String str = address + "06" + String.format("%04X", register) + String.format("%04X", value);
|
||||||
|
String instruction = str + getCRC(str);
|
||||||
|
return serialPortUtil.sendSerialDataNoResponse(this, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendBroadcastPower(String address, boolean state, boolean checkAvailable) {
|
||||||
|
if (checkAvailable && !isAvailable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String str = address + "06" + String.format("%04X", REG_BROADCAST_POWER) + (state ? "00AA" : "0055");
|
||||||
|
String instruction = str + getCRC(str);
|
||||||
|
return checkAvailable
|
||||||
|
? executeInstructionsNoResponse(instruction, state ? "广播开机" : "广播关机")
|
||||||
|
: serialPortUtil.sendSerialDataNoResponse(this, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendFault(StringBuilder builder, int bit, String text) {
|
||||||
|
if ((faultCode & (1 << bit)) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.append("、");
|
||||||
|
}
|
||||||
|
builder.append(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendStatus(StringBuilder builder, int bit, String text) {
|
||||||
|
if ((workStatus & (1 << bit)) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.append("、");
|
||||||
|
}
|
||||||
|
builder.append(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseHex(String hex, int defaultValue) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(hex, 16);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toSigned16(int value) {
|
||||||
|
return value > 0x7FFF ? value - 0x10000 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int limit(int value, int min, int max) {
|
||||||
|
return Math.max(min, Math.min(max, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] buildAddressList() {
|
||||||
|
String[] result = new String[100];
|
||||||
|
result[0] = "00";
|
||||||
|
for (int i = 1; i <= 99; i++) {
|
||||||
|
result[i] = String.format("%02X", i);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.example.iot_controlhost.R;
|
|||||||
import com.example.iot_controlhost.base.BaseActivity;
|
import com.example.iot_controlhost.base.BaseActivity;
|
||||||
import com.example.iot_controlhost.base.SetAddress;
|
import com.example.iot_controlhost.base.SetAddress;
|
||||||
import com.example.iot_controlhost.databinding.ActivityDebugBinding;
|
import com.example.iot_controlhost.databinding.ActivityDebugBinding;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.model.sensor.Sensor;
|
import com.example.iot_controlhost.model.sensor.Sensor;
|
||||||
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
||||||
import com.example.iot_controlhost.ui.dialog.ConfirmDialog;
|
import com.example.iot_controlhost.ui.dialog.ConfirmDialog;
|
||||||
@@ -47,6 +48,7 @@ public class DebugActivity extends BaseActivity<ActivityDebugBinding, DebugActiv
|
|||||||
List<String> deviceNames = new ArrayList<>();
|
List<String> deviceNames = new ArrayList<>();
|
||||||
deviceNames.add(RoomController.relay.getName());
|
deviceNames.add(RoomController.relay.getName());
|
||||||
deviceNames.add(RoomController.airConditionInfrared.getName());
|
deviceNames.add(RoomController.airConditionInfrared.getName());
|
||||||
|
deviceNames.add(RoomController.dehumidifier485.getName());
|
||||||
deviceNames.addAll(RoomSensor.getAllSensorNames());
|
deviceNames.addAll(RoomSensor.getAllSensorNames());
|
||||||
binding.acSensorType.setAdapter(new CustomSpinnerAdapter(mContext, deviceNames.toArray(new String[0])));
|
binding.acSensorType.setAdapter(new CustomSpinnerAdapter(mContext, deviceNames.toArray(new String[0])));
|
||||||
binding.acSensorType.addTextChangedListener(new TextWatcher() {
|
binding.acSensorType.addTextChangedListener(new TextWatcher() {
|
||||||
@@ -59,6 +61,7 @@ public class DebugActivity extends BaseActivity<ActivityDebugBinding, DebugActiv
|
|||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
//在选择设备类型后,自动选择设备型号
|
//在选择设备类型后,自动选择设备型号
|
||||||
|
binding.acNewBaud.setAdapter(new CustomSpinnerAdapter(mContext, SpinnerList.BAUD));
|
||||||
if (charSequence.toString().equals(RoomController.relay.getName())) {
|
if (charSequence.toString().equals(RoomController.relay.getName())) {
|
||||||
setAddress = RoomController.relay;
|
setAddress = RoomController.relay;
|
||||||
binding.acSensorModel.setAdapter(new CustomSpinnerAdapter(mContext, new String[]{RoomController.relay.getModels()[1]}));
|
binding.acSensorModel.setAdapter(new CustomSpinnerAdapter(mContext, new String[]{RoomController.relay.getModels()[1]}));
|
||||||
@@ -66,6 +69,10 @@ public class DebugActivity extends BaseActivity<ActivityDebugBinding, DebugActiv
|
|||||||
//调试时,只需要一个空调即可,RoomController.airConditionInfrared
|
//调试时,只需要一个空调即可,RoomController.airConditionInfrared
|
||||||
setAddress = RoomController.airConditionInfrared;
|
setAddress = RoomController.airConditionInfrared;
|
||||||
binding.acSensorModel.setAdapter(new CustomSpinnerAdapter(mContext, new String[]{RoomController.airConditionInfrared.getModels()[0]}));
|
binding.acSensorModel.setAdapter(new CustomSpinnerAdapter(mContext, new String[]{RoomController.airConditionInfrared.getModels()[0]}));
|
||||||
|
} else if (charSequence.toString().equals(RoomController.dehumidifier485.getName())) {
|
||||||
|
setAddress = RoomController.dehumidifier485;
|
||||||
|
binding.acSensorModel.setAdapter(new CustomSpinnerAdapter(mContext, RoomController.dehumidifier485.getModels()));
|
||||||
|
binding.acNewBaud.setAdapter(new CustomSpinnerAdapter(mContext, Dehumidifier485.BAUD_LIST));
|
||||||
} else {
|
} else {
|
||||||
binding.btnReadAndParse.setEnabled(true);
|
binding.btnReadAndParse.setEnabled(true);
|
||||||
for (Sensor sensor : RoomSensor.getAllSensors()) {
|
for (Sensor sensor : RoomSensor.getAllSensors()) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class MainActivity extends BaseActivity<ActivityIncubationBinding, MainAc
|
|||||||
private long mExitTime;
|
private long mExitTime;
|
||||||
AppBarViewModel appBarViewModel;
|
AppBarViewModel appBarViewModel;
|
||||||
WorkDialog workDialog;
|
WorkDialog workDialog;
|
||||||
|
private PasswordDialog lockPasswordDialog;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initView() {
|
public void initView() {
|
||||||
@@ -110,11 +111,7 @@ public class MainActivity extends BaseActivity<ActivityIncubationBinding, MainAc
|
|||||||
presenter.getNoticeLiveData().observe(this, integer -> {
|
presenter.getNoticeLiveData().observe(this, integer -> {
|
||||||
switch (integer) {
|
switch (integer) {
|
||||||
case 2 ->//锁屏
|
case 2 ->//锁屏
|
||||||
new PasswordDialog(mContext, "请输入锁屏密码", RoomSetting.getMainActivityLock(), v1 -> {
|
showLockPasswordDialog();
|
||||||
binding.mainLock.setVisibility(View.GONE);
|
|
||||||
binding.mainKey.setImageDrawable(getDrawable(R.mipmap.unlock));
|
|
||||||
refreshLock();
|
|
||||||
}).show();
|
|
||||||
case 3 ->//进入设置
|
case 3 ->//进入设置
|
||||||
new SetBaseDialog(mContext).show();
|
new SetBaseDialog(mContext).show();
|
||||||
case 4 -> {//结束登记弹窗
|
case 4 -> {//结束登记弹窗
|
||||||
@@ -298,6 +295,19 @@ public class MainActivity extends BaseActivity<ActivityIncubationBinding, MainAc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showLockPasswordDialog() {
|
||||||
|
if (lockPasswordDialog != null && lockPasswordDialog.isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lockPasswordDialog = new PasswordDialog(mContext, "请输入锁屏密码", RoomSetting.getMainActivityLock(), v1 -> {
|
||||||
|
binding.mainLock.setVisibility(View.GONE);
|
||||||
|
binding.mainKey.setImageDrawable(getDrawable(R.mipmap.unlock));
|
||||||
|
refreshLock();
|
||||||
|
});
|
||||||
|
lockPasswordDialog.setOnDismissListener(dialogInterface -> lockPasswordDialog = null);
|
||||||
|
lockPasswordDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
private ScheduledExecutorService mainLockExecutorService;
|
private ScheduledExecutorService mainLockExecutorService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.example.iot_controlhost.databinding.ItemSetBinding;
|
|||||||
import com.example.iot_controlhost.model.Device;
|
import com.example.iot_controlhost.model.Device;
|
||||||
import com.example.iot_controlhost.model.Set;
|
import com.example.iot_controlhost.model.Set;
|
||||||
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.model.controller.DehumidifierInfrared;
|
import com.example.iot_controlhost.model.controller.DehumidifierInfrared;
|
||||||
import com.example.iot_controlhost.model.controller.Floor;
|
import com.example.iot_controlhost.model.controller.Floor;
|
||||||
import com.example.iot_controlhost.model.net.AirConditionList;
|
import com.example.iot_controlhost.model.net.AirConditionList;
|
||||||
@@ -29,6 +30,7 @@ import com.example.iot_controlhost.ui.dialog.AirConditionAddDialog;
|
|||||||
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
||||||
import com.example.iot_controlhost.ui.dialog.ConfirmDialog;
|
import com.example.iot_controlhost.ui.dialog.ConfirmDialog;
|
||||||
import com.example.iot_controlhost.ui.dialog.DehumidityAddDialog;
|
import com.example.iot_controlhost.ui.dialog.DehumidityAddDialog;
|
||||||
|
import com.example.iot_controlhost.ui.dialog.Dehumidifier485Dialog;
|
||||||
import com.example.iot_controlhost.ui.dialog.PasswordDialog;
|
import com.example.iot_controlhost.ui.dialog.PasswordDialog;
|
||||||
import com.example.iot_controlhost.ui.dialog.SetDeviceBaseDialog;
|
import com.example.iot_controlhost.ui.dialog.SetDeviceBaseDialog;
|
||||||
import com.example.iot_controlhost.ui.dialog.SetPWMDialog;
|
import com.example.iot_controlhost.ui.dialog.SetPWMDialog;
|
||||||
@@ -78,6 +80,7 @@ public class SetActivity extends BaseActivity<ActivitySetBinding, SetActivityPre
|
|||||||
case 1 -> MyUtil.relaunchApp();
|
case 1 -> MyUtil.relaunchApp();
|
||||||
case 2 -> setAirCondition();
|
case 2 -> setAirCondition();
|
||||||
case 3 -> setAdvanced();
|
case 3 -> setAdvanced();
|
||||||
|
case 4 -> setDeHumidity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
presenter.getShowImportAirConditionInstructionDialogLiveData().observe(this,
|
presenter.getShowImportAirConditionInstructionDialogLiveData().observe(this,
|
||||||
@@ -99,6 +102,8 @@ public class SetActivity extends BaseActivity<ActivitySetBinding, SetActivityPre
|
|||||||
setSensor();
|
setSensor();
|
||||||
} else if (toMain == 2) {
|
} else if (toMain == 2) {
|
||||||
setAirCondition();
|
setAirCondition();
|
||||||
|
} else if (toMain == 3) {
|
||||||
|
setDeHumidity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -276,19 +281,48 @@ public class SetActivity extends BaseActivity<ActivitySetBinding, SetActivityPre
|
|||||||
*/
|
*/
|
||||||
void setDeHumidity() {
|
void setDeHumidity() {
|
||||||
toMain = 0;
|
toMain = 0;
|
||||||
|
binding.tvTitle.setText(getText(R.string.set) + " > 除湿机配置");
|
||||||
|
setList.clear();
|
||||||
|
setList.add(new Set("485除湿机配置", RoomController.dehumidifier485.toString(), view -> setDehumidifier485()));
|
||||||
|
setList.add(new Set("红外除湿机配置", RoomController.dehumidifierInfrared.toString(), view -> setDeHumidityInfrared()));
|
||||||
|
setAdapter.setDataList(setList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDehumidifier485() {
|
||||||
|
toMain = 3;
|
||||||
|
Dehumidifier485 dehumidifier485 = RoomController.dehumidifier485;
|
||||||
|
binding.tvTitle.setText(getText(R.string.set) + " > 除湿机配置 > 485除湿机");
|
||||||
|
setList.clear();
|
||||||
|
setList.add(new Set("启用485除湿机", dehumidifier485.isEnable(), (compoundButton, b) -> {
|
||||||
|
dehumidifier485.setEnable(b);
|
||||||
|
setDehumidifier485();
|
||||||
|
}));
|
||||||
|
setList.add(new Set("基础配置", dehumidifier485.toString(), view ->
|
||||||
|
new SetDeviceBaseDialog(mContext, "485除湿机基础配置", dehumidifier485.getModels(),
|
||||||
|
getString(R.string.select_model), Dehumidifier485.ADDRESS_LIST, getString(R.string.select_address), (model, address) -> {
|
||||||
|
dehumidifier485.setModel(model);
|
||||||
|
dehumidifier485.setAddress(address);
|
||||||
|
setDehumidifier485();
|
||||||
|
}).show()));
|
||||||
|
setList.add(new Set("控制测试", dehumidifier485.getState(), view -> new Dehumidifier485Dialog(mContext, dehumidifier485).show()));
|
||||||
|
setAdapter.setDataList(setList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDeHumidityInfrared() {
|
||||||
|
toMain = 3;
|
||||||
DehumidifierInfrared deHumidityInfrared = RoomController.dehumidifierInfrared;
|
DehumidifierInfrared deHumidityInfrared = RoomController.dehumidifierInfrared;
|
||||||
binding.tvTitle.setText(getText(R.string.set) + " > 除湿机配置");
|
binding.tvTitle.setText(getText(R.string.set) + " > 除湿机配置");
|
||||||
setList.clear();
|
setList.clear();
|
||||||
setList.add(new Set(getString(R.string.enable_air_condition_infrared), deHumidityInfrared.isEnable(), (compoundButton, b) -> {
|
setList.add(new Set(getString(R.string.enable_air_condition_infrared), deHumidityInfrared.isEnable(), (compoundButton, b) -> {
|
||||||
deHumidityInfrared.setEnable(b);
|
deHumidityInfrared.setEnable(b);
|
||||||
setDeHumidity();
|
setDeHumidityInfrared();
|
||||||
}));
|
}));
|
||||||
setList.add(new Set(getString(R.string.set_base_infrared), deHumidityInfrared.toString(), view ->
|
setList.add(new Set(getString(R.string.set_base_infrared), deHumidityInfrared.toString(), view ->
|
||||||
new SetDeviceBaseDialog(mContext, getString(R.string.set_base_infrared), deHumidityInfrared.getModels(),
|
new SetDeviceBaseDialog(mContext, getString(R.string.set_base_infrared), deHumidityInfrared.getModels(),
|
||||||
getString(R.string.select_model), SpinnerList.ADDRESS, getString(R.string.select_address), (model, address) -> {
|
getString(R.string.select_model), SpinnerList.ADDRESS, getString(R.string.select_address), (model, address) -> {
|
||||||
deHumidityInfrared.setModel(model);
|
deHumidityInfrared.setModel(model);
|
||||||
deHumidityInfrared.setAddress(address);
|
deHumidityInfrared.setAddress(address);
|
||||||
setDeHumidity();
|
setDeHumidityInfrared();
|
||||||
}).show()));
|
}).show()));
|
||||||
setList.add(new Set("导入除湿机指令", "除湿机指令集", view ->
|
setList.add(new Set("导入除湿机指令", "除湿机指令集", view ->
|
||||||
presenter.getAirConditionModelList(-1)));
|
presenter.getAirConditionModelList(-1)));
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ public class SetActivityPresenter extends BasePresenter {
|
|||||||
}
|
}
|
||||||
// 只有开机关机两条指令
|
// 只有开机关机两条指令
|
||||||
String openInstruction = instructions.get(0);
|
String openInstruction = instructions.get(0);
|
||||||
boolean result = RoomController.airConditionInfrared.writeInstruction(200, openInstruction);
|
boolean result = RoomController.dehumidifierInfrared.writeInstruction(200, openInstruction);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
showLoadingDialogInIO("导入" + targetAirCondition + "型空调\n开机指令,指令错误!!!");
|
showLoadingDialogInIO("导入" + targetAirCondition + "型空调\n开机指令,指令错误!!!");
|
||||||
MyLog.controller("导入开机指令,云端指令有误");
|
MyLog.controller("导入开机指令,云端指令有误");
|
||||||
@@ -327,7 +327,7 @@ public class SetActivityPresenter extends BasePresenter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String closeInstruction = instructions.get(1);
|
String closeInstruction = instructions.get(1);
|
||||||
result = RoomController.airConditionInfrared.writeInstruction(201, closeInstruction);
|
result = RoomController.dehumidifierInfrared.writeInstruction(201, closeInstruction);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
showLoadingDialogInIO("导入" + targetAirCondition + "型空调\n关机指令,指令错误!!!");
|
showLoadingDialogInIO("导入" + targetAirCondition + "型空调\n关机指令,指令错误!!!");
|
||||||
MyLog.controller("导入关机指令,云端指令有误");
|
MyLog.controller("导入关机指令,云端指令有误");
|
||||||
@@ -346,7 +346,7 @@ public class SetActivityPresenter extends BasePresenter {
|
|||||||
} else {
|
} else {
|
||||||
errorTips("导入空调指令失败");
|
errorTips("导入空调指令失败");
|
||||||
}
|
}
|
||||||
refreshLiveData.setValue(2);
|
refreshLiveData.setValue(4);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -645,6 +645,10 @@ public class SetActivityPresenter extends BasePresenter {
|
|||||||
map.put(RoomController.DEVICE_NAME[15] + Device.ENABLE, RoomController.dehumidifierInfrared.isEnable());
|
map.put(RoomController.DEVICE_NAME[15] + Device.ENABLE, RoomController.dehumidifierInfrared.isEnable());
|
||||||
map.put(RoomController.DEVICE_NAME[15] + Device.MODEL, RoomController.dehumidifierInfrared.getModel());
|
map.put(RoomController.DEVICE_NAME[15] + Device.MODEL, RoomController.dehumidifierInfrared.getModel());
|
||||||
map.put(RoomController.DEVICE_NAME[15] + Device.ADDRESS, RoomController.dehumidifierInfrared.getAddress());
|
map.put(RoomController.DEVICE_NAME[15] + Device.ADDRESS, RoomController.dehumidifierInfrared.getAddress());
|
||||||
|
//485除湿机配置
|
||||||
|
map.put(RoomController.dehumidifier485.getName() + Device.ENABLE, RoomController.dehumidifier485.isEnable());
|
||||||
|
map.put(RoomController.dehumidifier485.getName() + Device.MODEL, RoomController.dehumidifier485.getModel());
|
||||||
|
map.put(RoomController.dehumidifier485.getName() + Device.ADDRESS, RoomController.dehumidifier485.getAddress());
|
||||||
//空调2配置
|
//空调2配置
|
||||||
map.put(RoomController.DEVICE_NAME[14] + Device.ENABLE, RoomController.airConditionInfrared2.isEnable());
|
map.put(RoomController.DEVICE_NAME[14] + Device.ENABLE, RoomController.airConditionInfrared2.isEnable());
|
||||||
map.put(RoomController.DEVICE_NAME[14] + Device.MODEL, RoomController.airConditionInfrared2.getModel());
|
map.put(RoomController.DEVICE_NAME[14] + Device.MODEL, RoomController.airConditionInfrared2.getModel());
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package com.example.iot_controlhost.ui.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.transition.Fade;
|
||||||
|
import android.transition.TransitionManager;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.example.iot_controlhost.R;
|
||||||
|
import com.example.iot_controlhost.base.BaseDialog;
|
||||||
|
import com.example.iot_controlhost.databinding.DialogDehumidifier485Binding;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
|
import com.example.iot_controlhost.model.thread.QueueIOUITask;
|
||||||
|
import com.example.iot_controlhost.utils.DialogUtil;
|
||||||
|
import com.example.iot_controlhost.utils.MyQueue;
|
||||||
|
import com.example.iot_controlhost.utils.global.RoomSetting;
|
||||||
|
import com.example.iot_controlhost.utils.global.RxTag;
|
||||||
|
import com.example.iot_controlhost.utils.log.UserLog;
|
||||||
|
import com.xuexiang.rxutil2.rxbus.RxBusUtils;
|
||||||
|
|
||||||
|
import android_serialport_api.SerialPortUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 485除湿机控制弹窗。
|
||||||
|
*/
|
||||||
|
public class Dehumidifier485Dialog extends BaseDialog<DialogDehumidifier485Binding> {
|
||||||
|
private final Dehumidifier485 dehumidifier;
|
||||||
|
|
||||||
|
public Dehumidifier485Dialog(@NonNull Context mContext, Dehumidifier485 dehumidifier) {
|
||||||
|
super(mContext);
|
||||||
|
this.dehumidifier = dehumidifier;
|
||||||
|
binding.tvTitle.setText(dehumidifier.getName() + "控制");
|
||||||
|
if (!SerialPortUtil.getInstance(SerialPortUtil.TYPE_CONTROLLER).openSerialPort()) {
|
||||||
|
errorTips("串口打开失败");
|
||||||
|
}
|
||||||
|
refreshDehumidifier();
|
||||||
|
binding.cardStatus.setOnClickListener(v -> changeDehumidifier(8));
|
||||||
|
binding.btnPower.setOnClickListener(v -> changeDehumidifier(0));
|
||||||
|
binding.btnHumidityReduce.setOnClickListener(v -> changeDehumidifier(1));
|
||||||
|
binding.btnHumidityPlus.setOnClickListener(v -> changeDehumidifier(2));
|
||||||
|
binding.modeDehumidify.setOnClickListener(v -> changeDehumidifier(3));
|
||||||
|
binding.modeVentilation.setOnClickListener(v -> changeDehumidifier(4));
|
||||||
|
binding.fanLow.setOnClickListener(v -> changeDehumidifier(5));
|
||||||
|
binding.fanMiddle.setOnClickListener(v -> changeDehumidifier(6));
|
||||||
|
binding.fanHigh.setOnClickListener(v -> changeDehumidifier(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshDehumidifier() {
|
||||||
|
TransitionManager.beginDelayedTransition(binding.ll, new Fade());
|
||||||
|
binding.tvTargetHumidity.setText(dehumidifier.isPowerSupply() ? String.valueOf(dehumidifier.getTargetHumidity()) : "-");
|
||||||
|
binding.tvEnvironmentHumidity.setText("环境湿度:" + dehumidifier.getEnvironmentHumidityText());
|
||||||
|
binding.tvEnvironmentTemperature.setText("环境温度:" + dehumidifier.getEnvironmentTemperatureText());
|
||||||
|
binding.tvWorkStatus.setText("状态:" + dehumidifier.getWorkStatusText());
|
||||||
|
binding.tvFault.setText("故障:" + dehumidifier.getFaultText());
|
||||||
|
binding.btnPower.setImageDrawable(mContext.getDrawable(dehumidifier.isPowerSupply() ? R.mipmap.open : R.mipmap.close));
|
||||||
|
binding.ivSelDehumidify.setVisibility(dehumidifier.getWorkMode() == Dehumidifier485.MODE_DEHUMIDIFY ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
binding.ivSelVentilation.setVisibility(dehumidifier.getWorkMode() == Dehumidifier485.MODE_VENTILATION ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
binding.ivSelFanLow.setVisibility(dehumidifier.getFanSpeed() == Dehumidifier485.FAN_LOW ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
binding.ivSelFanMiddle.setVisibility(dehumidifier.getFanSpeed() == Dehumidifier485.FAN_MIDDLE ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
binding.ivSelFanHigh.setVisibility(dehumidifier.getFanSpeed() == Dehumidifier485.FAN_HIGH ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeDehumidifier(int type) {
|
||||||
|
DialogUtil.showLoadingDialog(mContext, mContext.getString(R.string.in_operate));
|
||||||
|
MyQueue.start(MyQueue.TYPE_CONTROLLER, new QueueIOUITask<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean doInQueueThread() {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
if (dehumidifier.isPowerSupply()) {
|
||||||
|
return dehumidifier.setPowerSupply(false);
|
||||||
|
}
|
||||||
|
boolean powerResult = dehumidifier.setPowerSupply(true);
|
||||||
|
if (powerResult) {
|
||||||
|
dehumidifier.setWorkMode(dehumidifier.getWorkMode());
|
||||||
|
dehumidifier.setFanSpeed(dehumidifier.getFanSpeed());
|
||||||
|
dehumidifier.setTargetHumidity(dehumidifier.getTargetHumidity());
|
||||||
|
dehumidifier.setTargetTemperature(dehumidifier.getTargetTemperature());
|
||||||
|
}
|
||||||
|
return powerResult;
|
||||||
|
case 1:
|
||||||
|
return dehumidifier.setTargetHumidity(dehumidifier.getTargetHumidity() - 1);
|
||||||
|
case 2:
|
||||||
|
return dehumidifier.setTargetHumidity(dehumidifier.getTargetHumidity() + 1);
|
||||||
|
case 3:
|
||||||
|
return dehumidifier.setWorkMode(Dehumidifier485.MODE_DEHUMIDIFY);
|
||||||
|
case 4:
|
||||||
|
return dehumidifier.setWorkMode(Dehumidifier485.MODE_VENTILATION);
|
||||||
|
case 5:
|
||||||
|
return dehumidifier.setFanSpeed(Dehumidifier485.FAN_LOW);
|
||||||
|
case 6:
|
||||||
|
return dehumidifier.setFanSpeed(Dehumidifier485.FAN_MIDDLE);
|
||||||
|
case 7:
|
||||||
|
return dehumidifier.setFanSpeed(Dehumidifier485.FAN_HIGH);
|
||||||
|
case 8:
|
||||||
|
return dehumidifier.readState();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doInUIThread(Boolean result) {
|
||||||
|
if (result) {
|
||||||
|
successTips(dehumidifier.getState());
|
||||||
|
UserLog.operate("手动:操作485除湿机 " + dehumidifier.getState());
|
||||||
|
} else {
|
||||||
|
errorTips("操作485除湿机失败");
|
||||||
|
UserLog.operateError("手动:操作485除湿机失败");
|
||||||
|
}
|
||||||
|
refreshDehumidifier();
|
||||||
|
DialogUtil.hideLoadingDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dismiss() {
|
||||||
|
super.dismiss();
|
||||||
|
if (RoomSetting.getMode() == 0) {
|
||||||
|
RxBusUtils.get().post(RxTag.UPDATE_MANUAL, 0);
|
||||||
|
} else if (RoomSetting.getMode() == 1) {
|
||||||
|
RxBusUtils.get().post(RxTag.UPDATE_AUTO, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import com.example.iot_controlhost.base.BaseMode;
|
|||||||
import com.example.iot_controlhost.databinding.FragmentModelAutoBinding;
|
import com.example.iot_controlhost.databinding.FragmentModelAutoBinding;
|
||||||
import com.example.iot_controlhost.databinding.ItemControllerAutoBinding;
|
import com.example.iot_controlhost.databinding.ItemControllerAutoBinding;
|
||||||
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
import com.example.iot_controlhost.model.controller.Floor;
|
import com.example.iot_controlhost.model.controller.Floor;
|
||||||
import com.example.iot_controlhost.model.controller.relay.Relay;
|
import com.example.iot_controlhost.model.controller.relay.Relay;
|
||||||
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
||||||
@@ -68,7 +69,7 @@ public class AutoFragment extends BaseFragment<FragmentModelAutoBinding, AutoFra
|
|||||||
binding.recycleView.setLayoutManager(new GridLayoutManager(mContext, 2));
|
binding.recycleView.setLayoutManager(new GridLayoutManager(mContext, 2));
|
||||||
binding.recycleView2.setAdapter(manualControllerAdapterTwo);
|
binding.recycleView2.setAdapter(manualControllerAdapterTwo);
|
||||||
binding.recycleView2.setLayoutManager(new GridLayoutManager(mContext, 4));
|
binding.recycleView2.setLayoutManager(new GridLayoutManager(mContext, 4));
|
||||||
List<Relay> devices = RoomController.getAllControlRelays();
|
List<Controller> devices = RoomController.getAllControlDevices();
|
||||||
// 第一排显示2个设备
|
// 第一排显示2个设备
|
||||||
if (devices.size() <= 2) {
|
if (devices.size() <= 2) {
|
||||||
int missingCount = 2 - devices.size();
|
int missingCount = 2 - devices.size();
|
||||||
@@ -78,9 +79,9 @@ public class AutoFragment extends BaseFragment<FragmentModelAutoBinding, AutoFra
|
|||||||
}
|
}
|
||||||
manualControllerAdapter.setDataList(devices);
|
manualControllerAdapter.setDataList(devices);
|
||||||
// 第二排显示剩下的设备
|
// 第二排显示剩下的设备
|
||||||
List<Relay> remainingDevices = new ArrayList<>();
|
List<Controller> remainingDevices = new ArrayList<>();
|
||||||
if (devices.size() > 2) {
|
if (devices.size() > 2) {
|
||||||
List<Relay> tempDevices = devices.subList(2, devices.size());
|
List<Controller> tempDevices = devices.subList(2, devices.size());
|
||||||
remainingDevices.addAll(tempDevices);
|
remainingDevices.addAll(tempDevices);
|
||||||
}
|
}
|
||||||
if (remainingDevices.size() < 4) {
|
if (remainingDevices.size() < 4) {
|
||||||
@@ -150,6 +151,7 @@ public class AutoFragment extends BaseFragment<FragmentModelAutoBinding, AutoFra
|
|||||||
|
|
||||||
private void changeFloorState() {
|
private void changeFloorState() {
|
||||||
Floor floor = RoomController.floor;
|
Floor floor = RoomController.floor;
|
||||||
|
binding.tvFloor.setText(RoomSetting.getFloorName());
|
||||||
binding.tvStateFloor.setText(floor.getState());
|
binding.tvStateFloor.setText(floor.getState());
|
||||||
if (floor.isPowerSupply()) {
|
if (floor.isPowerSupply()) {
|
||||||
binding.ivControllerFloor.setImageResource(R.mipmap.floor_open);
|
binding.ivControllerFloor.setImageResource(R.mipmap.floor_open);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.example.iot_controlhost.base.BaseMode;
|
|||||||
import com.example.iot_controlhost.databinding.FragmentModelManualBinding;
|
import com.example.iot_controlhost.databinding.FragmentModelManualBinding;
|
||||||
import com.example.iot_controlhost.databinding.ItemControllerBinding;
|
import com.example.iot_controlhost.databinding.ItemControllerBinding;
|
||||||
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
import com.example.iot_controlhost.model.controller.Floor;
|
import com.example.iot_controlhost.model.controller.Floor;
|
||||||
import com.example.iot_controlhost.model.controller.relay.Relay;
|
import com.example.iot_controlhost.model.controller.relay.Relay;
|
||||||
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
import com.example.iot_controlhost.ui.dialog.AirDialog;
|
||||||
@@ -52,7 +53,7 @@ public class ManualFragment extends BaseFragment<FragmentModelManualBinding, Man
|
|||||||
manualControllerAdapter = new ManualControllerAdapter(mContext, null, ItemControllerBinding.class);
|
manualControllerAdapter = new ManualControllerAdapter(mContext, null, ItemControllerBinding.class);
|
||||||
binding.recycleView.setAdapter(manualControllerAdapter);
|
binding.recycleView.setAdapter(manualControllerAdapter);
|
||||||
binding.recycleView.setLayoutManager(new GridLayoutManager(mContext, 3));
|
binding.recycleView.setLayoutManager(new GridLayoutManager(mContext, 3));
|
||||||
List<Relay> devices = RoomController.getAllControlRelays();
|
List<Controller> devices = RoomController.getAllControlDevices();
|
||||||
int size = devices.size();
|
int size = devices.size();
|
||||||
if (size < 6) {
|
if (size < 6) {
|
||||||
for (int i = 0; i < 6 - size; i++) {
|
for (int i = 0; i < 6 - size; i++) {
|
||||||
|
|||||||
@@ -432,6 +432,8 @@ public class MyUtil {
|
|||||||
devices.add(RoomController.floor);
|
devices.add(RoomController.floor);
|
||||||
devices.add(RoomController.airConditionInfrared);
|
devices.add(RoomController.airConditionInfrared);
|
||||||
devices.add(RoomController.airConditionInfrared2);
|
devices.add(RoomController.airConditionInfrared2);
|
||||||
|
devices.add(RoomController.dehumidifierInfrared);
|
||||||
|
devices.add(RoomController.dehumidifier485);
|
||||||
devices.add(RoomController.relayFloor);
|
devices.add(RoomController.relayFloor);
|
||||||
// 检查固定传感器
|
// 检查固定传感器
|
||||||
Collections.addAll(devices, RoomSensor.outdoorTHSensor, RoomSensor.consumptionSensor, RoomSensor.airTHSensor, RoomSensor.co2OutdoorSensor);
|
Collections.addAll(devices, RoomSensor.outdoorTHSensor, RoomSensor.consumptionSensor, RoomSensor.airTHSensor, RoomSensor.co2OutdoorSensor);
|
||||||
|
|||||||
+32
-5
@@ -1,6 +1,8 @@
|
|||||||
package com.example.iot_controlhost.utils.control.humidity;
|
package com.example.iot_controlhost.utils.control.humidity;
|
||||||
|
|
||||||
import com.example.iot_controlhost.model.thread.QueueIOTask;
|
import com.example.iot_controlhost.model.thread.QueueIOTask;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.utils.MyQueue;
|
import com.example.iot_controlhost.utils.MyQueue;
|
||||||
import com.example.iot_controlhost.utils.MyUtil;
|
import com.example.iot_controlhost.utils.MyUtil;
|
||||||
import com.example.iot_controlhost.utils.control.Control;
|
import com.example.iot_controlhost.utils.control.Control;
|
||||||
@@ -27,6 +29,7 @@ public class HumidityController extends Control {
|
|||||||
* 是否需要开启加湿器直到达到目标湿度
|
* 是否需要开启加湿器直到达到目标湿度
|
||||||
*/
|
*/
|
||||||
private static boolean needOpenToTarget = false;
|
private static boolean needOpenToTarget = false;
|
||||||
|
private static boolean needDehumidifyToTarget = false;
|
||||||
/**
|
/**
|
||||||
* 目标湿度
|
* 目标湿度
|
||||||
*/
|
*/
|
||||||
@@ -46,7 +49,7 @@ public class HumidityController extends Control {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean startMethod() {
|
protected boolean startMethod() {
|
||||||
if (!RoomController.humidifier.isAvailable()) {
|
if (!RoomController.humidifier.isAvailable() && RoomController.getAutoDehumidifier() == null) {
|
||||||
MyLog.autoError("加湿器不可用,无法自动控制");
|
MyLog.autoError("加湿器不可用,无法自动控制");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -76,18 +79,31 @@ public class HumidityController extends Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 除湿逻辑(新增)
|
// 除湿逻辑(新增)
|
||||||
if (cur > max) {
|
if (cur > max || cur > target && needDehumidifyToTarget) {
|
||||||
|
needDehumidifyToTarget = true;
|
||||||
needDehumidify = true;
|
needDehumidify = true;
|
||||||
|
} else {
|
||||||
|
needDehumidifyToTarget = false;
|
||||||
|
needDehumidify = false;
|
||||||
}
|
}
|
||||||
// === 互斥处理 ===
|
// === 互斥处理 ===
|
||||||
if (needHumidify && needDehumidify) {
|
if (needHumidify && needDehumidify) {
|
||||||
// 理论不会发生,保险处理
|
// 理论不会发生,保险处理
|
||||||
needDehumidify = false;
|
needDehumidify = false;
|
||||||
|
needDehumidifyToTarget = false;
|
||||||
}
|
}
|
||||||
boolean humidifierState = needHumidify;
|
boolean humidifierState = needHumidify;
|
||||||
boolean dehumidifierState = needDehumidify;
|
boolean dehumidifierState = needDehumidify;
|
||||||
|
Controller autoDehumidifier = RoomController.getAutoDehumidifier();
|
||||||
|
int dehumidifierTargetHumidity = (int) Math.round(target);
|
||||||
|
boolean needRefreshDehumidifierSetting = autoDehumidifier instanceof Dehumidifier485
|
||||||
|
&& dehumidifierState
|
||||||
|
&& ((Dehumidifier485) autoDehumidifier).getTargetHumidity() != dehumidifierTargetHumidity;
|
||||||
|
boolean humidifierKeep = !RoomController.humidifier.isAvailable() || RoomController.humidifier.isPowerSupply() == humidifierState;
|
||||||
|
boolean dehumidifierKeep = autoDehumidifier == null
|
||||||
|
|| autoDehumidifier.isPowerSupply() == dehumidifierState && !needRefreshDehumidifierSetting;
|
||||||
|
|
||||||
if (RoomController.humidifier.isPowerSupply() == humidifierState && RoomController.dehumidifier.isPowerSupply() == dehumidifierState) {
|
if (humidifierKeep && dehumidifierKeep) {
|
||||||
MyLog.auto("湿度-控制维持当前状态");
|
MyLog.auto("湿度-控制维持当前状态");
|
||||||
} else {
|
} else {
|
||||||
// 加湿器控制
|
// 加湿器控制
|
||||||
@@ -102,10 +118,15 @@ public class HumidityController extends Control {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
// 除湿器控制(新增)
|
// 除湿器控制(新增)
|
||||||
if (RoomController.dehumidifier.isAvailable()) {
|
if (autoDehumidifier != null) {
|
||||||
MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
|
MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
|
||||||
MyLog.auto("自动:" + (dehumidifierState ? "开启" : "关闭") + "除湿机--");
|
MyLog.auto("自动:" + (dehumidifierState ? "开启" : "关闭") + "除湿机--");
|
||||||
MyUtil.autoControlOperateThird(RoomController.dehumidifier, dehumidifierState);
|
if (autoDehumidifier instanceof Dehumidifier485 && dehumidifierState) {
|
||||||
|
Dehumidifier485 dehumidifier485 = (Dehumidifier485) autoDehumidifier;
|
||||||
|
dehumidifier485.setWorkMode(Dehumidifier485.MODE_DEHUMIDIFY);
|
||||||
|
dehumidifier485.setTargetHumidity(dehumidifierTargetHumidity);
|
||||||
|
}
|
||||||
|
MyUtil.autoControlOperateThird(autoDehumidifier, dehumidifierState);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,8 +136,14 @@ public class HumidityController extends Control {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void stopMethod() {
|
protected void stopMethod() {
|
||||||
|
needOpenToTarget = false;
|
||||||
|
needDehumidifyToTarget = false;
|
||||||
MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
|
MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> {
|
||||||
MyUtil.autoControlOperateThird(RoomController.humidifier);
|
MyUtil.autoControlOperateThird(RoomController.humidifier);
|
||||||
|
Controller autoDehumidifier = RoomController.getAutoDehumidifier();
|
||||||
|
if (autoDehumidifier != null) {
|
||||||
|
MyUtil.autoControlOperateThird(autoDehumidifier, false);
|
||||||
|
}
|
||||||
String airExchangeMode = AutoModelSet.getAirExchangeMode();
|
String airExchangeMode = AutoModelSet.getAirExchangeMode();
|
||||||
if (RoomController.airExchange.isAvailable() && airExchangeMode.equals(SpinnerList.AIR_EXCHANGE_MODES[2])) {
|
if (RoomController.airExchange.isAvailable() && airExchangeMode.equals(SpinnerList.AIR_EXCHANGE_MODES[2])) {
|
||||||
MyUtil.autoControlOperateThird(RoomController.airExchange, false);
|
MyUtil.autoControlOperateThird(RoomController.airExchange, false);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.example.iot_controlhost.utils.global;
|
|||||||
import com.example.iot_controlhost.R;
|
import com.example.iot_controlhost.R;
|
||||||
import com.example.iot_controlhost.model.Device;
|
import com.example.iot_controlhost.model.Device;
|
||||||
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
import com.example.iot_controlhost.model.controller.AirConditionInfrared;
|
||||||
|
import com.example.iot_controlhost.model.controller.Controller;
|
||||||
|
import com.example.iot_controlhost.model.controller.Dehumidifier485;
|
||||||
import com.example.iot_controlhost.model.controller.DehumidifierInfrared;
|
import com.example.iot_controlhost.model.controller.DehumidifierInfrared;
|
||||||
import com.example.iot_controlhost.model.controller.Floor;
|
import com.example.iot_controlhost.model.controller.Floor;
|
||||||
import com.example.iot_controlhost.model.controller.relay.AirCondition;
|
import com.example.iot_controlhost.model.controller.relay.AirCondition;
|
||||||
@@ -59,6 +61,10 @@ public class RoomController {
|
|||||||
* 除湿机
|
* 除湿机
|
||||||
*/
|
*/
|
||||||
public static DehumidifierInfrared dehumidifierInfrared = new DehumidifierInfrared(DEVICE_NAME[15]);
|
public static DehumidifierInfrared dehumidifierInfrared = new DehumidifierInfrared(DEVICE_NAME[15]);
|
||||||
|
/**
|
||||||
|
* 485除湿机
|
||||||
|
*/
|
||||||
|
public static Dehumidifier485 dehumidifier485 = new Dehumidifier485("485除湿机");
|
||||||
|
|
||||||
//——————————————————————————————————————————————以下为继电器下设备——————————————————————————————————————————————————
|
//——————————————————————————————————————————————以下为继电器下设备——————————————————————————————————————————————————
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +138,7 @@ public class RoomController {
|
|||||||
devices.add(floor);
|
devices.add(floor);
|
||||||
devices.add(airConditionInfrared);
|
devices.add(airConditionInfrared);
|
||||||
devices.add(dehumidifierInfrared);
|
devices.add(dehumidifierInfrared);
|
||||||
|
devices.add(dehumidifier485);
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +181,31 @@ public class RoomController {
|
|||||||
* @param deviceName 设备名称 需要在 PublicClass.DEVICE_NAME选用
|
* @param deviceName 设备名称 需要在 PublicClass.DEVICE_NAME选用
|
||||||
* @return 设备类 可用于设置端口地址等操作
|
* @return 设备类 可用于设置端口地址等操作
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* 获得手动/自动页面可直接控制的设备。
|
||||||
|
*/
|
||||||
|
public static List<Controller> getAllControlDevices() {
|
||||||
|
List<Controller> devices = new ArrayList<>();
|
||||||
|
devices.addAll(getAllControlRelays());
|
||||||
|
if (dehumidifier485.isAvailable()) {
|
||||||
|
devices.add(dehumidifier485);
|
||||||
|
}
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 湿度自动控制优先使用485除湿机,未配置时兼容旧继电器除湿机。
|
||||||
|
*/
|
||||||
|
public static Controller getAutoDehumidifier() {
|
||||||
|
if (dehumidifier485.isAvailable()) {
|
||||||
|
return dehumidifier485;
|
||||||
|
}
|
||||||
|
if (dehumidifier.isAvailable()) {
|
||||||
|
return dehumidifier;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static Relay getRelay(String deviceName) {
|
public static Relay getRelay(String deviceName) {
|
||||||
for (int i = 0; i < DEVICE_NAME.length; i++) {
|
for (int i = 0; i < DEVICE_NAME.length; i++) {
|
||||||
if (DEVICE_NAME[i].equals(deviceName)) {
|
if (DEVICE_NAME[i].equals(deviceName)) {
|
||||||
@@ -225,6 +257,7 @@ public class RoomController {
|
|||||||
//关闭单独设备
|
//关闭单独设备
|
||||||
MyInfraredUtils.getInstances().setPowerSupply(false);
|
MyInfraredUtils.getInstances().setPowerSupply(false);
|
||||||
RoomController.floor.setPowerSupply(false);
|
RoomController.floor.setPowerSupply(false);
|
||||||
|
RoomController.dehumidifier485.setPowerSupply(false);
|
||||||
//关闭继电器下的所有设备
|
//关闭继电器下的所有设备
|
||||||
List<Relay> devices = getAllAvailableRelays();
|
List<Relay> devices = getAllAvailableRelays();
|
||||||
//除了空调物理电源
|
//除了空调物理电源
|
||||||
@@ -309,6 +342,7 @@ public class RoomController {
|
|||||||
List<Relay> relays = RoomController.getAllAvailableRelays();
|
List<Relay> relays = RoomController.getAllAvailableRelays();
|
||||||
MyInfraredUtils.getInstances().setPowerSupply(false);
|
MyInfraredUtils.getInstances().setPowerSupply(false);
|
||||||
RoomController.dehumidifier.setPowerSupply(false);
|
RoomController.dehumidifier.setPowerSupply(false);
|
||||||
|
RoomController.dehumidifier485.setPowerSupply(false);
|
||||||
RoomController.floor.setPowerSupply(false);
|
RoomController.floor.setPowerSupply(false);
|
||||||
relays.remove(RoomController.airCondition);
|
relays.remove(RoomController.airCondition);
|
||||||
relays.remove(RoomController.dehumidifier);
|
relays.remove(RoomController.dehumidifier);
|
||||||
|
|||||||
@@ -0,0 +1,463 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/transparent">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="560dp"
|
||||||
|
android:layout_height="690dp"
|
||||||
|
android:layout_margin="80dp"
|
||||||
|
app:cardCornerRadius="10dp"
|
||||||
|
app:cardElevation="40dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.3">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/ll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/layout_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_dialog_close"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="30dp"
|
||||||
|
android:src="@mipmap/cancel"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:background="#00A1FF"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:layout_marginEnd="90dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="485除湿机控制"
|
||||||
|
android:textColor="#38ADFF"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_status"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="170dp"
|
||||||
|
android:layout_marginTop="95dp"
|
||||||
|
app:cardCornerRadius="20dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#F2F0F1">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_target_humidity"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="60"
|
||||||
|
android:textSize="86sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.35"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="%"
|
||||||
|
android:textSize="24sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/tv_target_humidity"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/tv_target_humidity" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_environment_humidity"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="26dp"
|
||||||
|
android:text="环境湿度:--"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/tv_environment_temperature"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_environment_temperature"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="26dp"
|
||||||
|
android:text="环境温度:--"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/tv_work_status"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_work_status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="26dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:text="状态:待机"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/tv_fault"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_fault"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="250dp"
|
||||||
|
android:layout_marginEnd="26dp"
|
||||||
|
android:layout_marginBottom="18dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="故障:正常"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/cl_dehumidifier_control"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="106dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/card_status"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/card_status"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/card_status">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_power"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
app:cardCornerRadius="45dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btn_power"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="18dp"
|
||||||
|
android:src="@mipmap/open" />
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_mode"
|
||||||
|
android:layout_width="330dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
app:cardCornerRadius="45dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/mode_dehumidify"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="18dp"
|
||||||
|
android:src="@mipmap/hum_open" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/mode_ventilation"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="18dp"
|
||||||
|
android:src="@mipmap/ven_open" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sel_dehumidify"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@mipmap/sel_cold" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sel_ventilation"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@mipmap/sel_auto" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_mode_labels"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/cl_dehumidifier_control"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/cl_dehumidifier_control"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/cl_dehumidifier_control">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开关"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="除湿"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="通风"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_fan"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginTop="25dp"
|
||||||
|
app:cardCornerRadius="40dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/card_status"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/card_status"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/ll_mode_labels">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/fan_low"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="24dp"
|
||||||
|
android:src="@mipmap/ven_open" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/fan_middle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:src="@mipmap/ven_open" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/fan_high"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:src="@mipmap/ven_open" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sel_fan_low"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@mipmap/sel_auto" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sel_fan_middle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@mipmap/sel_auto" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sel_fan_high"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@mipmap/sel_auto" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_fan_labels"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/card_fan"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/card_fan"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/card_fan">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="低风"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="中风"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="高风"
|
||||||
|
android:textSize="22sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/card_humidity"
|
||||||
|
android:layout_width="450dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginTop="25dp"
|
||||||
|
app:cardCornerRadius="40dp"
|
||||||
|
app:cardElevation="10dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/card_status"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/card_status"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/ll_fan_labels">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btn_humidity_reduce"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:src="@mipmap/minus"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="目标湿度"
|
||||||
|
android:textSize="24sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btn_humidity_plus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:src="@mipmap/add"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
Reference in New Issue
Block a user