diff --git a/.classpath b/.classpath new file mode 100644 index 00000000..f04bd82a --- /dev/null +++ b/.classpath @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 00000000..2656b0ff --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + hal + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..983eddac --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//lib/sphinx4-5prealpha-src/sphinx4-core/src/main/java=UTF-8 +encoding//lib/sphinx4-5prealpha-src/sphinx4-core/src/main/java/edu/cmu/sphinx/alignment/SimpleTokenizer.java=UTF-8 diff --git a/hal.db b/hal.db index bcc25b1f..f5355e27 100755 Binary files a/hal.db and b/hal.db differ diff --git a/lib/pi4j-core-1.0.jar b/lib/pi4j-core-1.0.jar new file mode 100644 index 00000000..64b7902c Binary files /dev/null and b/lib/pi4j-core-1.0.jar differ diff --git a/src/se/koc/hal/PowerChallenge.java b/src/se/koc/hal/PowerChallenge.java index 72d9752f..b2f45e0f 100755 --- a/src/se/koc/hal/PowerChallenge.java +++ b/src/se/koc/hal/PowerChallenge.java @@ -4,21 +4,31 @@ package se.koc.hal; import se.koc.hal.deamon.DataAggregatorDaemon; import se.koc.hal.deamon.HalDaemon; import zutil.db.DBConnection; +import zutil.log.CompactLogFormatter; +import zutil.log.LogUtil; import java.util.Timer; +import java.util.logging.Level; /** * Created by Ziver on 2015-12-03. */ public class PowerChallenge { + + public static DBConnection db; + private static HalDaemon[] daemons = new HalDaemon[]{ new DataAggregatorDaemon() }; public static void main(String[] args) throws Exception { + // init logging + LogUtil.setGlobalLevel(Level.ALL); + LogUtil.setGlobalFormatter(new CompactLogFormatter()); + // init Database - final DBConnection db = new DBConnection(DBConnection.DBMS.SQLite, "hal.db"); + db = new DBConnection(DBConnection.DBMS.SQLite, "hal.db"); // init daemons Timer daemonTimer = new Timer(); diff --git a/src/se/koc/hal/deamon/DataAggregatorDaemon.java b/src/se/koc/hal/deamon/DataAggregatorDaemon.java index 4ad7544f..9a6f7ab6 100755 --- a/src/se/koc/hal/deamon/DataAggregatorDaemon.java +++ b/src/se/koc/hal/deamon/DataAggregatorDaemon.java @@ -1,22 +1,90 @@ package se.koc.hal.deamon; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import java.util.Timer; import java.util.TimerTask; +import java.util.logging.Logger; + +import com.ibm.icu.util.Calendar; + +import se.koc.hal.PowerChallenge; +import zutil.db.DBConnection; +import zutil.db.SQLResultHandler; +import zutil.db.handler.SimpleSQLHandler; +import zutil.log.LogUtil; /** * Created by Ziver on 2015-12-03. */ public class DataAggregatorDaemon extends TimerTask implements HalDaemon { + private static final Logger logger = LogUtil.getLogger(); private static final int FIVE_MINUTES_IN_MS = 5 * 60 * 1000; public void initiate(Timer timer){ timer.schedule(this, FIVE_MINUTES_IN_MS); + run(); } @Override public void run() { - + DBConnection db = PowerChallenge.db; + try { + Long maxTimestampEnd = db.exec("SELECT MAX(timestamp_end) FROM sensor_data_aggr", new SimpleSQLHandler()); + if(maxTimestampEnd == null) + maxTimestampEnd = 0l; + logger.fine("Calculating 5 min periods..."); + long intervallTimestamp = getTimestampPeriodStart(5, System.currentTimeMillis()); + db.exec("SELECT * FROM sensor_data_raw WHERE timestamp > " + maxTimestampEnd + " AND timestamp < " + intervallTimestamp + " ORDER BY timestamp ASC", new FiveMinuteAgrrigator()); + } catch (SQLException e) { + e.printStackTrace(); + } } + + + private static long getTimestampPeriodStart(int min, long timestamp){ + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(System.currentTimeMillis()); + int currentMinute = cal.get(Calendar.MINUTE); + cal.set(Calendar.MINUTE, (currentMinute/min) * min); + return cal.getTimeInMillis(); + } + + private class FiveMinuteAgrrigator implements SQLResultHandler{ + + @Override + public Object handleQueryResult(Statement stmt, ResultSet result) throws SQLException { + long currentPeriodTimestamp = 0; + int sum = 0; + int count = 0; + while(result.next()){ + long timestamp = result.getLong("timestamp"); + long periodTimestamp = getTimestampPeriodStart(5, timestamp); + if(currentPeriodTimestamp != 0 && periodTimestamp != currentPeriodTimestamp){ + float confidence = count / 5f; + logger.finer("Calculated period: "+ currentPeriodTimestamp +" sum: "+ sum +" confidence: "+ confidence); + PowerChallenge.db.exec(String.format("INSERT INTO sensor_data_aggr(sensor_id, sequence_id, timestamp_start, timestamp_end, data, confidence) VALUES(%d, %d, %d, %d, %d, %f)", + result.getInt("sensor_id"), + 42, + currentPeriodTimestamp, + currentPeriodTimestamp + FIVE_MINUTES_IN_MS -1, + sum, + confidence)); + + // Reset variables + periodTimestamp = currentPeriodTimestamp; + sum = count = 0; + } + if(currentPeriodTimestamp == 0) currentPeriodTimestamp = periodTimestamp; + sum += result.getInt("data"); + ++count; + } + return null; + } + + } + } diff --git a/src/se/koc/hal/plugin/localsensor/ImpulseTracker.java b/src/se/koc/hal/plugin/localsensor/ImpulseTracker.java new file mode 100644 index 00000000..56a2fd71 --- /dev/null +++ b/src/se/koc/hal/plugin/localsensor/ImpulseTracker.java @@ -0,0 +1,106 @@ +package se.koc.hal.plugin.localsensor; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.pi4j.io.gpio.GpioController; +import com.pi4j.io.gpio.GpioFactory; +import com.pi4j.io.gpio.GpioPinDigitalInput; +import com.pi4j.io.gpio.PinPullResistance; +import com.pi4j.io.gpio.PinState; +import com.pi4j.io.gpio.RaspiPin; +import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; +import com.pi4j.io.gpio.event.GpioPinListenerDigital; + +public class ImpulseTracker implements Runnable { + + private static final int IMPULSE_REPORT_TIMEOUT = 60000; //one minute + private long nanoSecondsSleep = IMPULSE_REPORT_TIMEOUT * 1000000L; + private Integer impulseCount = 0; + private ExecutorService executorPool; + + public static void main(String args[]) throws InterruptedException, IOException { + new ImpulseTracker(); + } + + public ImpulseTracker() throws InterruptedException, IOException{ + + // create gpio controller + final GpioController gpio = GpioFactory.getInstance(); + + // provision gpio pin #02 as an input pin with its internal pull up resistor enabled + final GpioPinDigitalInput irLightSensor = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_UP); + + // create and register gpio pin listener + irLightSensor.addListener(new GpioPinListenerDigital() { + @Override + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { + if(event.getState() == PinState.LOW){ //low = light went on + //System.out.println("IR LED turned ON"); + synchronized(impulseCount){ + impulseCount++; + } + } + } + + }); + + this.executorPool = Executors.newCachedThreadPool(); + + //start a daemon thread to save the impulse count every minute + Thread thread = new Thread(this); + thread.setDaemon(true); + thread.start(); + + } + + @Override + public void run() { + long startTime = System.nanoTime(); + synchronized(impulseCount){ + impulseCount = 0; //reset the impulse count + } + while(true) { + sleepNano(nanoSecondsSleep); + int count = -1; + synchronized(impulseCount){ + count = impulseCount; + impulseCount = 0; + } + save(System.currentTimeMillis(), count); //save the impulse count + long estimatedNanoTimeSpent = System.nanoTime() - startTime; //this is where the loop ends + startTime = System.nanoTime(); //this is where the loop starts from now on + if(estimatedNanoTimeSpent > 0){ //if no overflow + long nanoSecondsTooMany = estimatedNanoTimeSpent - (IMPULSE_REPORT_TIMEOUT*1000000L); + //System.out.println("the look took ~" + estimatedNanoTimeSpent + "ns. That is " + nanoSecondsTooMany/1000000L + "ms off"); + nanoSecondsSleep -= nanoSecondsTooMany / 3; //divide by constant to take into account varaiations im loop time + } + } + } + + private void sleepNano(long ns){ + //System.out.println("will go to sleep for " + ns + "ns"); + try{ + Thread.sleep(ns/1000000L, (int)(ns%1000000L)); + }catch(InterruptedException e){ + //ignore + } + } + + private void save(long timestamp_end, int data){ + executorPool.execute(new Runnable(){ + @Override + public void run() { + //this.listener. + } + }); + } + + /* + public void setListener(Object listener){ + this.listener = listener; + } + */ + +}