軟件代碼

如下是美的電飯煲的oh代碼:
// OH code for Midea Rice Cooker// This code requires a pre-configured Thing for basic communication// and provides additional functionality for controlling the cooker
// Channels// Switch state// Percentual Remaining Time// Timer control for Delayed Start// String Recipe Selection// String Recipe Output// Number Cooking Temperature// Profile Power Consumption// Lock
// Auto-generated Device-Specific Importsimport java.util.Map;import java.util.concurrent.TimeUnit;import java.util.regex.Matcher;import java.util.regex.Pattern;
import org.eclipse.jdt.annotation.NonNullByDefault;import org.eclipse.smarthome.core.library.types.*;import org.eclipse.smarthome.core.thing.*;import org.eclipse.smarthome.core.thing.binding.*;import org.eclipse.smarthome.core.types.*;import org.eclipse.xtext.xbase.lib.Functions.Function1;import org.slf4j.Logger;import org.slf4j.LoggerFactory;
@NonNullByDefaultpublic class MideaRiceCookerDevice extends BaseThingHandler {
// Constants//private static final Logger logger = LoggerFactory.getLogger(MideaRiceCookerDevice.class);
private static final String SWITCH_STATE = "switch_state";private static final String REMAINING_TIME_PERCENT = "remaining_time_percent";private static final String DELAYED_START_TIMER = "delayed_start";private static final String RECIPE_SELECTION = "recipe_selection";private static final String RECIPE_OUTPUT = "recipe_output";private static final String COOKING_TEMPERATURE = "cooking_temperature";private static final String PROFILE_POWER_CONSUMPTION = "power_consumption";private static final String LOCK_STATE = "lock";
private static final String HEX_PREFIX = "0x";
private static final int[] baseProfile = {400, 1200, 1800, 2200, 2450}; // 5 levels of power consumption profile
// Variables//private ThingConfig thingConfig;private MideaCommunicationService communicationService;private Boolean switchState = false;private Integer remainingTimePercent = 0;private Integer delayedStartMinutes = 0;private String recipeSelection = "";private String recipeOutput = "";private Integer cookingTemperature = 0;private Integer profilePowerConsumption = 0;private Boolean lockState = false;
// Constructor//public MideaRiceCookerDevice(ThingConfig thingConfig) { super(thingConfig); this.thingConfig = thingConfig;}
// Basic Communications Methods//@Overridepublic void handleCommand(ChannelUID channelUID, Command command) {
if (channelUID == null command == null) { logger.error("ChannelUID or Command is null"); return; }
if (communicationService == null !communicationService.isConnected()) { logger.warn("Device is disconnected"); return; }
switch (channelUID.getId()) { case SWITCH_STATE: // Switch state if (command instanceof OnOffType) { if ((Boolean) ((OnOffType) command).toBoolean()) { switchOn(); } else { switchOff(); } } break; case DELAYED_START_TIMER: // Timer if (command instanceof StringType) { delayedStart((String) ((StringType) command).toString()); } break; case RECIPE_SELECTION: // Recipe if (command instanceof StringType) { recipe((String) ((StringType) command).toString()); } break; case COOKING_TEMPERATURE: // Cooking Temperature if (command instanceof DecimalType) { setTemperature(((DecimalType) command).intValue()); } break; case PROFILE_POWER_CONSUMPTION: // Power Consumption Profile if (command instanceof DecimalType) { setPowerConsumption(((DecimalType) command).intValue()); } break; case LOCK_STATE: // Lock if (command instanceof OnOffType) { if ((Boolean) ((OnOffType) command).toBoolean()) { lock(); } else { unlock(); } } break; default: logger.error("Channel not supported: {}", channelUID); break; }}
@Overridepublic void initialize() { logger.debug("Initialize Thing Handler");
// Create and Connect Communication Service Map
communicationService = new MideaCommunicationService(ipAddress, port, this); communicationService.connect();
// Initialize Switch State, Remaining Time Percent, and Delayed Start refreshState();
// Register Refresh Job and Start Timer scheduler.schedule(()->refreshState(), 0, TimeUnit.SECONDS); scheduler.schedule(()->refreshProfile(), 5, TimeUnit.SECONDS); scheduler.schedule(()->refreshTime(), 1, TimeUnit.SECONDS); scheduler.schedule(()->refreshRecipeOutput(), 10, TimeUnit.SECONDS); scheduler.schedule(()->refreshLock(), 10, TimeUnit.SECONDS);}
@Overridepublic void dispose() { logger.debug("Dispose Thing Handler"); communicationService.disconnect();}
// Specific Communication Methods//private void sendCommand(String command) { logger.debug("Send command: {}", command); String response = communicationService.sendCommand(command); logger.debug("Response: {}", response);}
private String sendQuery(String command) { logger.debug("Send query: {}", command); String response = communicationService.sendQuery(command); logger.debug("Response: {}", response); return response;}
private void switchOn() { sendCommand("ch00c1");
// Wait for Restart try { Thread.sleep(5000); } catch (InterruptedException e) { logger.error("Interrupted Exception", e); }
refreshState();}
private void switchOff() { sendCommand("ch00c0"); refreshState();}
private void delayedStart(String time) { if (time.equals("00:00")) { sendCommand("ch00c3"); } else { try { Pattern timePattern = Pattern.compile("([0-9]{2}):([0-9]{2})"); Matcher matcher = timePattern.matcher(time);
if (matcher.find()) { String hours = Integer.toHexString(Integer.parseInt(matcher.group(1))); String minutes = Integer.toHexString(Integer.parseInt(matcher.group(2)));
if (hours.length() < 2) { hours = "0" + hours; } if (minutes.length() < 2) { minutes = "0" + minutes; }
sendCommand("ch00cf" + hours + minutes + "00"); } else { logger.error("Wrong format for delayed start time: {}", time); } } catch (Exception e) { logger.error("Could not set delayed start", e); } }}
private void recipe(String recipe) { try { pattern = Pattern.compile("([A-Za-z0-9_ -]+)"); matcher = pattern.matcher(recipe);
if (matcher.find()) { recipeSelection = matcher.group(1); sendCommand("ch00" + Integer.toHexString(recipeSelection.length()) + recipeSelection); } else { logger.error("No recipe selection"); } } catch (Exception e) { logger.error("Could not set recipe", e); }}
private void setTemperature(Integer temperature) { if (temperature == null) { logger.error("No temperature set"); } else if (temperature < 50 temperature> 130) { logger.error("Temperature out of range"); } else { sendCommand("ch00" + Integer.toHexString(temperature - 50) + "01"); cookingTemperature = temperature; }}
private void setPowerConsumption(Integer profile) { if (profile == null) { logger.error("No Power Consumption Profile Set"); } else if (profile < 0 profile> 4) { logger.error("Power Consumption Profile out of range"); } else { sendCommand("ch01" + Integer.toHexString(baseProfile[profile])); profilePowerConsumption = baseProfile[profile]; }}
private void lock() { sendCommand("ch00cd"); refreshState();}
private void unlock() { sendCommand("ch00ce"); refreshState();}
// StatusUpdate Methods//public void refreshState() { String state = sendQuery("ch00c4");
if (state == null state.length() != 12) { logger.error("State: Incomplete Response: {}", state); return; }
switchState = (state.toLowerCase().startsWith("0a")); remainingTimePercent = Integer.parseInt(state.substring(2, 4), 16); delayedStartMinutes = Integer.parseInt(state.substring(10, 12), 16) * 60;
updateState(SWITCH_STATE, new OnOffType(switchState)); updateState(REMAINING_TIME_PERCENT, new QuantityType<>(remainingTimePercent, "%")); updateState(DELAYED_START_TIMER, new StringType(String.format("%02d:%02d", delayedStartMinutes / 60, delayedStartMinutes % 60)));}
public void refreshTime() { String response = sendQuery("ch0050"); String[] parts = response.split(" ");
if (parts.length != 3) { logger.error("Time: Incomplete Response: {}", response); return;

























