package srsim.controller;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import srsim.actuators.LightingActuator;
import srsim.domain.AbstractController;
import srsim.domain.IActuator;
import srsim.domain.ISensor;
import srsim.sensors.LightSensor;
import srsim.simulator.SimulationConfigurationException;
import srsim.simulator.SimulationContextException;
/**
* Controller class simulating a lighting controller
*
* @author phil
*
*/
public class LightingController extends AbstractController {
private ISensor sensor;
private List<IActuator> lights;
private int[] targetLightColor;
/**
* Adjusts attached lighting actuators to achieve the target light color
*
* @throws SimulationContextException
*/
private void controlColor() throws SimulationContextException {
getTargetLightColor();
int[] currentLightColor = context.getLightColor();
boolean changedColor = false;
if (currentLightColor[0] != targetLightColor[0]
|| currentLightColor[1] != targetLightColor[1]
|| currentLightColor[2] != targetLightColor[2]) {
for (IActuator light : lights) {
changedColor = ((LightingActuator) light)
.setColor(targetLightColor);
}
}
if (changedColor) {
notifyListeners("Light color has been adjusted.");
}
}
/**
* Adjusts attached lighting actuators to achieve the target brightness
* value
*
* @throws SimulationContextException
*/
private void controlBrightness() throws SimulationContextException {
double targetBrightness = getTargetBrightness();
if (targetBrightness < 1.0D) {
disableLights();
} else if (context.getBrightness() < targetBrightness) {
increaseBrightness(targetBrightness);
} else if (context.getBrightness() > targetBrightness) {
decreaseBrightness(targetBrightness);
}
}
/**
* Attempts to decrease the brightness of attached lights until
* targetBrightness is reached
*
* @param targetBrightness
* @throws SimulationContextException
*/
private void decreaseBrightness(final double targetBrightness)
throws SimulationContextException {
Iterator<IActuator> lights = this.lights.iterator();
while (lights.hasNext() && context.getBrightness() > targetBrightness) {
LightingActuator light = (LightingActuator) lights.next();
if (light.getState() == IActuator.ACTIVE
&& light.getBrightness() > light.getMinimumBrightness()) {
light.turnDown();
notifyListeners("light " + light.getId() + " turned down");
} else if (light.getState() == IActuator.ACTIVE) {
light.disable();
notifyListeners("light " + light.getId() + " disabled");
}
}
}
/**
* Attempts to increase the brightness of attached lights until
* targetBrightness is reached
*
* @param targetBrightness
* @throws SimulationContextException
*/
private void increaseBrightness(final double targetBrightness)
throws SimulationContextException {
Iterator<IActuator> lights = this.lights.iterator();
while (lights.hasNext() && context.getBrightness() < targetBrightness) {
LightingActuator light = (LightingActuator) lights.next();
if (light.getState() == IActuator.ACTIVE
&& light.getBrightness() < light.getMaxBrightness()) {
light.turnUp();
notifyListeners("light " + light.getId() + " turned up");
} else if (light.getState() == IActuator.IDLE) {
light.enable();
notifyListeners("light " + light.getId() + " enabled");
}
}
}
/**
* Disables all attached lights
*
* @throws SimulationContextException
*/
private void disableLights() throws SimulationContextException {
Iterator<IActuator> lights = this.lights.iterator();
while (lights.hasNext()) {
LightingActuator light = (LightingActuator) lights.next();
if (light.getState() == IActuator.ACTIVE) {
light.disable();
notifyListeners("light " + light.getId() + " disabled");
}
}
}
/**
* obtains the current target value for light color from the simulation
* context
*
* @throws SimulationContextException
*/
private void getTargetLightColor() throws SimulationContextException {
List<String> preferences = context.getPreference("targetLightColor");
targetLightColor = new int[] { 0, 0, 0 };
if (preferences != null) {
int validColors = 0;
for (String preference : preferences) {
if (preference.matches("^#([A-Fa-f0-9]{6})$")) {
validColors++;
String red = preference.substring(1, 3);
targetLightColor[0] += Integer.parseInt(red, 16);
String green = preference.substring(3, 5);
targetLightColor[1] += Integer.parseInt(green, 16);
String blue = preference.substring(5, 7);
targetLightColor[2] += Integer.parseInt(blue, 16);
} else {
String[] colorStrings = preference.split(" ");
if (colorStrings.length == 3) {
validColors++;
targetLightColor[0] += Integer
.parseInt(colorStrings[0]);
targetLightColor[1] += Integer
.parseInt(colorStrings[1]);
targetLightColor[2] += Integer
.parseInt(colorStrings[2]);
}
}
}
if (validColors > 0) {
targetLightColor[0] /= validColors;
targetLightColor[1] /= validColors;
targetLightColor[2] /= validColors;
}
} else {
targetLightColor[0] = 0;
targetLightColor[1] = 0;
targetLightColor[2] = 0;
}
}
/**
* Obtains the current target value for brightness from the simulation
* context
*
* @return
* @throws SimulationContextException
*/
private double getTargetBrightness() throws SimulationContextException {
double targetBrightness = 0.0D;
List<String> preferences = context.getPreference("targetBrightness");
if (preferences != null) {
for (String preference : preferences) {
targetBrightness += Double.parseDouble(preference);
}
targetBrightness /= preferences.size();
}
return targetBrightness;
}
public LightingController() {
lights = new LinkedList<IActuator>();
targetLightColor = new int[] { 0, 0, 0 };
}
@Override
public void attachSensor(ISensor sensor)
throws SimulationConfigurationException {
if (sensor instanceof LightSensor) {
this.sensor = sensor;
} else {
throw new SimulationConfigurationException(
"Trying to attach incompatible sensor");
}
}
@Override
public List<ISensor> getAttachedSensors() {
LinkedList<ISensor> list = new LinkedList<ISensor>();
list.add(sensor);
return list;
}
@Override
public void attachActuator(IActuator actuator)
throws SimulationConfigurationException {
if (actuator instanceof LightingActuator) {
lights.add(actuator);
} else {
throw new SimulationConfigurationException(
"Trying to attach incompatible actuator");
}
}
@Override
public List<IActuator> getAttachedActuators() {
return lights;
}
@Override
public void step() throws SimulationContextException {
controlBrightness();
controlColor();
}
}