/*******************************************************************************
* Copyright (c) 2015 Dominik Brämer.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
******************************************************************************/
package com.blogspot.thedsweb.daemon;
import java.io.File;
import java.net.MalformedURLException;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import com.blogspot.thedsweb.engine.Brightness;
import com.blogspot.thedsweb.engine.Stable;
import com.blogspot.thedsweb.main.Debug;
import com.blogspot.thedsweb.util.Battery;
import com.blogspot.thedsweb.util.Check;
import com.blogspot.thedsweb.util.Config;
import com.blogspot.thedsweb.util.Database;
import com.blogspot.thedsweb.util.Files;
import com.blogspot.thedsweb.util.Initialization;
public class BrightnessDaemon {
private Config config;
private boolean calibration;
private boolean faceDetectConfig;
private boolean faceDetect;
private int lowerLimit;
private int upperLimit;
private int[] limit;
private Stable stable;
private int i;
private int before;
private int after;
private int minIncrease;
private int maxIncrease;
private int increase;
private Brightness brightness;
private final File pidFile;
private final Semaphore semaphore = new Semaphore(1, false);
public BrightnessDaemon() {
// Initialize Files if necessary
Initialization.Files();
// Set PID file
pidFile = new File(Database.PATH_PID);
// Calibration has been running
calibration = false;
initialize();
}
private void initialize() {
// Read configuration File and set
// Upper limit, lower limit and face detection
try {
config = new Config();
faceDetectConfig = config.faceDetect();
lowerLimit = config.lowerLimit();
upperLimit = config.upperLimit();
limit = new int[4];
limit[0] = lowerLimit;
limit[1] = upperLimit;
limit[2] = lowerLimit;
limit[3] = upperLimit;
// Check upper and lower limit and correct values
// if necessary
Tools.checkLimit(limit);
i = limit[2];
// Values to increase loop sleep if nothing to do
before = 0;
after = 0;
minIncrease = config.minIncrease();
maxIncrease = config.maxIncrease();
increase = maxIncrease;
stable = new Stable(after, lowerLimit);
// Get actual brightness
brightness = new Brightness(config);
brightness.start();
} catch (final MalformedURLException e) {
Debug.LOG.log(Level.SEVERE, "Could not read config file.", e);
}
}
public void start() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Files.deletePid();
}
});
System.out.close();
System.err.close();
// Reset brightness level after reboot
brightness.resetBrightnessAfterReboot();
// Daemon for battery level observation
final Thread batteryDaemon = new Thread(new BatteryDaemon(),
"batteryDaemon");
batteryDaemon.setDaemon(true);
batteryDaemon.start();
// Loop until interrupt
while (pidFile.exists()) {
// Reload configuration on change
if (Check.configuration()) {
brightness.interrupt();
initialize();
}
// Check if calibration is running
if (Check.calibration()) {
if (!calibration) {
// Get current brightness
brightness.setCurrent();
} else {
// Reinitialize brightness after calibration
calibration = false;
brightness.interrupt();
brightness = new Brightness(config);
brightness.start();
}
} else {
calibration = true;
}
// Get last brightness value BEFORE processing
before = brightness.getLast();
/*
* If face detection is deactivated then set faceDetect to true only
* else set faceDetect to the value of the getFace function of
* Brightness object
*/
if (faceDetectConfig) {
faceDetect = brightness.getFace();
} else {
faceDetect = true;
}
try {
semaphore.acquire();
} catch (final InterruptedException e) {
}
lowerLimit = limit[2];
upperLimit = limit[3];
semaphore.release();
if (faceDetect) {
// Set brightness level
brightness.setBrightness();
try {
semaphore.acquire();
} catch (final InterruptedException e) {
}
upperLimit = limit[1];
semaphore.release();
increase = maxIncrease;
} else {
// Dim display
brightness.darkenBrightness();
increase = minIncrease;
}
// Get last brightness value AFTER processing
after = brightness.getLast();
// Increase loop sleep
if (before == after) {
if (i < upperLimit) {
i = i + increase;
}
} else {
i = lowerLimit;
}
// Increase correction
stable.setStatus(i, after);
i = stable.getLimit();
// Sleep for i seconds
try {
Thread.sleep(i);
} catch (final InterruptedException e) {
}
}
}
class BatteryDaemon implements Runnable {
@Override
public void run() {
try {
semaphore.acquire();
} catch (final InterruptedException e) {
}
final int lowerLimitConst = limit[0];
final int upperLimitConst = limit[1];
semaphore.release();
int lowerLimit;
int j;
while (true) {
// Battery friendliness
if (Battery.status() > 30) {
lowerLimit = lowerLimitConst;
// Set sleep of daemon loop to 1 minute
j = 60000;
} else {
lowerLimit = ((upperLimitConst - lowerLimitConst) >> 1)
+ lowerLimitConst;
// Set sleep of daemon loop to 5 minutes
j = 300000;
}
try {
semaphore.acquire();
} catch (final InterruptedException e) {
}
limit[2] = lowerLimit;
semaphore.release();
// Sleep for j seconds
try {
Thread.sleep(j);
} catch (final InterruptedException e) {
}
}
}
}
}