diff --git a/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/BuildingDashboardActivity.java b/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/BuildingDashboardActivity.java index 6958a05..42a82a2 100644 --- a/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/BuildingDashboardActivity.java +++ b/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/BuildingDashboardActivity.java @@ -1,13 +1,10 @@ package cn.ykbox.dashboard.activity; -import android.app.AlarmManager; -import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -28,15 +25,9 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.preference.PreferenceManager; -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.Calendar; - -import cn.ykbox.dashboard.ConfigReader; +import cn.ykbox.dashboard.alarm.PowerAlarmManager; import cn.ykbox.dashboard.databinding.ActivityBuildingDashboardBinding; import cn.ykbox.dashboard.perferences.PreferenceConfiguration; -import cn.ykbox.dashboard.receiver.CommandBroadcastReceiver; import cn.ykbox.dashboard.serial.SerialPortDetector; public class BuildingDashboardActivity extends FullscreenActivity { @@ -44,22 +35,16 @@ public class BuildingDashboardActivity extends FullscreenActivity { private static final boolean AUTO_HIDE = true; private static final int AUTO_HIDE_DELAY_MILLIS = 3000; - private static final long CONFIG_LOAD_INTERVAL = 10 * 60 * 1000; // 10 minutes - private static final int MAX_COMMAND_ALARMS = 20; // 支持的最大闹钟指令数量 private Context mContext; private String mainUrl; private int retryCount = 0; private static final int MAX_RETRY = 99; // 最大重试次数 private static final int RETRY_DELAY = 60000; // 1分钟 = 60000毫秒 - private String configUrl; - private ConfigReader configReader; - private String lastAppliedSerialConfig = null; + private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener; - // --- Periodic Config Loading --- - private final Handler configLoadHandler = new Handler(Looper.getMainLooper()); - private Runnable configLoadRunnable; + private PowerAlarmManager powerAlarmManager; private ActivityBuildingDashboardBinding binding; private ActivityResultLauncher settingsLauncher; @@ -95,7 +80,17 @@ public class BuildingDashboardActivity extends FullscreenActivity { initSettingsLauncher(); initListener(); initWebView(); - initConfigLoader(); + + // 获取配置 URL + SharedPreferences pre = PreferenceManager.getDefaultSharedPreferences(this); + String urlPrefix = pre.getString("k_url_prefix", "http://172.18.22.211:8002/Dashboard"); + String configUrl = urlPrefix + "/data/config.json"; + + // 初始化 PowerAlarmManager + powerAlarmManager = new PowerAlarmManager(this, configUrl); + powerAlarmManager.start(); + + initPreferenceChangeListener(); } @Override @@ -105,14 +100,9 @@ public class BuildingDashboardActivity extends FullscreenActivity { SharedPreferences pre = PreferenceManager.getDefaultSharedPreferences(this); String urlPrefix = pre.getString("k_url_prefix", "http://172.18.22.211:8002/Dashboard"); String urlPath = pre.getString("k_url_path", "/index.html"); - mainUrl = urlPrefix + urlPath; - configUrl = urlPrefix + "/data/config.json"; Log.i(TAG, "Main: " + mainUrl); - Log.i(TAG, "Config: " + configUrl); - - configLoadHandler.post(configLoadRunnable); loadUrlWithRetry(); } @@ -236,7 +226,7 @@ public class BuildingDashboardActivity extends FullscreenActivity { Log.d("WebView", "加载失败,将在1分钟后重试 (第" + retryCount + "次重试)"); // 使用Handler延迟执行重试 - configLoadHandler.postDelayed(new Runnable() { + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { Log.d("WebView", "开始重试加载..."); @@ -254,14 +244,18 @@ public class BuildingDashboardActivity extends FullscreenActivity { @Override protected void onPause() { super.onPause(); - configLoadHandler.removeCallbacks(configLoadRunnable); + // PowerAlarmManager 内部已处理配置加载的暂停 } @Override protected void onDestroy() { super.onDestroy(); - if (configReader != null) { - configReader.release(); + if (preferenceChangeListener != null) { + PreferenceManager.getDefaultSharedPreferences(this) + .unregisterOnSharedPreferenceChangeListener(preferenceChangeListener); + } + if (powerAlarmManager != null) { + powerAlarmManager.stop(); } } @@ -349,109 +343,25 @@ public class BuildingDashboardActivity extends FullscreenActivity { }); } - private void initConfigLoader() { - configLoadRunnable = new Runnable() { - @Override - public void run() { - if (!TextUtils.isEmpty(configUrl)) { - Log.d(TAG, "Periodically loading config..."); - if (configReader != null) { - configReader.loadConfig(configUrl); + private void initPreferenceChangeListener() { + preferenceChangeListener = (sharedPreferences, key) -> { + if (key.equals("k_power_control_mode") || + key.equals("k_power_on_time") || + key.equals("k_power_off_time")) { + Log.d(TAG, "Power control preference changed: " + key); + runOnUiThread(() -> { + if (key.equals("k_power_control_mode")) { + int mode = PreferenceConfiguration.getPowerControlMode(BuildingDashboardActivity.this); + powerAlarmManager.onModeChanged(mode); + } else { + // 本地时间变更 + powerAlarmManager.onLocalTimeChanged(); } - } else { - Log.e(TAG, "configUrl is empty, skipping config load."); - } - configLoadHandler.postDelayed(this, CONFIG_LOAD_INTERVAL); + }); } }; - - if (configReader == null) { - configReader = new ConfigReader(this); - configReader.setOnConfigLoadListener(new ConfigReader.OnConfigLoadListener() { - @Override - public void onConfigLoaded() { - Log.i(TAG, "Config loaded successfully. Refreshing alarms."); - String serialConfig = configReader.getSavedSerialConfig(); - refreshAlarms(serialConfig); - } - - @Override - public void onConfigLoadFailed(String error) { - Log.e(TAG, "Config load failed: " + error + ". Refreshing alarms with local config."); - String serialConfig = configReader.getSavedSerialConfig(); - refreshAlarms(serialConfig); - } - }); - } - } - - private void refreshAlarms(String serialConfigJson) { - if (serialConfigJson != null && serialConfigJson.equals(lastAppliedSerialConfig)) { - Log.d(TAG, "Serial config has not changed. Skipping alarm refresh."); - return; - } - - AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - - for (int i = 0; i < MAX_COMMAND_ALARMS; i++) { - Intent intent = new Intent(this, CommandBroadcastReceiver.class); - intent.setAction(CommandBroadcastReceiver.ACTION_SEND_COMMAND); - PendingIntent pendingIntent = PendingIntent.getBroadcast(this, i, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE); - if (pendingIntent != null) { - alarmManager.cancel(pendingIntent); - pendingIntent.cancel(); - } - } - - try { - JSONObject serialConfig = new JSONObject(serialConfigJson); - - if (serialConfig.has("Commands")) { - JSONArray commands = serialConfig.getJSONArray("Commands"); - for (int i = 0; i < commands.length() && i < MAX_COMMAND_ALARMS; i++) { - JSONObject command = commands.getJSONObject(i); - String time = command.getString("Time"); - String hex = command.getString("Hex"); - - String[] timeParts = time.split(":"); - int hour = Integer.parseInt(timeParts[0]); - int minute = Integer.parseInt(timeParts[1]); - - Intent intent = new Intent(this, CommandBroadcastReceiver.class); - intent.setAction(CommandBroadcastReceiver.ACTION_SEND_COMMAND); - intent.putExtra(CommandBroadcastReceiver.EXTRA_COMMAND_HEX, hex); - - PendingIntent pendingIntent = PendingIntent.getBroadcast(this, i, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.HOUR_OF_DAY, hour); - calendar.set(Calendar.MINUTE, minute); - calendar.set(Calendar.SECOND, 0); - - if (calendar.getTimeInMillis() <= System.currentTimeMillis()) { - calendar.add(Calendar.DAY_OF_YEAR, 1); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); - Log.d(TAG, "setExactAndAllowWhileIdle, Set repeating alarm for " + time + " with command " + hex); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); - Log.d(TAG, "setExact, Set repeating alarm for " + time + " with command " + hex); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); - Log.d(TAG, "Set repeating alarm for " + time + " with command " + hex); - } - } - } - - this.lastAppliedSerialConfig = serialConfigJson; - Log.d(TAG, "Alarms refreshed and config backed up."); - - } catch (Exception e) { - Log.e(TAG, "Failed to parse or schedule commands", e); - } + PreferenceManager.getDefaultSharedPreferences(this) + .registerOnSharedPreferenceChangeListener(preferenceChangeListener); } private void openSettingsActivity() { @@ -464,4 +374,4 @@ public class BuildingDashboardActivity extends FullscreenActivity { message, Toast.LENGTH_SHORT).show()); } -} +} \ No newline at end of file diff --git a/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/SettingsActivity.java b/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/SettingsActivity.java index 563e20c..7c78f34 100644 --- a/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/SettingsActivity.java +++ b/app_dashboard/src/main/java/cn/ykbox/dashboard/activity/SettingsActivity.java @@ -8,6 +8,7 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.preference.EditTextPreference; +import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; @@ -41,6 +42,10 @@ public class SettingsActivity extends AppCompatActivity { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.root_preferences, rootKey); + ListPreference powerControlModePref = findPreference("k_power_control_mode"); + EditTextPreference powerOnTimePref = findPreference("k_power_on_time"); + EditTextPreference powerOffTimePref = findPreference("k_power_off_time"); + Preference clearDevicePref = findPreference("k_clear_device"); if (clearDevicePref != null) { clearDevicePref.setOnPreferenceClickListener(this); @@ -55,6 +60,29 @@ public class SettingsActivity extends AppCompatActivity { if (testPowerOffPref != null) { testPowerOffPref.setOnPreferenceClickListener(this); } + + if (powerControlModePref != null) { + powerControlModePref.setOnPreferenceChangeListener((preference, newValue) -> { + int mode = Integer.parseInt((String) newValue); + boolean isLocalMode = (mode == 2); + if (powerOnTimePref != null) { + powerOnTimePref.setEnabled(isLocalMode); + } + if (powerOffTimePref != null) { + powerOffTimePref.setEnabled(isLocalMode); + } + return true; + }); + } + + int mode = PreferenceConfiguration.getPowerControlMode(getContext()); + boolean isLocalMode = (mode == 2); + if (powerOnTimePref != null) { + powerOnTimePref.setEnabled(isLocalMode); + } + if (powerOffTimePref != null) { + powerOffTimePref.setEnabled(isLocalMode); + } } @Override diff --git a/app_dashboard/src/main/java/cn/ykbox/dashboard/alarm/PowerAlarmManager.java b/app_dashboard/src/main/java/cn/ykbox/dashboard/alarm/PowerAlarmManager.java new file mode 100644 index 0000000..50dd8aa --- /dev/null +++ b/app_dashboard/src/main/java/cn/ykbox/dashboard/alarm/PowerAlarmManager.java @@ -0,0 +1,357 @@ +package cn.ykbox.dashboard.alarm; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.Calendar; + +import cn.ykbox.dashboard.ConfigReader; +import cn.ykbox.dashboard.perferences.PreferenceConfiguration; +import cn.ykbox.dashboard.receiver.CommandBroadcastReceiver; +import cn.ykbox.dashboard.serial.SerialPortDetector; + +public class PowerAlarmManager { + private static final String TAG = "PowerAlarmManager"; + private static final int MAX_COMMAND_ALARMS = 20; + private static final int ALARM_ID_POWER_ON = 0; + private static final int ALARM_ID_POWER_OFF = 1; + private static final long CONFIG_LOAD_INTERVAL = 10 * 60 * 1000; // 10 minutes + + private static final int POWER_MODE_NONE = 0; + private static final int POWER_MODE_REMOTE = 1; + private static final int POWER_MODE_LOCAL = 2; + + private final Context context; + private String lastAppliedSerialConfig = null; + private ConfigReader configReader; + private String configUrl; + private Handler configLoadHandler; + private Runnable configLoadRunnable; + + public PowerAlarmManager(Context context, String configUrl) { + this.context = context.getApplicationContext(); + this.configUrl = configUrl; + this.configLoadHandler = new Handler(Looper.getMainLooper()); + } + + /** + * 启动管理器,根据当前模式初始化 + */ + public void start() { + int mode = PreferenceConfiguration.getPowerControlMode(context); + Log.d(TAG, "PowerAlarmManager starting, mode: " + mode); + + refreshAlarms(); + + if (mode == POWER_MODE_REMOTE) { + // 服务器配置模式,初始化 ConfigLoader + initConfigLoader(); + } + } + + /** + * 停止管理器,释放资源 + */ + public void stop() { + if (configLoadRunnable != null) { + configLoadHandler.removeCallbacks(configLoadRunnable); + } + if (configReader != null) { + configReader.release(); + configReader = null; + } + } + + /** + * 模式变更时调用 + */ + public void onModeChanged(int newMode) { + Log.d(TAG, "Mode changed to: " + newMode); + + if (newMode == POWER_MODE_REMOTE) { + // 切换到服务器配置模式 + if (configReader == null) { + initConfigLoader(); + } + clearServerConfigCache(); + if (configLoadRunnable != null) { + configLoadHandler.post(configLoadRunnable); + } + } else { + // 切换到其他模式,停止配置加载 + if (configLoadRunnable != null) { + configLoadHandler.removeCallbacks(configLoadRunnable); + } + } + + refreshAlarms(); + } + + /** + * 本地时间变更时调用 + */ + public void onLocalTimeChanged() { + int mode = PreferenceConfiguration.getPowerControlMode(context); + if (mode == POWER_MODE_LOCAL) { + // 本地控制模式,刷新闹钟 + refreshAlarms(); + } + } + + /** + * 根据当前模式刷新闹钟 + */ + public void refreshAlarms() { + int mode = PreferenceConfiguration.getPowerControlMode(context); + Log.d(TAG, "Refreshing alarms, mode: " + mode); + + cancelAllAlarms(); + + switch (mode) { + case POWER_MODE_NONE: // 不控制 + Log.d(TAG, "Power control: No control mode. No alarms set."); + break; + + case POWER_MODE_REMOTE: // 根据服务器配置 + Log.d(TAG, "Power control: Server config mode."); + // 使用已加载的配置或请求立即加载 + if (configReader != null) { + String serialConfig = configReader.getSavedSerialConfig(); + refreshWithServerConfig(serialConfig, false); + } + break; + + case POWER_MODE_LOCAL: // 本地控制 + Log.d(TAG, "Power control: Local control mode."); + setupLocalControlAlarms(); + break; + + default: + Log.w(TAG, "Unknown power control mode: " + mode); + break; + } + } + + /** + * 使用服务器配置刷新闹钟 + * @param serialConfigJson 服务器配置 JSON + * @param forceRefresh 是否强制刷新(模式切换时为 true) + */ + private void refreshWithServerConfig(String serialConfigJson, boolean forceRefresh) { + cancelAllAlarms(); + + if (serialConfigJson == null) { + Log.w(TAG, "Server config is null."); + return; + } + + if (!forceRefresh && serialConfigJson.equals(lastAppliedSerialConfig)) { + Log.d(TAG, "Server config has not changed. Skipping alarm refresh."); + return; + } + + setupServerConfigAlarms(serialConfigJson); + this.lastAppliedSerialConfig = serialConfigJson; + } + + /** + * 取消所有闹钟 + */ + private void cancelAllAlarms() { + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + for (int i = 0; i < MAX_COMMAND_ALARMS; i++) { + Intent intent = new Intent(context, CommandBroadcastReceiver.class); + intent.setAction(CommandBroadcastReceiver.ACTION_SEND_COMMAND); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + context, i, intent, + PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE + ); + if (pendingIntent != null) { + alarmManager.cancel(pendingIntent); + pendingIntent.cancel(); + } + } + } + + /** + * 设置服务器配置的闹钟 + */ + private void setupServerConfigAlarms(String serialConfigJson) { + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + + try { + JSONObject serialConfig = new JSONObject(serialConfigJson); + + if (serialConfig.has("Commands")) { + JSONArray commands = serialConfig.getJSONArray("Commands"); + for (int i = 0; i < commands.length() && i < MAX_COMMAND_ALARMS; i++) { + JSONObject command = commands.getJSONObject(i); + String time = command.getString("Time"); + String hex = command.getString("Hex"); + + String[] timeParts = time.split(":"); + int hour = Integer.parseInt(timeParts[0]); + int minute = Integer.parseInt(timeParts[1]); + + setupAlarm(alarmManager, i, time, hex, hour, minute); + } + } + Log.d(TAG, "Server config alarms set successfully."); + + } catch (Exception e) { + Log.e(TAG, "Failed to parse server config", e); + } + } + + /** + * 设置本地控制的闹钟 + */ + private void setupLocalControlAlarms() { + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + String onTime = PreferenceConfiguration.getPowerOnTime(context); + String offTime = PreferenceConfiguration.getPowerOffTime(context); + + int[] onParts = parseTimeParts(onTime); + int[] offParts = parseTimeParts(offTime); + + if (onParts != null) { + setupAlarm(alarmManager, ALARM_ID_POWER_ON, onTime, + SerialPortDetector.TEST_CMD_ON, + onParts[0], onParts[1]); + } else { + Log.w(TAG, "Invalid power-on time, alarm skipped: " + onTime); + } + + if (offParts != null) { + setupAlarm(alarmManager, ALARM_ID_POWER_OFF, offTime, + SerialPortDetector.TEST_CMD_OFF, + offParts[0], offParts[1]); + } else { + Log.w(TAG, "Invalid power-off time, alarm skipped: " + offTime); + } + + Log.d(TAG, "Local control alarms set: ON=" + onTime + ", OFF=" + offTime); + } + + /** + * 解析 "HH:mm" 格式时间字符串 + * @return int[]{hour, minute},解析失败返回 null + */ + private int[] parseTimeParts(String time) { + if (time == null || time.trim().isEmpty()) { + return null; + } + String[] parts = time.split(":"); + if (parts.length < 2) { + return null; + } + try { + int hour = Integer.parseInt(parts[0].trim()); + int minute = Integer.parseInt(parts[1].trim()); + if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { + return null; + } + return new int[]{hour, minute}; + } catch (NumberFormatException e) { + Log.e(TAG, "Failed to parse time: " + time, e); + return null; + } + } + + /** + * 设置单个闹钟 + */ + private void setupAlarm(AlarmManager alarmManager, int alarmId, String timeStr, + String cmdHex, int hour, int minute) { + Intent intent = new Intent(context, CommandBroadcastReceiver.class); + intent.setAction(CommandBroadcastReceiver.ACTION_SEND_COMMAND); + intent.putExtra(CommandBroadcastReceiver.EXTRA_COMMAND_HEX, cmdHex); + + PendingIntent pendingIntent = PendingIntent.getBroadcast( + context, alarmId, intent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE + ); + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + calendar.set(Calendar.SECOND, 0); + + if (calendar.getTimeInMillis() <= System.currentTimeMillis()) { + calendar.add(Calendar.DAY_OF_YEAR, 1); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + alarmManager.setExactAndAllowWhileIdle( + AlarmManager.RTC_WAKEUP, + calendar.getTimeInMillis(), pendingIntent); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + alarmManager.setExact( + AlarmManager.RTC_WAKEUP, + calendar.getTimeInMillis(), pendingIntent); + } else { + alarmManager.set( + AlarmManager.RTC_WAKEUP, + calendar.getTimeInMillis(), pendingIntent); + } + Log.d(TAG, "Alarm set: " + timeStr + " with command " + cmdHex); + } + + /** + * 初始化 ConfigLoader + */ + private void initConfigLoader() { + if (configReader != null) { + return; // 已初始化 + } + + configLoadRunnable = new Runnable() { + @Override + public void run() { + if (!TextUtils.isEmpty(configUrl)) { + Log.d(TAG, "Periodically loading config..."); + configReader.loadConfig(configUrl); + } else { + Log.e(TAG, "configUrl is empty, skipping config load."); + } + configLoadHandler.postDelayed(this, CONFIG_LOAD_INTERVAL); + } + }; + + configReader = new ConfigReader(context); + configReader.setOnConfigLoadListener(new ConfigReader.OnConfigLoadListener() { + @Override + public void onConfigLoaded() { + Log.i(TAG, "Config loaded successfully. Refreshing alarms."); + String serialConfig = configReader.getSavedSerialConfig(); + refreshWithServerConfig(serialConfig, false); + } + + @Override + public void onConfigLoadFailed(String error) { + Log.e(TAG, "Config load failed: " + error); + } + }); + + // 立即执行一次 + configLoadRunnable.run(); + } + + /** + * 清除缓存的服务器配置 + */ + private void clearServerConfigCache() { + this.lastAppliedSerialConfig = null; + } +} diff --git a/app_dashboard/src/main/java/cn/ykbox/dashboard/perferences/PreferenceConfiguration.java b/app_dashboard/src/main/java/cn/ykbox/dashboard/perferences/PreferenceConfiguration.java index ebc1314..e6b7884 100644 --- a/app_dashboard/src/main/java/cn/ykbox/dashboard/perferences/PreferenceConfiguration.java +++ b/app_dashboard/src/main/java/cn/ykbox/dashboard/perferences/PreferenceConfiguration.java @@ -14,6 +14,9 @@ public class PreferenceConfiguration { private static final String KEY_SERIAL_PORT_PATH = "k_serial_port_path"; private static final String KEY_SERIAL_PORT_BAUD_RATE = "k_serial_baud"; private static final String KEY_SEND_POWER_ON_CMD = "k_send_power_on_cmd"; + private static final String KEY_POWER_CONTROL_MODE = "k_power_control_mode"; + private static final String KEY_POWER_ON_TIME = "k_power_on_time"; + private static final String KEY_POWER_OFF_TIME = "k_power_off_time"; public static String getSerialPortPath(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -39,4 +42,20 @@ public class PreferenceConfiguration { public static int getSerialCmdLoop(Context context) { return 3; } + + public static int getPowerControlMode(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String mode = prefs.getString(KEY_POWER_CONTROL_MODE, "1"); + return Integer.parseInt(mode); + } + + public static String getPowerOnTime(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getString(KEY_POWER_ON_TIME, "07:30"); + } + + public static String getPowerOffTime(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getString(KEY_POWER_OFF_TIME, "20:30"); + } } diff --git a/app_dashboard/src/main/java/cn/ykbox/dashboard/serial/SerialPortDetector.java b/app_dashboard/src/main/java/cn/ykbox/dashboard/serial/SerialPortDetector.java index 692dfa5..6d7ea35 100644 --- a/app_dashboard/src/main/java/cn/ykbox/dashboard/serial/SerialPortDetector.java +++ b/app_dashboard/src/main/java/cn/ykbox/dashboard/serial/SerialPortDetector.java @@ -16,8 +16,8 @@ import tp.xmaihh.serialport.bean.ComBean; public class SerialPortDetector { private static final String TAG = "SerialPortDetector"; // 测试命令 - private static final String TEST_CMD_OFF = "ACEAB500ED"; // 关闭设备 - private static final String TEST_CMD_ON = "ACEAB400ED"; // 打开设备 + public static final String TEST_CMD_OFF = "ACEAB500ED"; // 关闭设备 + public static final String TEST_CMD_ON = "ACEAB400ED"; // 打开设备 // 响应超时时间(毫秒) private static final long RESPONSE_TIMEOUT = 4000; @@ -59,11 +59,11 @@ public class SerialPortDetector { try { serialHelper.open(); - for(int i = 0; i < loop; i ++) { + for(int i = 0; i < loop; i++) { serialHelper.sendHex(hexCommand); + Log.d(TAG, "Successfully sent command '" + hexCommand + "' to port '" + portPath + "'"); Thread.sleep(1000); } - Log.d(TAG, "Successfully sent command '" + hexCommand + "' to port '" + portPath + "'"); return true; } catch (Exception e) { Log.e(TAG, "Error sending command to port " + portPath, e); @@ -118,10 +118,9 @@ public class SerialPortDetector { for(int i = 0; i < loop; i ++) { serialHelper.sendHex(commandHex); + Log.d(TAG, "Sent command: " + commandHex); Thread.sleep(1000); } - - Log.d(TAG, "Sent command: " + commandHex); } catch (Exception e) { Log.e(TAG, "Error sending command: " + e.getMessage()); } finally { diff --git a/app_dashboard/src/main/res/values/strings.xml b/app_dashboard/src/main/res/values/strings.xml index 7e74272..9540e00 100644 --- a/app_dashboard/src/main/res/values/strings.xml +++ b/app_dashboard/src/main/res/values/strings.xml @@ -3,4 +3,15 @@ Building Dashboard Settings / + + + 不控制 + 根据服务器配置 + 本地控制 + + + 0 + 1 + 2 + \ No newline at end of file diff --git a/app_dashboard/src/main/res/xml/root_preferences.xml b/app_dashboard/src/main/res/xml/root_preferences.xml index 38e4305..32ee38e 100644 --- a/app_dashboard/src/main/res/xml/root_preferences.xml +++ b/app_dashboard/src/main/res/xml/root_preferences.xml @@ -29,6 +29,25 @@ app:title="APP 启动时重启电源插座" app:summary="APP 启动时先关闭电源,5秒后再打开电源" app:defaultValue="true" /> + + +