You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
16 KiB
470 lines
16 KiB
package com.ouxuan.oxface.device;
|
|
|
|
import android.content.Context;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.util.Log;
|
|
|
|
import com.ouxuan.oxface.utils.LogManager;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.FileOutputStream;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* 继电器控制器
|
|
* 基于GPIO控制继电器的开关操作
|
|
*
|
|
* @author AI Assistant
|
|
* @version 1.0
|
|
* @date 2024/09/11
|
|
*/
|
|
public class RelayController {
|
|
|
|
private static final String TAG = "RelayController";
|
|
|
|
// 第6批设备-默认GPIO路径
|
|
private static final String PWM_FLASH_OUT = "/sys/class/gpio/gpio114/direction";
|
|
private static final String PWM_FLASH = "/sys/class/gpio/gpio114/value";
|
|
|
|
// 第2批设备GPIO路径
|
|
// private static final String PWM_FLASH_OUT_2 = "/sys/class/gpio/gpio123/direction";
|
|
// private static final String PWM_FLASH_2 = "/sys/class/gpio/gpio123/value";
|
|
|
|
private static final String PWM_FLASH_OUT_2 = "/sys/class/gpio/gpio154/direction";
|
|
private static final String PWM_FLASH_2 = "/sys/class/gpio/gpio154/value";
|
|
|
|
// 第7批设备GPIO路径
|
|
private static final String PWM_FLASH_OUT_7 = "/sys/class/gpio/gpio88/direction";
|
|
private static final String PWM_FLASH_7 = "/sys/class/gpio/gpio88/value";
|
|
|
|
// GPIO操作命令
|
|
private static final byte[] OPEN_RELAY = {'1'};
|
|
private static final byte[] CLOSE_RELAY = {'0'};
|
|
private static final byte[] GPIO_OUT = {'o', 'u', 't'};
|
|
private static final byte[] GPIO_IN = {'i', 'n'};
|
|
|
|
// 设备类型
|
|
public static final String PAD_TYPE_DEFAULT = "pad_default";
|
|
public static final String PAD_TYPE_TWO = "pad_two";
|
|
public static final String PAD_TYPE_SEVEN = "pad_seven";
|
|
|
|
// 单例实例
|
|
private static volatile RelayController instance;
|
|
|
|
// Handler用于延时操作
|
|
private Handler handler;
|
|
|
|
// 第七批设备管理器
|
|
private DeviceType7Manager deviceType7Manager;
|
|
|
|
// 当前设备类型(5=第6批,6=第7批等)
|
|
private int deviceType = -1;
|
|
|
|
private RelayController() {
|
|
handler = new Handler(Looper.getMainLooper());
|
|
}
|
|
|
|
/**
|
|
* 初始化第七批设备管理器
|
|
* @param context Android上下文
|
|
* @return 是否初始化成功
|
|
*/
|
|
public boolean initDeviceType7Manager(Context context) {
|
|
deviceType7Manager = DeviceType7Manager.getInstance();
|
|
boolean success = deviceType7Manager.init(context);
|
|
if (success) {
|
|
LogManager.logInfo(TAG, "第七批设备管理器初始化成功");
|
|
} else {
|
|
LogManager.logError(TAG, "第七批设备管理器初始化失败");
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/**
|
|
* 根据设备类型获取GPIO值文件路径
|
|
* @param deviceType 设备类型(5=第6批,6=第7批等)
|
|
* @return GPIO值文件路径
|
|
*/
|
|
private String getGpioValuePath(int deviceType) {
|
|
switch (deviceType) {
|
|
case 5: // 第6批设备
|
|
return PWM_FLASH;
|
|
case 6: // 第7批设备
|
|
return PWM_FLASH_7;
|
|
case 2: // 第2批设备(兼容旧逻辑)
|
|
return PWM_FLASH_2;
|
|
default: // 默认使用第6批设备路径
|
|
return PWM_FLASH;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 根据设备类型获取GPIO方向文件路径
|
|
* @param deviceType 设备类型(5=第6批,6=第7批等)
|
|
* @return GPIO方向文件路径
|
|
*/
|
|
private String getGpioDirectionPath(int deviceType) {
|
|
switch (deviceType) {
|
|
case 5: // 第6批设备
|
|
return PWM_FLASH_OUT;
|
|
case 6: // 第7批设备
|
|
return PWM_FLASH_OUT_7;
|
|
case 2: // 第2批设备(兼容旧逻辑)
|
|
return PWM_FLASH_OUT_2;
|
|
default: // 默认使用第6批设备路径
|
|
return PWM_FLASH_OUT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取当前设备类型(兼容性方法,返回字符串类型)
|
|
* @return 设备类型字符串
|
|
*/
|
|
private String getCurrentPadType() {
|
|
// 根据设备类型返回对应的padType
|
|
if (deviceType == 6) {
|
|
return PAD_TYPE_SEVEN; // deviceType=6表示第7批设备,使用DeviceType7Manager
|
|
} else if (deviceType == 5) {
|
|
return PAD_TYPE_TWO; // deviceType=5表示第6批设备,使用第2批的GPIO路径
|
|
} else {
|
|
// 其他情况返回默认
|
|
return PAD_TYPE_DEFAULT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取RelayController单例实例
|
|
* @return RelayController实例
|
|
*/
|
|
public static RelayController getInstance() {
|
|
if (instance == null) {
|
|
synchronized (RelayController.class) {
|
|
if (instance == null) {
|
|
instance = new RelayController();
|
|
}
|
|
}
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* 设置设备类型
|
|
* @param deviceType 设备类型(5=第6批,6=第7批等)
|
|
*/
|
|
public void setDeviceType(int deviceType) {
|
|
this.deviceType = deviceType;
|
|
LogManager.logInfo(TAG, "设置设备类型: " + deviceType);
|
|
}
|
|
|
|
/**
|
|
* 设置GPIO方向为输出模式
|
|
* @param padType 设备类型(保留兼容性)
|
|
*/
|
|
private void setGpioDirection(String padType) {
|
|
if (PAD_TYPE_SEVEN.equals(padType) && deviceType7Manager != null) {
|
|
// 第七批设备使用DeviceType7Manager
|
|
deviceType7Manager.setGpioDirection(DeviceType7Manager.YxGpioConstants.GPIO_RELAY,
|
|
DeviceType7Manager.YxGpioConstants.GPIO_DIRECTION_OUTPUT);
|
|
} else {
|
|
// 其他设备使用文件操作,根据deviceType动态获取路径
|
|
FileOutputStream fos = null;
|
|
try {
|
|
String directionPath = getGpioDirectionPath(deviceType);
|
|
fos = new FileOutputStream(directionPath);
|
|
fos.write(GPIO_OUT);
|
|
LogManager.logInfo(TAG, "GPIO方向设置为输出模式成功, 设备类型: " + deviceType + ", 路径: " + directionPath);
|
|
} catch (Exception e) {
|
|
LogManager.logError(TAG, "设置GPIO方向失败, 设备类型: " + deviceType, e);
|
|
} finally {
|
|
if (fos != null) {
|
|
try {
|
|
fos.close();
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "关闭FileOutputStream失败", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 设置GPIO方向为输入模式
|
|
* @param padType 设备类型(保留兼容性)
|
|
*/
|
|
private void setGpioDirectionInput(String padType) {
|
|
FileOutputStream fos = null;
|
|
try {
|
|
String directionPath = getGpioDirectionPath(deviceType);
|
|
fos = new FileOutputStream(directionPath);
|
|
fos.write(GPIO_IN);
|
|
LogManager.logInfo(TAG, "GPIO方向设置为输入模式成功, 设备类型: " + deviceType + ", 路径: " + directionPath);
|
|
} catch (Exception e) {
|
|
LogManager.logError(TAG, "设置GPIO方向为输入模式失败, 设备类型: " + deviceType, e);
|
|
} finally {
|
|
if (fos != null) {
|
|
try {
|
|
fos.close();
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "关闭FileOutputStream失败", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 读取GPIO值
|
|
* @param padType 设备类型(保留兼容性)
|
|
* @return GPIO值字符串,失败返回null
|
|
*/
|
|
public String readGpioValue(String padType) {
|
|
if (PAD_TYPE_SEVEN.equals(padType) && deviceType7Manager != null) {
|
|
// 第七批设备使用DeviceType7Manager
|
|
int value = deviceType7Manager.getGpioValue(DeviceType7Manager.YxGpioConstants.GPIO_RELAY);
|
|
if (value == -1) {
|
|
LogManager.logError(TAG, "DeviceType7Manager读取GPIO值失败");
|
|
return null;
|
|
} else {
|
|
String strValue = String.valueOf(value);
|
|
LogManager.logInfo(TAG, "DeviceType7Manager读取GPIO值成功: " + strValue);
|
|
return strValue;
|
|
}
|
|
} else {
|
|
// 其他设备使用文件操作,根据deviceType动态获取路径
|
|
BufferedReader reader = null;
|
|
try {
|
|
String valuePath = getGpioValuePath(deviceType);
|
|
reader = new BufferedReader(new FileReader(valuePath));
|
|
String value = reader.readLine();
|
|
LogManager.logInfo(TAG, "读取GPIO值成功: " + value + ", 设备类型: " + deviceType + ", 路径: " + valuePath);
|
|
return value;
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "读取GPIO值失败, 设备类型: " + deviceType, e);
|
|
return null;
|
|
} finally {
|
|
if (reader != null) {
|
|
try {
|
|
reader.close();
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "关闭BufferedReader失败", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 直接写入GPIO值到文件
|
|
* @param value 要写入的值
|
|
* @param valuePath GPIO值文件路径
|
|
* @return 是否成功
|
|
*/
|
|
private boolean writeGpioValueDirect(byte[] value, String valuePath) {
|
|
FileOutputStream fos = null;
|
|
try {
|
|
fos = new FileOutputStream(valuePath);
|
|
fos.write(value);
|
|
LogManager.logInfo(TAG, "GPIO值写入成功: " + valuePath + " -> " + new String(value));
|
|
return true;
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "GPIO值写入失败: " + valuePath + ", 错误: " + e.getMessage(), e);
|
|
return false;
|
|
} finally {
|
|
if (fos != null) {
|
|
try {
|
|
fos.close();
|
|
} catch (IOException e) {
|
|
LogManager.logError(TAG, "关闭FileOutputStream失败", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 写入GPIO值
|
|
* @param value 要写入的值
|
|
* @param padType 设备类型(保留兼容性)
|
|
* @return 是否成功
|
|
*/
|
|
private boolean writeGpioValue(byte[] value, String padType) {
|
|
if (PAD_TYPE_SEVEN.equals(padType) && deviceType7Manager != null) {
|
|
// 第七批设备使用DeviceType7Manager
|
|
int gpioValue = (value[0] == '1') ? DeviceType7Manager.YxGpioConstants.GpioState.HIGH : DeviceType7Manager.YxGpioConstants.GpioState.LOW;
|
|
boolean success = deviceType7Manager.setGpioValue(DeviceType7Manager.YxGpioConstants.GPIO_RELAY, gpioValue);
|
|
if (success) {
|
|
LogManager.logInfo(TAG, "DeviceType7Manager写入GPIO值成功: " + gpioValue);
|
|
} else {
|
|
LogManager.logError(TAG, "DeviceType7Manager写入GPIO值失败");
|
|
}
|
|
return success;
|
|
} else {
|
|
// 其他设备使用文件操作,根据deviceType动态获取路径
|
|
String valuePath = getGpioValuePath(deviceType);
|
|
|
|
// 第一次尝试
|
|
if (writeGpioValueDirect(value, valuePath)) {
|
|
return true;
|
|
}
|
|
|
|
// 如果失败,尝试设置GPIO方向后重试
|
|
LogManager.logWarning(TAG, "GPIO写入失败,尝试设置方向后重试, 设备类型: " + deviceType + ", 路径: " + valuePath);
|
|
setGpioDirection(padType);
|
|
|
|
// 第二次尝试
|
|
return writeGpioValueDirect(value, valuePath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 开启继电器(默认设备)
|
|
* @return 是否成功
|
|
*/
|
|
public boolean openRelay() {
|
|
return openRelay(getCurrentPadType());
|
|
}
|
|
|
|
/**
|
|
* 1. 开启继电器(指定设备类型)
|
|
* @param padType 设备类型
|
|
* @return 是否成功
|
|
*/
|
|
public boolean openRelay(String padType) {
|
|
LogManager.logInfo(TAG, "开启继电器, 设备类型: " + padType);
|
|
boolean success = writeGpioValue(OPEN_RELAY, padType);
|
|
if (success) {
|
|
LogManager.logInfo(TAG, "继电器开启成功");
|
|
} else {
|
|
LogManager.logError(TAG, "继电器开启失败");
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/**
|
|
* 2. 关闭继电器(默认设备)
|
|
* @return 是否成功
|
|
*/
|
|
public boolean closeRelay() {
|
|
return closeRelay(getCurrentPadType());
|
|
}
|
|
|
|
/**
|
|
* 2. 关闭继电器(指定设备类型)
|
|
* @param padType 设备类型
|
|
* @return 是否成功
|
|
*/
|
|
public boolean closeRelay(String padType) {
|
|
LogManager.logInfo(TAG, "关闭继电器, 设备类型: " + padType);
|
|
boolean success = writeGpioValue(CLOSE_RELAY, padType);
|
|
if (success) {
|
|
LogManager.logInfo(TAG, "继电器关闭成功");
|
|
} else {
|
|
LogManager.logError(TAG, "继电器关闭失败");
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/**
|
|
* 3. 开启继电器3秒后自动关闭(默认设备)
|
|
* @return 是否成功开启
|
|
*/
|
|
public boolean openRelayWithAutoClose() {
|
|
return openRelayWithAutoClose(PAD_TYPE_DEFAULT);
|
|
}
|
|
|
|
/**
|
|
* 3. 开启继电器3秒后自动关闭(指定设备类型)
|
|
* @param padType 设备类型
|
|
* @return 是否成功开启
|
|
*/
|
|
public boolean openRelayWithAutoClose(String padType) {
|
|
LogManager.logInfo(TAG, "开启继电器并设置3秒后自动关闭, 设备类型: " + padType);
|
|
|
|
// 先开启继电器
|
|
boolean openSuccess = openRelay(padType);
|
|
if (!openSuccess) {
|
|
LogManager.logError(TAG, "继电器开启失败,取消自动关闭计划");
|
|
return false;
|
|
}
|
|
|
|
// 3秒后自动关闭
|
|
handler.postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
LogManager.logInfo(TAG, "3秒时间到,自动关闭继电器, 设备类型: " + padType);
|
|
closeRelay(padType);
|
|
}
|
|
}, 3000);
|
|
|
|
LogManager.logInfo(TAG, "继电器已开启,3秒后将自动关闭");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 开启继电器指定时间后自动关闭(扩展功能)
|
|
* @param padType 设备类型
|
|
* @param delayMillis 延时时间(毫秒)
|
|
* @return 是否成功开启
|
|
*/
|
|
public boolean openRelayWithAutoClose(String padType, long delayMillis) {
|
|
LogManager.logInfo(TAG, "开启继电器并设置" + delayMillis + "ms后自动关闭, 设备类型: " + padType);
|
|
|
|
// 先开启继电器
|
|
boolean openSuccess = openRelay(padType);
|
|
if (!openSuccess) {
|
|
LogManager.logError(TAG, "继电器开启失败,取消自动关闭计划");
|
|
return false;
|
|
}
|
|
|
|
// 指定时间后自动关闭
|
|
handler.postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
LogManager.logInfo(TAG, delayMillis + "ms时间到,自动关闭继电器, 设备类型: " + padType);
|
|
closeRelay(padType);
|
|
}
|
|
}, delayMillis);
|
|
|
|
LogManager.logInfo(TAG, "继电器已开启," + delayMillis + "ms后将自动关闭");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 获取继电器当前状态
|
|
* @param padType 设备类型
|
|
* @return true为开启状态,false为关闭状态,null为读取失败
|
|
*/
|
|
public Boolean getRelayStatus(String padType) {
|
|
String value = readGpioValue(padType);
|
|
if (value == null) {
|
|
LogManager.logError(TAG, "无法读取继电器状态");
|
|
return null;
|
|
}
|
|
|
|
boolean isOpen = "1".equals(value.trim());
|
|
LogManager.logInfo(TAG, "继电器当前状态: " + (isOpen ? "开启" : "关闭") + ", 设备类型: " + padType);
|
|
return isOpen;
|
|
}
|
|
|
|
/**
|
|
* 获取第七批设备管理器实例
|
|
* @return DeviceType7Manager实例
|
|
*/
|
|
public DeviceType7Manager getDeviceType7Manager() {
|
|
return deviceType7Manager;
|
|
}
|
|
|
|
/**
|
|
* 释放资源
|
|
*/
|
|
public void release() {
|
|
if (handler != null) {
|
|
handler.removeCallbacksAndMessages(null);
|
|
}
|
|
if (deviceType7Manager != null) {
|
|
deviceType7Manager.release();
|
|
deviceType7Manager = null;
|
|
}
|
|
LogManager.logInfo(TAG, "RelayController资源已释放");
|
|
}
|
|
}
|