/**
* 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);
}
}