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资源已释放"); } }