/** * C-Nery - A home automation web application for C-Bus. * Copyright (C) 2008,2009,2012 Dave Oxley <dave@daveoxley.co.uk>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package com.daveoxley.cnery.scenes; import com.daveoxley.cbus.CGateException; import com.daveoxley.cbus.Group; import com.daveoxley.cbus.Response; import com.daveoxley.cnery.actions.SceneActionHome; import com.daveoxley.cnery.entities.Scene; import com.daveoxley.cnery.entities.SceneAction; import com.daveoxley.cnery.entities.SceneActionCondition; import com.daveoxley.cnery.util.CBusAction; import com.workplacesystems.queuj.Process; import com.workplacesystems.queuj.process.java.JavaProcessRunner; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; /** * * @author Dave Oxley <dave@daveoxley.co.uk> */ @Name("sceneActionRunner") public class SceneActionRunner extends AbstractRunner<SceneActionCondition> { private final static Log log = LogFactory.getLog(SceneActionRunner.class); @In private JavaProcessRunner PROCESS_RUNNER; @In private SceneAction sceneAction; @In(create=true) private SceneActionHome sceneActionHome; @In private CBusAction cBusAction; @Override boolean ignoreCondition(boolean scheduledCheck, SceneActionCondition condition) { return (condition.getSceneState() == SceneActionCondition.SceneState.TRIGGERED && scheduledCheck); } @Override boolean doAction(SceneActionCondition condition) { return condition.getAction() == SceneActionCondition.Action.ACTION; } public void run() throws CGateException { sceneActionHome.clearInstance(); sceneActionHome.setId(sceneAction.getId()); sceneAction = sceneActionHome.getInstance(); Group group = sceneAction.getCBusGroup(); Scene scene = sceneAction.getScene(); Process<Integer> process = scene.getActivateProcess(); if (!scene.isActive() && process != null && (process.isRunning() || process.isWaitingToRun())) { process.attach(); } if (sceneAction.getScene().isActive()) { log.info("Checking conditions for SceneAction " + sceneAction.getScene().getName() + "." + group.getName() + "." + sceneAction.getId() + " : " + group.getAddress()); boolean firstRun = sceneAction.isFirstRun(); if (conditionsMet(sceneAction, !firstRun)) runAction(group); else if (!firstRun) resetAction(group); } else { resetAction(group); } sceneAction.setFirstRun(false); sceneActionHome.update(); } private void runAction(Group group) throws CGateException { if (sceneAction.isActive()) return; sceneAction.setActive(true); String logMessage = "run SceneAction " + sceneAction.getScene().getName() + "." + sceneAction.getId() + " : " + group.getAddress() + " - "; List<Response> responses = new ArrayList<Response>(); if (sceneAction.getType() == SceneAction.Type.ON) { log.info(logMessage + "on"); responses.add(cBusAction.on(group)); } else if (sceneAction.getType() == SceneAction.Type.OFF) { log.info(logMessage + "off"); responses.add(cBusAction.off(group)); } else if (sceneAction.getType() == SceneAction.Type.RAMP) { log.info(logMessage + "ramp to " + sceneAction.getLevel() + " in " + sceneAction.getDuration()); responses.add(cBusAction.ramp(group, sceneAction.getLevel(), sceneAction.getDuration())); } else if (sceneAction.getType() == SceneAction.Type.BELL_PRESS) { log.info(logMessage + "bell press"); responses.addAll(cBusAction.bellPress(group)); } else throw new IllegalStateException(sceneAction.getType() + " is not 'O', 'F' or 'R'"); cBusAction.handleResponses(responses); } private void resetAction(Group group) throws CGateException { if (!sceneAction.isActive()) return; sceneAction.setActive(false); if (sceneAction.getScene().getResetAction() == Scene.ResetAction.RESET_UNLESS_CHANGED) { int expectedLevel = -1; if (sceneAction.getType() == SceneAction.Type.ON) expectedLevel = 255; else if (sceneAction.getType() == SceneAction.Type.OFF || sceneAction.getType() == SceneAction.Type.BELL_PRESS) expectedLevel = 0; else if (sceneAction.getType() == SceneAction.Type.RAMP) expectedLevel = sceneAction.getLevel(); else throw new IllegalStateException(sceneAction.getType() + " is not 'O', 'F' or 'R'"); int currentLevel = group.getLevel(); if (currentLevel != expectedLevel) return; } int resetLevel = -1; if (sceneAction.getScene().getResetAction() == Scene.ResetAction.RESET_UNLESS_CHANGED || sceneAction.getScene().getResetAction() == Scene.ResetAction.RESET) resetLevel = sceneAction.getOriginalLevel(); else if (sceneAction.getScene().getResetAction() == Scene.ResetAction.ZERO) resetLevel = 0; log.info("reset SceneAction " + sceneAction.getScene().getName() + "." + sceneAction.getId() + " : " + group.getAddress() + " - level " + resetLevel); if (resetLevel < 0) return; List<Response> responses = new ArrayList<Response>(); if (sceneAction.getType() == SceneAction.Type.ON) { if (resetLevel == 0) responses.add(cBusAction.off(group)); else if (resetLevel < 255) responses.add(cBusAction.ramp(group, resetLevel, 0)); } else if (sceneAction.getType() == SceneAction.Type.OFF) { if (resetLevel == 255) responses.add(cBusAction.on(group)); else if (resetLevel > 0) responses.add(cBusAction.ramp(group, resetLevel, 0)); } else if (sceneAction.getType() == SceneAction.Type.RAMP) responses.add(cBusAction.ramp(group, resetLevel, 0)); else if (sceneAction.getType() == SceneAction.Type.BELL_PRESS) responses.addAll(cBusAction.bellPress(group)); cBusAction.handleResponses(responses); } }