diff --git a/Makefile b/Makefile
index 4ac9732fd6310275df214bbdc99592e43f757cc6..df72e4686464f379274b299df9523ea05ac39ada 100644
--- a/Makefile
+++ b/Makefile
@@ -1,24 +1,40 @@
 ARCH=$(shell arch)
 CXX=			g++
-CXXFLAGS=		-O2 -g -pthread -fopenmp
+CXXFLAGS=		-std=c++11 -O2 -g -pthread -fopenmp
 
 obj/$(ARCH)/%.o:	%.cc
+			@mkdir -p obj/$(ARCH)
 			$(CXX) -c $(CXXFLAGS) $< -o $@
 
-all::			lib/$(ARCH)/libPowerSensor.a bin/$(ARCH)/testPowerSensor arduino
+all::			lib/$(ARCH)/libPowerSensor.a\
+			bin/$(ARCH)/psconfig\
+			bin/$(ARCH)/psrun\
+			bin/$(ARCH)/pstest\
+			arduino
 
-lib/$(ARCH)/libPowerSensor.a:	obj/$(ARCH)/PowerSensor.o lib/$(ARCH)
+lib/$(ARCH)/libPowerSensor.a: obj/$(ARCH)/PowerSensor.o
+			-mkdir -p lib/$(ARCH)
 			$(AR) cr $@ $<
 
-bin/$(ARCH)/testPowerSensor:	obj/$(ARCH)/testPowerSensor.o lib/$(ARCH)/libPowerSensor.a bin/$(ARCH)
-			$(CXX) $(CXXFLAGS) obj/$(ARCH)/testPowerSensor.o -Llib/$(ARCH) -lPowerSensor -o $@
+bin/$(ARCH)/psconfig:	obj/$(ARCH)/psconfig.o lib/$(ARCH)/libPowerSensor.a
+			-mkdir -p bin/$(ARCH)
+			$(CXX) $(CXXFLAGS) obj/$(ARCH)/psconfig.o -Llib/$(ARCH) -lPowerSensor -o $@
 
-obj/$(ARCH)/testPowerSensor.o:	testPowerSensor.cc PowerSensor.h obj/$(ARCH)
+bin/$(ARCH)/psrun:	obj/$(ARCH)/psrun.o lib/$(ARCH)/libPowerSensor.a
+			-mkdir -p bin/$(ARCH)
+			$(CXX) $(CXXFLAGS) obj/$(ARCH)/psrun.o -Llib/$(ARCH) -lPowerSensor -o $@
 
-obj/$(ARCH)/PowerSensor.o:	PowerSensor.cc PowerSensor.h obj/$(ARCH)
+bin/$(ARCH)/pstest:	obj/$(ARCH)/pstest.o lib/$(ARCH)/libPowerSensor.a
+			-mkdir -p bin/$(ARCH)
+			$(CXX) $(CXXFLAGS) obj/$(ARCH)/pstest.o -Llib/$(ARCH) -lPowerSensor -o $@
 
-obj/$(ARCH) lib/$(ARCH) bin/$(ARCH):
-			mkdir -p $@
+obj/$(ARCH)/psconfig.o:	psconfig.cc PowerSensor.h
+
+obj/$(ARCH)/psrun.o:	psrun.cc PowerSensor.h
+
+obj/$(ARCH)/pstest.o:	pstest.cc PowerSensor.h
+
+obj/$(ARCH)/PowerSensor.o: PowerSensor.cc PowerSensor.h Semaphore.h
 
 arduino::
 			+make -C Arduino
@@ -28,3 +44,4 @@ upload::		all
 
 clean::
 			make -C Arduino clean
+			$(RM) -r bin/$(ARCH) lib/$(ARCH) obj/$(ARCH)
diff --git a/PowerSensor.cc b/PowerSensor.cc
index c9bedad0c3bcc2266da3c793aa06628fcc4b6419..e205d3dc4212e0bb2ba78591dca9ba120db3aecc 100644
--- a/PowerSensor.cc
+++ b/PowerSensor.cc
@@ -22,44 +22,130 @@
 
 #include <cstdio>
 #include <cstdlib>
+#include <cstring>
 #include <iostream>
 
+#include <byteswap.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <omp.h>
-#include <sys/types.h>
+#include <sys/file.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <termios.h>
 #include <unistd.h>
 
 
+namespace PowerSensor {
 
-PowerSensor::PowerSensor(const char *device, const char *dumpFileName)
-:
-  dumpFile(dumpFileName == 0 ? 0 : new std::ofstream(dumpFileName)),
-  stop(false)
+
+void PowerSensor::Sensor::readFromEEPROM(int fd)
+{
+  struct EEPROM eeprom;
+  ssize_t       retval, bytesRead = 0;
+
+  do {
+    if ((retval = ::read(fd, (char *) &eeprom + bytesRead, sizeof eeprom - bytesRead)) < 0) {
+      perror("read device");
+      exit(1);
+    }
+  } while ((bytesRead += retval) < sizeof eeprom);
+
+#if defined __BIG_ENDIAN__
+  eeprom.volt      = __bswap_32(eeprom.volt);
+  eeprom.type      = __bswap_32(eeprom.type);
+  eeprom.nullLevel = __bswap_32(eeprom.nullLevel);
+#endif
+
+  setVolt(eeprom.volt);
+  setType(eeprom.type);
+  setNullLevel(eeprom.nullLevel);
+}
+
+
+void PowerSensor::Sensor::writeToEEPROM(int fd) const
+{
+  struct EEPROM eeprom;
+
+  eeprom.volt	   = volt;
+  eeprom.type      = type;
+  eeprom.nullLevel = nullLevel;
+
+#if defined __BIG_ENDIAN__
+  eeprom.volt      = __bswap_32(eeprom.volt);
+  eeprom.type      = __bswap_32(eeprom.type);
+  eeprom.nullLevel = __bswap_32(eeprom.nullLevel);
+#endif
+
+  ssize_t retval, bytesWritten = 0;
+
+  do {
+    if ((retval = ::write(fd, (char *) &eeprom + bytesWritten, sizeof eeprom - bytesWritten)) < 0) {
+      perror("write device");
+      exit(1);
+    }
+  } while ((bytesWritten += retval) < sizeof eeprom);
+}
+
+
+void PowerSensor::Sensor::updateDerivedValues()
+{
+  weight		= volt != 0 ? 2.5 / 512 * volt / type : 0;
+  consumedEnergy	= 0;
+  wattAtlastMeasurement = 0;
+  timeAtLastMeasurement = omp_get_wtime();
+}
+
+
+void PowerSensor::Sensor::setVolt(float volt)
+{
+  this->volt = volt;
+  updateDerivedValues();
+}
+
+
+void PowerSensor::Sensor::setType(float type)
+{
+  this->type = type;
+  updateDerivedValues();
+}
+
+
+void PowerSensor::Sensor::setNullLevel(float nullLevel)
+{
+  this->nullLevel = nullLevel;
+  updateDerivedValues();
+}
+
+
+int PowerSensor::openDevice(const char *device)
 {
-  lastState.microSeconds = 0;
+  int fd;
 
   if ((fd = open(device, O_RDWR)) < 0) {
     perror("open device");
     exit(1);
   }
 
+  if (flock(fd, LOCK_EX) < 0) {
+    perror("flock");
+    exit(1);
+  }
 
   //Configure port for 8N1 transmission
   struct termios options;
 
   tcgetattr(fd, &options);		//Gets the current options for the port
-  cfsetispeed(&options, B2000000);	//Sets the Input Baud Rate
-  cfsetospeed(&options, B2000000);	//Sets the Output Baud Rate
+  cfsetispeed(&options, B9600);	//Sets the Input Baud Rate
+  cfsetospeed(&options, B9600);	//Sets the Output Baud Rate
 
   options.c_cflag = (options.c_cflag & ~CSIZE) | CS8;
   options.c_iflag = IGNBRK;
   options.c_lflag = 0;
   options.c_oflag = 0;
   options.c_cflag |= CLOCAL | CREAD;
-  options.c_cc[VMIN] = sizeof(State::MC_State);
+  options.c_cc[VMIN] = 2;
   options.c_cc[VTIME] = 0;
   options.c_iflag &= ~(IXON | IXOFF | IXANY);
   options.c_cflag &= ~(PARENB | PARODD);
@@ -67,173 +153,368 @@ PowerSensor::PowerSensor(const char *device, const char *dumpFileName)
   /* commit the options */
   tcsetattr(fd, TCSANOW, &options);
 
+#if defined UNO
   /* Wait for the Arduino to reset */
   sleep(2);
+#endif
+
   /* Flush anything already in the serial buffer */
   tcflush(fd, TCIFLUSH);
 
-  if ((errno = pthread_mutex_init(&mutex, 0)) != 0) {
-    perror("pthread_mutex_init");
-    exit(1);
-  }
+  return fd;
+}
 
-  doMeasurement(); // initialise
 
-  if ((errno = pthread_create(&thread, 0, &PowerSensor::IOthread, this)) != 0) {
-    perror("pthread_create");
-    exit(1);
-  }
+PowerSensor::PowerSensor(const char *device)
+:
+  startTime(omp_get_wtime()),
+  fd(openDevice(device)),
+  thread(nullptr)
+{
+  startCleanupProcess();
+  readSensorsFromEEPROM();
+  startIOthread();
 }
 
 
 PowerSensor::~PowerSensor()
 {
-  stop = true;
-
-  if ((errno = pthread_join(thread, 0)) != 0)
-    perror("pthread_join");
-
-  if ((errno = pthread_mutex_destroy(&mutex)) != 0)
-    perror("pthread_mutex_destroy");
+  stopIOthread();
 
   if (close(fd))
     perror("close device");
+}
+
 
-  if (dumpFile != 0)
-    delete dumpFile;
+void PowerSensor::readSensorsFromEEPROM()
+{
+  if (write(fd, "r", 1) != 1) {
+    perror("write device");
+    exit(1);
+  }
+
+  for (Sensor &sensor : sensors)
+    sensor.readFromEEPROM(fd);
 }
 
 
-void PowerSensor::lock()
+void PowerSensor::writeSensorsToEEPROM()
 {
-  if ((errno = pthread_mutex_lock(&mutex)) != 0) {
-    perror("pthread_mutex_lock");
+  stopIOthread();
+
+  if (write(fd, "w", 1) != 1) {
+    perror("write device");
     exit(1);
   }
+
+#if defined UNO
+  struct termios options;
+
+  usleep(200000);
+  tcgetattr(fd, &options);
+  cfsetospeed(&options, B115200);
+  tcsetattr(fd, TCSANOW, &options);
+#endif
+
+  for (const Sensor &sensor : sensors)
+    sensor.writeToEEPROM(fd);
+
+#if defined UNO
+  usleep(200000);
+  tcgetattr(fd, &options);
+  cfsetospeed(&options, B2000000);
+  tcsetattr(fd, TCSANOW, &options);
+#endif
+
+  startIOthread();
 }
 
 
-void PowerSensor::unlock()
+void PowerSensor::startCleanupProcess()
 {
-  if ((errno = pthread_mutex_unlock(&mutex)) != 0) {
-    perror("pthread_mutex_unlock");
+  // spawn child process to make sure that the Arduino receives a 'T', no matter how the application terminates
+
+  int pipe_fds[2];
+
+  if (pipe(pipe_fds) < 0) {
+    perror("pipe");
     exit(1);
   }
+
+  switch (fork())
+  {
+    ssize_t retval;
+
+    case -1 : perror("fork");
+	      exit(1);
+
+    case  0 : // detach from the parent process, so signals to the parent are not caught by the child
+	      setsid();
+
+	      // close all file descriptors, except pipe read end and Arduino fd
+	      for (int i = 3, last = getdtablesize(); i < last; i ++)
+		if (i != fd && i != pipe_fds[0])
+		  close(i);
+
+	      // wait until parent closes pipe_fds[1] so that read fails
+	      char byte;
+	      retval = ::read(pipe_fds[0], &byte, sizeof byte);
+
+	      // tell Arduino to stop sending data
+	      retval = write(fd, "T", 1);
+
+	      // drain garbage
+	      usleep(100000);
+	      tcflush(fd, TCIFLUSH);
+
+	      exit(0);
+
+    default:  close(pipe_fds[0]);
+  }
 }
 
 
-void *PowerSensor::IOthread(void *arg)
+bool PowerSensor::Sensor::inUse() const
 {
-  return static_cast<PowerSensor *>(arg)->IOthread();
+  return volt != 0;
 }
 
 
-void *PowerSensor::IOthread()
+void PowerSensor::Sensor::updateLevel(int16_t level)
 {
-  while (!stop)
-    doMeasurement();
+  double now = omp_get_wtime();
 
-  return 0;
+  wattAtlastMeasurement = (level - 512) * weight - nullLevel;
+  consumedEnergy       += wattAtlastMeasurement * (now - timeAtLastMeasurement);
+  timeAtLastMeasurement = now;
 }
 
 
-void PowerSensor::doMeasurement()
+double PowerSensor::Sensor::totalEnergy(double now) const
 {
-  State::MC_State currentState;
+  return /* weight == 0 ? 0 : */ consumedEnergy + wattAtlastMeasurement * (now - timeAtLastMeasurement);
+}
 
-  ssize_t retval, bytesRead = 0;
 
-  if (write(fd, "s", 1) != 1) {
-    perror("write device");
-    exit(1);
-  }
+double PowerSensor::Sensor::currentWatt() const
+{
+  return /* weight == 0 ? 0 : */ wattAtlastMeasurement;
+}
 
-  do {
-    if ((retval = ::read(fd, (char *) &currentState.consumedEnergy + bytesRead, sizeof(State::MC_State) - bytesRead)) < 0) {
+
+bool PowerSensor::readLevelFromDevice(unsigned &sensorNumber, unsigned &level)
+{
+  uint8_t msg[2];
+  ssize_t retval, bytesRead = 0;
+
+  while (true) {
+    if ((retval = ::read(fd, (char *) &msg + bytesRead, sizeof msg - bytesRead)) < 0) {
       perror("read device");
       exit(1);
+    } else if ((bytesRead += retval) == sizeof msg) {
+      if (msg[0] == 0xFF && msg[1] == 0xE0) {
+	return false;
+      } else if ((sensorNumber = msg[0] >> 5) < MAX_SENSORS && (msg[1] & 0xE0) == 0xE0) {
+	level = ((msg[0] & 0x1F) << 5) | (msg[1] & 0x1F);
+	return true;
+      } else {
+	msg[0] = msg[1]; // byte lost?  drop first byte and try again
+	bytesRead = 1;
+      }
     }
-  } while ((bytesRead += retval) < sizeof(State::MC_State));
+  }
+}
 
-  lock();
 
-  if (lastState.microSeconds != currentState.microSeconds) {
-    previousState = lastState;
-    lastState = currentState;
+void PowerSensor::dumpCurrentWattToFile()
+{
+  std::unique_lock<std::mutex> lock(dumpFileMutex);
+  double totalWatt = 0;
+  double time      = omp_get_wtime();
+
+  *dumpFile << "S " << time - startTime;
+
+#if 1
+  static double previousTime;
+  *dumpFile << ' ' << 1e6 * (time - previousTime);
+  previousTime = time;
+#endif
+
+  for (const Sensor &sensor : sensors)
+    if (sensor.inUse()) {
+      *dumpFile << ' ' << sensor.currentWatt();
+      totalWatt += sensor.currentWatt();
+    }
 
-    if (dumpFile != 0)
-      *dumpFile << "S " << currentState.microSeconds / 1e6 << ' ' << (currentState.consumedEnergy - previousState.consumedEnergy) * (65536.0 / 512) / (currentState.microSeconds - previousState.microSeconds) << std::endl;
+  *dumpFile << ' ' << totalWatt << std::endl;
+}
+
+
+void PowerSensor::IOthread()
+{
+  threadStarted.up();
+
+  unsigned sensorNumber, level;
+
+  while (readLevelFromDevice(sensorNumber, level)) {
+    std::unique_lock<std::mutex> lock(mutex);
+    sensors[sensorNumber].updateLevel(level);
+
+    if (dumpFile != nullptr)
+      dumpCurrentWattToFile();
   }
+}
 
-#if 0
-  static double lastTime;
-  static unsigned count;
-  ++ count;
 
-  if (lastTime + 1 < omp_get_wtime()) {
-#pragma omp critical (cout)
-    std::cout << "nr times read = " << count << std::endl;
-    lastTime = omp_get_wtime();
-    count = 0;
+void PowerSensor::startIOthread()
+{
+  if (thread == nullptr) {
+    thread = new std::thread(&PowerSensor::IOthread, this);
+
+    if (write(fd, "S", 1) != 1) {
+      perror("write device");
+      exit(1);
+    }
   }
-#endif
 
-  unlock();
+  threadStarted.down(); // wait for the IOthread to run smoothly
+}
+
+
+void PowerSensor::stopIOthread()
+{
+  if (thread != nullptr) {
+    if (write(fd, "X", 1) < 0) {
+      perror("write");
+      exit(1);
+    }
+
+    thread->join();
+    delete thread;
+    thread = 0;
+  }
+}
+
+
+void PowerSensor::dump(const char *dumpFileName)
+{
+  dumpFile = std::unique_ptr<std::ofstream>(dumpFileName != nullptr ? new std::ofstream(dumpFileName) : nullptr);
 }
 
 
-void PowerSensor::mark(const State &state, const char *name, unsigned tag)
+void PowerSensor::mark(const State &state, const char *name, unsigned tag) const
 {
-  if (dumpFile != 0) {
-    lock();
-    *dumpFile << "M " << state.lastState.microSeconds * 1e-6 << ' ' << tag << " \"" << (name == 0 ? "" : name) << '"' << std::endl;
-    unlock();
+  if (dumpFile != nullptr) {
+    std::unique_lock<std::mutex> lock(dumpFileMutex);
+    *dumpFile << "M " << state.timeAtRead - startTime << ' ' << tag << " \"" << (name == nullptr ? "" : name) << '"' << std::endl;
   }
 }
 
 
-void PowerSensor::mark(const State &startState, const State &stopState, const char *name, unsigned tag)
+void PowerSensor::mark(const State &startState, const State &stopState, const char *name, unsigned tag) const
 {
-  if (dumpFile != 0) {
-    lock();
-    *dumpFile << "M " << startState.lastState.microSeconds * 1e-6 << ' ' << stopState.lastState.microSeconds * 1e-6 << ' ' << tag << " \"" << (name == 0 ? "" : name) << '"' << std::endl;
-    unlock();
+  if (dumpFile != nullptr) {
+    std::unique_lock<std::mutex> lock(dumpFileMutex);
+    *dumpFile << "M " << startState.timeAtRead - startTime << ' ' << stopState.timeAtRead << ' ' << tag << " \"" << (name == nullptr ? "" : name) << '"' << std::endl;
   }
 }
 
 
-PowerSensor::State PowerSensor::read()
+State PowerSensor::read() const
 {
   State state;
 
-  lock();
-  state.previousState = previousState;
-  state.lastState = lastState;
+  std::unique_lock<std::mutex> lock(mutex);
   state.timeAtRead = omp_get_wtime();
-  unlock();
+
+  for (unsigned sensorID = 0; sensorID < MAX_SENSORS; sensorID ++)
+    state.consumedEnergy[sensorID] = sensors[sensorID].totalEnergy(state.timeAtRead);
 
   return state;
 }
 
 
-double PowerSensor::Joules(const State &firstState, const State &secondState)
+double Joules(const State &firstState, const State &secondState, int sensorID)
 {
-  return Watt(firstState, secondState) * seconds(firstState, secondState);
+  if (sensorID >= (signed) MAX_SENSORS)
+    return 0;
+
+  if (sensorID >= 0)
+    return secondState.consumedEnergy[sensorID] - firstState.consumedEnergy[sensorID];
+
+  double joules = 0;
+
+  for (double consumedEnergy : secondState.consumedEnergy)
+    joules += consumedEnergy;
+
+  for (double consumedEnergy : firstState.consumedEnergy)
+    joules -= consumedEnergy;
+
+  return joules;
 }
 
 
-double PowerSensor::seconds(const State &firstState, const State &secondState)
+double seconds(const State &firstState, const State &secondState)
 {
   return secondState.timeAtRead - firstState.timeAtRead;
 }
 
 
-double PowerSensor::Watt(const State &firstState, const State &secondState)
+double Watt(const State &firstState, const State &secondState, int sensorID)
+{
+  return Joules(firstState, secondState, sensorID) / seconds(firstState, secondState);
+}
+
+
+float PowerSensor::getVolt(unsigned sensorID) const
 {
-  uint32_t microSeconds = secondState.lastState.microSeconds - firstState.lastState.microSeconds;
+  return sensorID < MAX_SENSORS ? sensors[sensorID].volt : 0;
+}
+
+
+void PowerSensor::setVolt(unsigned sensorID, float volt)
+{
+  if (sensorID < MAX_SENSORS) {
+    sensors[sensorID].setVolt(volt);
+    writeSensorsToEEPROM();
+  }
+}
+
+
+float PowerSensor::getType(unsigned sensorID) const
+{
+  return sensorID < MAX_SENSORS ? sensors[sensorID].type : 0;
+}
+
+
+void PowerSensor::setType(unsigned sensorID, float type)
+{
+  if (sensorID < MAX_SENSORS) {
+    sensors[sensorID].setType(type);
+    writeSensorsToEEPROM();
+  }
+}
+
+
+float PowerSensor::getNullLevel(unsigned sensorID) const
+{
+  return sensorID < MAX_SENSORS ? sensors[sensorID].nullLevel : 0;
+}
+
+
+void PowerSensor::setNullLevel(unsigned sensorID, float nullLevel)
+{
+  if (sensorID < MAX_SENSORS) {
+    sensors[sensorID].setNullLevel(nullLevel);
+    writeSensorsToEEPROM();
+  }
+}
+
+
+bool PowerSensor::inUse(unsigned sensorID) const
+{
+  return sensorID < MAX_SENSORS && sensors[sensorID].inUse();
+}
+
 
-  if (microSeconds != 0)
-    return (secondState.lastState.consumedEnergy - firstState.lastState.consumedEnergy) * (65536.0 / 512) / microSeconds;
-  else // very short time
-    return (secondState.lastState.consumedEnergy - secondState.previousState.consumedEnergy) * (65536.0 / 512) / (secondState.lastState.microSeconds - secondState.previousState.microSeconds);
 }
diff --git a/PowerSensor.h b/PowerSensor.h
index 783d8b0cdde82f4749aaea67f4ed7ba7fe25d9aa..a76c84b02c612c978cbcd2497ba193af5df8b6fc 100644
--- a/PowerSensor.h
+++ b/PowerSensor.h
@@ -21,50 +21,98 @@
 #if !defined POWER_SENSOR_H
 #define POWER_SENSOR_H
 
+#include "Semaphore.h"
+
 #include <inttypes.h>
-#include <pthread.h>
 
 #include <fstream>
+#include <mutex>
+#include <thread>
 
 
-class PowerSensor
+namespace PowerSensor {
+
+
+const static unsigned MAX_SENSORS = 5;
+
+
+struct State
 {
-  public:
-    struct State
-    {
-      struct MC_State
-      {
-	int32_t  consumedEnergy;
-	uint32_t microSeconds;
-      } previousState, lastState;
+  double consumedEnergy[MAX_SENSORS];
+  double timeAtRead;
+};
 
-      double timeAtRead;
-    };
 
-    PowerSensor(const char *device = "/dev/ttyACM0", const char *dumpFileName = 0);
+class PowerSensor
+{
+  public:
+    PowerSensor(const char *device = "/dev/ttyACM0");
     ~PowerSensor();
 
-    State read();
-    void mark(const State &, const char *name = 0, unsigned tag = 0);
-    void mark(const State &start, const State &stop, const char *name = 0, unsigned tag = 0);
+    State read() const;
 
-    static double Joules(const State &firstState, const State &secondState);
-    static double seconds(const State &firstState, const State &secondState);
-    static double Watt(const State &firstState, const State &secondState);
+    void dump(const char *dumpFileName); // dumpFileName == 0 --> stop dumping
+    void mark(const State &, const char *name = 0, unsigned tag = 0) const;
+    void mark(const State &start, const State &stop, const char *name = 0, unsigned tag = 0) const;
+
+    float getVolt(unsigned sensorID) const;
+    void  setVolt(unsigned sensorID, float volt);
+    float getType(unsigned sensorID) const;
+    void  setType(unsigned sensorID, float type);
+    float getNullLevel(unsigned sensorID) const;
+    void  setNullLevel(unsigned sensorID, float nullLevel);
+    bool  inUse(unsigned sensorID) const;
 
   private:
+    struct Sensor
+    {
+      struct EEPROM
+      {
+	float volt __attribute__((packed));
+	float type __attribute__((packed));
+	float nullLevel __attribute__((packed));
+      };
+
+      float    volt, type, nullLevel;
+      double   weight;
+      double   consumedEnergy;
+      double   wattAtlastMeasurement;
+      double   timeAtLastMeasurement;
+
+      bool     inUse() const;
+      void     readFromEEPROM(int fd), writeToEEPROM(int fd) const;
+      void     setVolt(float), setType(float), setNullLevel(float);
+      void     updateDerivedValues();
+      void     updateLevel(int16_t level);
+      double   totalEnergy(double now) const;
+      double   currentWatt() const;
+    } sensors[MAX_SENSORS];
+
+    double        startTime;
     int		  fd;
-    std::ofstream *dumpFile;
-    pthread_t	  thread;
-    pthread_mutex_t mutex;
-    volatile bool stop;
-    State::MC_State previousState, lastState;
+    std::unique_ptr<std::ofstream> dumpFile;
+    //volatile bool stop;
+    mutable std::mutex mutex, dumpFileMutex;
+    Semaphore     threadStarted;
+    std::thread	  *thread;
+    void	  startIOthread(), stopIOthread();
+
+    int		  openDevice(const char *device);
+    double	  totalEnergy() const;
+
+    void	  readSensorsFromEEPROM(), writeSensorsToEEPROM();
+    bool	  readLevelFromDevice(unsigned &sensorNumber, unsigned &level);
+    void	  dumpCurrentWattToFile();
+    void	  IOthread();
+
+    void	  startCleanupProcess();
+};
 
-    void	  lock(), unlock();
 
-    static void   *IOthread(void *);
-    void	  *IOthread();
-    void	  doMeasurement();
-};
+double Joules(const State &firstState, const State &secondState, int sensorID = -1 /* default: all sensors */);
+double seconds(const State &firstState, const State &secondState);
+double Watt(const State &firstState, const State &secondState, int sensorID = -1 /* default: all sensors */);
+
+}
 
 #endif