diff --git a/app/HasStatus.php b/app/HasStatus.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b0afb928f292ddc1b6295dfe0fa336cf99dff79
--- /dev/null
+++ b/app/HasStatus.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace App;
+
+/**
+ *
+ * @author tibo
+ */
+interface HasStatus
+{
+    public function status() : Status;
+}
diff --git a/app/Report.php b/app/Report.php
new file mode 100644
index 0000000000000000000000000000000000000000..b6d4809f40da311e6de485bc63adf539a9208fb7
--- /dev/null
+++ b/app/Report.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace App;
+
+/**
+ * Status report
+ *
+ * @author tibo
+ */
+class Report implements HasStatus
+{
+
+    private $name;
+    private $status;
+    private $html = "";
+    
+    /**
+     * Name is mandatory.
+     * Default status is "Unknown"
+     */
+    public function __construct(string $name, ?Status $status = null, ?string $html = "")
+    {
+        $this->name = $name;
+        $this->status = $status;
+        $this->html = $html;
+        
+        if ($status == null) {
+            $this->status = Status::unknown();
+        } else {
+            $this->status = $status;
+        }
+    }
+    
+    public function setStatus(Status $status) : Report
+    {
+        $this->status = $status;
+        return $this;
+    }
+    
+    public function setHTML(string $html) : Report
+    {
+        $this->html = $html;
+        return $this;
+    }
+    
+    public function name() : string
+    {
+        return $this->name;
+    }
+    
+    public function status() : Status
+    {
+        return $this->status;
+    }
+    
+    public function html() : string
+    {
+        return $this->html;
+    }
+}
diff --git a/app/Sensor.php b/app/Sensor.php
index e60166e7c2d50f69fcc085c254792e0516ef57b2..abf3d2fe1f3791bf00c14a2630bea7ba1c4d7a96 100644
--- a/app/Sensor.php
+++ b/app/Sensor.php
@@ -2,44 +2,14 @@
 
 namespace App;
 
+use Illuminate\Database\Eloquent\Collection;
+
 /**
- * Base (abstract) class for sensors.
+ * Sensors must analyze a collection of Record, and produce a Report.
  *
  * @author tibo
  */
-abstract class Sensor
+interface Sensor
 {
-
-    private $server;
-
-    public function __construct(?Server $server = null)
-    {
-        $this->server = $server;
-    }
-
-    protected function server() : Server
-    {
-        return $this->server;
-    }
-
-    /**
-     * Get the name of the sensor. Can be overridden by sub-classes to provide
-     * a more meaningful name.
-     *
-     * @return string
-     */
-    public function name() : string
-    {
-        return (new \ReflectionClass($this))->getShortName();
-    }
-    
-    /**
-     * Compute the status code from an array of Record.
-     */
-    abstract public function status(array $records) : int;
-    
-    /**
-     * Create the HTML report describing the result of this sensor's analysis.
-     */
-    abstract public function report(array $records) : string;
+    public function analyze(Collection $records, ServerInfo $serverinfo) : Report;
 }
diff --git a/app/Sensor/CPUtemperature.php b/app/Sensor/CPUtemperature.php
index d22b89c045f75d74f066e46163f2ef9b568d12b0..b53368cdc466e3bba3ea9c743111eae9be07458d 100644
--- a/app/Sensor/CPUtemperature.php
+++ b/app/Sensor/CPUtemperature.php
@@ -2,145 +2,71 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
      * Description of Update
  *
  * @author helha
  */
-class CPUtemperature extends Sensor
+class CPUtemperature implements Sensor
 {
-
-    const REGEXP = "/^(Core \d+):\s+\+(\d+\.\d+)/m";
+    // Match a CPU line like
+    // Package id 0:  +39.0°C  (high = +84.0°C, crit = +100.0°C)
     const REGEXPCPU= "/^(Package id)+\s+(\d):\s+\+(\d+\.\d+)°C\s+\(high\s=\s\+\d+\.\d°C,\scrit\s=\s\+(\d+\.\d+)°C\)/m";
+    
+    // Mach a core line
+    // Core 0:        +38.0°C  (high = +84.0°C, crit = +100.0°C)
+    const REGEXPCORE = "/^(Core \d+):\s+\+(\d+\.\d+)°C\s+\(high\s=\s\+\d+\.\d°C,\scrit\s=\s\+(\d+\.\d+)°C\)/m";
 
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("CPU temperature");
+        
+        $record = $records->last();
         if (! isset($record->data["cpu-temperature"])) {
-            return "<p>No data available...</p>"
+            return $report->setHTML("<p>No data available...</p>"
                 . "<p>Maybe <code>sensors</code> is not installed.</p>"
-                . "<p>You can install it with <code>sudo apt install lm-sensors</code></p>";
+                . "<p>You can install it with <code>sudo apt install lm-sensors</code></p>");
         }
-        $Cores = self::parseCPUtemperature($record->data['cpu-temperature']);
-        $CPUS = self::parseCPU($record->data['cpu-temperature']);
         
-        $return = "<table class='table table-sm'>";
-        $return .= "<tr><th>Name</th><th>Temperature (°C)</th><th>T°crit (°C)</th></tr>";
+        $cpus = $this->parse($record->data['cpu-temperature']);
+        $report->setHTML(view("sensor.cputemperature", ["cpus" => $cpus]));
+        $report->setStatus(Status::max($cpus));
         
-        foreach ($CPUS as $CPU) {
-            $return .= "<tr><td>" . "<b>" ."CPU " . $CPU->number . "</td><td>"
-                    . "<b>" . $CPU->value  . "</td><td>" . "<b>" . $CPU->critvalue . "</td></tr>";
-            foreach ($Cores as $Core) {
-                if ($Core->number == $CPU->number) {
-                    $return .= "<tr><td>" . $Core->name . "</td><td>"
-                            . $Core->corevalue  . "</td><td>" . " " . "</td></tr>";
-                }
-            }
-        }
-        $return .= "</table>";
-        return $return;
+        return $report;
     }
 
-    public function status(array $records) : int
+    public function parse(string $string)
     {
-        $record = end($records);
-        if (! isset($record->data["cpu-temperature"])) {
-            return \App\Status::UNKNOWN;
-        }
-
-        $all_status = [];
-        foreach (self::parseCPU($record->data['cpu-temperature']) as $CPU) {
-            /* @var $CPU Cpu */
-            $status = \App\Status::OK;
-            if ($CPU->value > $CPU->critvalue) {
-                $status = \App\Status::WARNING;
-            }
-            foreach (self::parseCPUtemperature($record->data['cpu-temperature']) as $Core) {
-                if ($Core->number == $CPU->number) {
-                    if ($Core->value > $CPU->critvalue) {
-                        $status = \App\Status::WARNING;
-                    }
-                }
-            }
-            $all_status[] = $status;
-        }
-
-        if (count($all_status) < 1) {
-            return \App\Status::UNKNOWN;
-        }
-
-        return max($all_status);
-    }
-
-    public static function parse(string $string) //cores only
-    {
-        $values = array();
-        preg_match_all(self::REGEXP, $string, $values);
-        $temperatures = array();
-        $count = count($values[1]);
-        for ($i = 0; $i < $count; $i++) {
-            $CPUTemp = new Temperature();
-            $CPUTemp->name = $values[1][$i];
-            $CPUTemp->value = $values[2][$i];
-            $temperatures[] = $CPUTemp;
-        }
-        return $temperatures;
-    }
-
-    public static function parseCPU(string $string) //cpus only
-    {
-        $values = array();
-        preg_match_all(self::REGEXPCPU, $string, $values);
-        $CPUS = array();
-        $count = count($values[1]);
-        for ($i = 0; $i < $count; $i++) {
-            $CPU = new Cpu();
-            $CPU->number = $values[2][$i];
-            $CPU->value = $values[3][$i];
-            $CPU->critvalue = $values[4][$i];
-            $CPUS[] = $CPU;
-        }
-        return $CPUS;
-    }
-    public function parseCPUtemperature(string $string) //cores (to associate with cpus only in report() )
-    {
-        if ($string == null) {
-            return [];
-        }
-
-        $current_cpu = new Cpu();
-        $CPUS=[];
-        $Cores=[];
-        $lines=explode("\n", $string);
+        $cpus = [];
+        $cpu = null;
+        
+        $lines = explode("\n", $string);
         foreach ($lines as $line) {
-            $matchesCPU = array();
-            if (preg_match(self::REGEXPCPU, $line, $matchesCPU) === 1) {
-                $current_cpu = new Cpu();
-                $current_cpu->number = $matchesCPU[2];
-                $CPUS[]=$current_cpu;
+            $match = [];
+            
+            // this line corresponds to a CPU definition
+            if (preg_match(self::REGEXPCPU, $line, $match) === 1) {
+                $cpu = new Cpu($match[2], $match[3], $match[4]);
+                $cpus[] = $cpu;
                 continue;
             }
-            $matchesCore = array();
-            if (preg_match(self::REGEXP, $line, $matchesCore) === 1) {
-                $Core=new Temperature();
-                $Core->name = $matchesCore[1];
-                $Core->corevalue = $matchesCore[2];
-                $Core->number = $current_cpu->number;
-                $Cores[] = $Core;
+            
+            // line correponds to a core definition
+            if (preg_match(self::REGEXPCORE, $line, $match) === 1) {
+                $core = new Core($match[1], $match[2], $match[3]);
+                // append to current CPU
+                $cpu->cores[] = $core;
                 continue;
             }
         }
-        return $Cores;
-    }
-    public function pregMatchOne($pattern, $string)
-    {
-        $matches = array();
-        if (preg_match($pattern, $string, $matches) === 1) {
-            return $matches[1];
-        }
-
-        return false;
+        return $cpus;
     }
 }
diff --git a/app/Sensor/ClientVersion.php b/app/Sensor/ClientVersion.php
index fdf090b2e7d92f87e96d6b78911e7230344b5e74..9137bf1da115823566d5779a61ca149e8039c90a 100644
--- a/app/Sensor/ClientVersion.php
+++ b/app/Sensor/ClientVersion.php
@@ -2,43 +2,51 @@
 
 namespace App\Sensor;
 
-use App\Sensor;
 use App\Jobs\FetchClientManifest;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Check if the latest version of the client is installed.
  *
  * @author tibo
  */
-class ClientVersion extends Sensor
+class ClientVersion implements Sensor
 {
-    public function report(array $records) : string
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        return "<p>Installed version: " . $this->installedVersion($records) . "</p>"
-        . "<p>Latest client version: " . FetchClientManifest::version() . "</p>";
-    }
+        $latest_version = FetchClientManifest::version();
+        $installed_version = $this->installedVersion($records);
+        
+        $report = new Report("Client Version");
+        $report->setHTML(
+            "<p>Installed version: $installed_version</p>" .
+            "<p>Latest client version: $latest_version</p>"
+        );
+        
+        if ($latest_version == null) {
+            $report->setStatus(Status::unknown());
+        } elseif ($installed_version === $latest_version) {
+            $report->setStatus(Status::ok());
+        } else {
+            $report->setStatus(Status::warning());
+        }
 
-    public function installedVersion(array $records)
+        return $report;
+    }
+    
+    public function installedVersion(Collection $records) : string
     {
-        $last_record = end($records);
+        $last_record = $records->last();
         if ($last_record == null) {
             return "none";
         }
 
         return $last_record->data["version"];
     }
-
-    public function status(array $records) : int
-    {
-        $latest_version = FetchClientManifest::version();
-        if ($latest_version == null) {
-            return \App\Status::UNKNOWN;
-        }
-
-        if ($this->installedVersion($records) === $latest_version) {
-            return \App\Status::OK;
-        }
-
-        return \App\Status::WARNING;
-    }
 }
diff --git a/app/Sensor/Core.php b/app/Sensor/Core.php
new file mode 100644
index 0000000000000000000000000000000000000000..10640e58f709c55f65adddfd4fb5d1b29ebf2b33
--- /dev/null
+++ b/app/Sensor/Core.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Sensor;
+
+use App\Status;
+use App\HasStatus;
+
+/**
+ * Description of Temperature (core)
+ *
+ * @author helha
+ */
+
+class Core implements HasStatus
+{
+    public $name = "";      // eg : core 0
+    public $value;          // eg : 42.5
+    public $critvalue;      // eg : 76.0
+    
+    public function __construct(string $name, float $value, float $critvalue)
+    {
+        $this->name = $name;
+        $this->value = $value;
+        $this->critvalue = $critvalue;
+    }
+    
+    public function status() : Status
+    {
+        if ($this->value >= $this->critvalue) {
+            return Status::warning();
+        }
+        
+        return Status::ok();
+    }
+}
diff --git a/app/Sensor/Cpu.php b/app/Sensor/Cpu.php
index 111921ef7e3a5e63267b7b5241f42f55c2a449fe..fbb425f20357bbed82e64d6262f6dcd4a0dfc604 100644
--- a/app/Sensor/Cpu.php
+++ b/app/Sensor/Cpu.php
@@ -2,14 +2,23 @@
 
 namespace App\Sensor;
 
+use App\Status;
+
 /**
  * Description of Cpu
  *
  * @author helha
  */
-class Cpu
+class Cpu extends Core
 {
-    public $number = ""; //eg : 1,2,3,4,...
-    public $value= ""; //eg : 38.0
-    public $critvalue= ""; //eg : 76.0
+
+    public $cores = [];
+
+    public function status() : Status
+    {
+        return max(
+            Status::max($this->cores),
+            parent::status()
+        );
+    }
 }
diff --git a/app/Sensor/Date.php b/app/Sensor/Date.php
index bc78b4f49589c42d92bb7afb1442fdf7054ab6d4..a77c7d9566ceabfe8202ab119d6ff9abef52d455 100644
--- a/app/Sensor/Date.php
+++ b/app/Sensor/Date.php
@@ -2,46 +2,37 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
-use App\Record;
+use App\Sensor;
 use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Description of Reboot
  *
  * @author tibo
  */
-class Date extends Sensor
+class Date implements Sensor
 {
-    public function report(array $records) : string
-    {
-        return "<p>Time drift: " . $this->delta(end($records)) . " seconds</p>";
-    }
-
-    public function status(array $records) : int
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        if (count($records) == 0) {
-            return Status::UNKNOWN;
-        }
+        $report = new Report("Time drift");
+        /** @var \App\Record $last_record */
+        $last_record = $records->last();
         
-        $delta = $this->delta(end($records));
-        if ($delta == null) {
-            return Status::UNKNOWN;
+        if (! isset($last_record->data["date"])) {
+            return $report->setHTML("<p>No data available ...</p>");
         }
-
+        
+        $delta = $last_record->data["date"] - $last_record->time;
+        $report->setHTML("<p>Time drift: $delta seconds</p>");
+        
         if (abs($delta) > 10) {
-            return Status::WARNING;
-        }
-
-        return Status::OK;
-    }
-
-    public function delta(Record $record)
-    {
-        if (! isset($record->data["date"])) {
-            return null;
+            return $report->setStatus(Status::warning());
         }
 
-        return $record->data["date"] - $record->time;
+        return $report->setStatus(Status::ok());
     }
 }
diff --git a/app/Sensor/Disk.php b/app/Sensor/Disk.php
index 2600702ac89b76cec065c7388f58ba60843e0c81..2816fc21f77a0391616cee8c2074f8f72fe8f0d9 100644
--- a/app/Sensor/Disk.php
+++ b/app/Sensor/Disk.php
@@ -2,17 +2,30 @@
 
 namespace App\Sensor;
 
+use App\Status;
+use App\HasStatus;
+
 /**
  * Description of Disk
  *
  * @author tibo
  */
-class Disk
+class Disk implements HasStatus
 {
     public $port = "";
     public $box = 0;
     public $bay = 0;
     public $type = "";
     public $size = "";
-    public $status = "";
+    
+    /**
+     *
+     * @var \App\Status
+     */
+    public $status;
+    
+    public function status() : Status
+    {
+        return $this->status;
+    }
 }
diff --git a/app/Sensor/Disks.php b/app/Sensor/Disks.php
index ccfe11577f36dd42bb91c45204b059a5b5d7db36..81786a3c58d9e8c0e6eacd4073cf69e96afaecd7 100644
--- a/app/Sensor/Disks.php
+++ b/app/Sensor/Disks.php
@@ -2,54 +2,39 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
+use App\Sensor;
+use App\ServerInfo;
+use App\Report;
+use App\Status;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Description of Update
  *
  * @author tibo
  */
-class Disks extends Sensor
+class Disks implements Sensor
 {
 
     const REGEXP = "/\\n([A-z\/0-9:\\-\\.]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)%\s*([A-z\/0-9]+)/";
-
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("Partitions");
+        
+        $record = $records->last();
         if (! isset($record->data['disks'])) {
-            return "<p>No data available...</p>";
+            return $report->setHTML("<p>No data available...</p>");
         }
 
-        $partitions = self::parse($record->data["disks"]);
-        return view("sensor.disks", ["partitions" => $partitions]);
+        $partitions = $this->parse($record->data["disks"]);
+        $report->setHTML(view("sensor.disks", ["partitions" => $partitions]));
+        
+        return $report->setStatus(Status::max($partitions));
     }
 
-    public function status(array $records) : int
-    {
-        $record = end($records);
-        if (! isset($record->data['disks'])) {
-            return \App\Status::UNKNOWN;
-        }
-
-        $all_status = [];
-        foreach (self::parse($record->data["disks"]) as $partition) {
-            /* @var $partition Partition */
-            $status = \App\Status::OK;
-            if ($partition->usedPercent() > 80) {
-                $status = \App\Status::WARNING;
-            } elseif ($partition->usedPercent() > 95) {
-                $status = \App\Status::ERROR;
-            }
-            $all_status[] = $status;
-        }
-
-        return max($all_status);
-    }
-
-    public static $skip_fs = ["none", "tmpfs", "shm", "udev", "overlay", '/dev/loop'];
-
-    public static function parse(string $string) : array
+    public function parse(string $string) : array
     {
         $values = array();
         preg_match_all(self::REGEXP, $string, $values);
@@ -57,7 +42,7 @@ class Disks extends Sensor
         $count = count($values[1]);
         for ($i = 0; $i < $count; $i++) {
             $fs = $values[1][$i];
-            if (self::shouldSkip($fs)) {
+            if ($this->shouldSkip($fs)) {
                 continue;
             }
 
@@ -71,9 +56,9 @@ class Disks extends Sensor
         return $partitions;
     }
 
-    public static function fromRecord($record) : array
+    public function fromRecord($record) : array
     {
-        $partitions = self::parse($record->data["disks"]);
+        $partitions = $this->parse($record->data["disks"]);
         $time = $record->time;
         foreach ($partitions as $partition) {
             $partition->time = $time;
@@ -81,11 +66,13 @@ class Disks extends Sensor
 
         return $partitions;
     }
-
-    public static function shouldSkip(string $fs) : bool
+    
+    const SKIP_FS = ["none", "tmpfs", "shm", "udev", "overlay", '/dev/loop'];
+    
+    public function shouldSkip(string $fs) : bool
     {
-        foreach (self::$skip_fs as $should_skip) {
-            if (self::startsWith($should_skip, $fs)) {
+        foreach (self::SKIP_FS as $should_skip) {
+            if ($this->startsWith($should_skip, $fs)) {
                 return true;
             }
         }
@@ -93,7 +80,7 @@ class Disks extends Sensor
         return false;
     }
 
-    public static function startsWith(string $needle, string $haystack) : bool
+    public function startsWith(string $needle, string $haystack) : bool
     {
         return substr($haystack, 0, strlen($needle)) === $needle;
     }
diff --git a/app/Sensor/Heartbeat.php b/app/Sensor/Heartbeat.php
index bf25216faf96706d4d368d33c7b0369ffb3e755c..3064e6b9fd4e887578fd5b28de3aa2d0427df305 100644
--- a/app/Sensor/Heartbeat.php
+++ b/app/Sensor/Heartbeat.php
@@ -2,51 +2,36 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
+use Carbon\Carbon;
 
 /**
  * Description of Reboot
  *
  * @author tibo
  */
-class Heartbeat extends Sensor
+class Heartbeat implements Sensor
 {
-    //put your code here
-    public function report(array $records) : string
-    {
-        return "<p>Last heartbeat received "
-        . $this->lastRecordTime(end($records))->diffForHumans() . "</p>";
-    }
-
-    /**
-     *
-     * @return \Carbon\Carbon
-     */
-    public function lastRecordTime($record) : \Carbon\Carbon
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        if ($record === null) {
-            return \Carbon\Carbon::createFromTimestamp(0);
-        }
-
-        return \Carbon\Carbon::createFromTimestamp($record->time);
-    }
-
-
-    public function status(array $records) : int
-    {
-        $record = end($records);
-
-        if ($record === null) {
-            $delta = PHP_INT_MAX;
-        } else {
-            $delta = \time() - $record->time;
-        }
-
+        $report = new Report("Heartbeat");
+        
+        $record = $records->last();
+        $report->setHTML("<p>Last heartbeat received "
+            . Carbon::createFromTimestamp($record->time)->diffForHumans() . "</p>");
+        
+        $delta = \time() - $record->time;
         // > 15 minutes
         if ($delta > 900) {
-            return \App\Status::ERROR;
+            return $report->setStatus(Status::error());
         }
-
-        return \App\Status::OK;
+        
+        return $report->setStatus(Status::ok());
     }
 }
diff --git a/app/Sensor/Ifconfig.php b/app/Sensor/Ifconfig.php
index 60b198717ab31cef4e55112f90b067e2e56c478d..65e7c8a3343f2d08148c491d8d5c8d6ee49915d6 100644
--- a/app/Sensor/Ifconfig.php
+++ b/app/Sensor/Ifconfig.php
@@ -2,29 +2,36 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
-use \App\Record;
+use App\Sensor;
+use App\Status;
+use App\Record;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Description of MemInfo
  *
  * @author tibo
  */
-class Ifconfig extends Sensor
+class Ifconfig implements Sensor
 {
-
-    public function report(array $records) : string
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
-        if (! isset($record->data['ifconfig'])) {
-            return "<p>No data available...</p>";
+        $report = new Report("Ifconfig");
+        
+        $last_record = $records->last();
+        if (! isset($last_record->data['ifconfig'])) {
+            return $report->setHTML("<p>No data available...</p>");
         }
 
-        $interfaces = $this->parseIfconfigRecord($record);
-        return view("agent.ifconfig", ["interfaces" => $interfaces]);
+        $interfaces = $this->parseIfconfigRecord($last_record);
+        return $report->setStatus(Status::ok())
+                ->setHTML(view("agent.ifconfig", ["interfaces" => $interfaces]));
     }
 
-    public function points(array $records)
+    public function points(Collection $records)
     {
         // Compute the time ordered list of arrays of interfaces
         $interfaces = [];
@@ -85,11 +92,6 @@ class Ifconfig extends Sensor
         return array_values($dataset);
     }
 
-    public function status(array $records) : int
-    {
-        return \App\Status::OK;
-    }
-
     const IFNAME = '/^(?|(\S+)\s+Link encap:|(\S+): flags)/m';
     const IPV4 = '/^\s+inet (?>addr:)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/m';
     const RXTX = '/^\s+RX bytes:(\d+) .*TX bytes:(\d+)/m';
@@ -114,7 +116,6 @@ class Ifconfig extends Sensor
      */
     public function parseIfconfig(string $string) : array
     {
-
         $allowed_prefixes = ["en", "eth", "wl", "venet"];
 
         if ($string == null) {
diff --git a/app/Sensor/Inodes.php b/app/Sensor/Inodes.php
index 44e3017c5816f101011e331906ea492ea6a47e81..cbc88f7d5776f48cc92463a8c006a2c3ee08cf06 100644
--- a/app/Sensor/Inodes.php
+++ b/app/Sensor/Inodes.php
@@ -2,55 +2,37 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\ServerInfo;
+use App\Report;
+use App\Status;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Description of Update
  *
  * @author tibo
  */
-class Inodes extends \App\Sensor
+class Inodes implements Sensor
 {
 
     const REGEXP = "/\\n([A-z\/0-9:\\-\\.]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)%\s*([A-z\/0-9]+)/";
-
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("Inodes");
+        
+        $record = $records->last();
+        
         if (! isset($record->data['inodes'])) {
-            return "<p>No data available...</p>";
+            return $report->setHTML("<p>No data available...</p>");
         }
 
         $disks = $this->parse($record->data["inodes"]);
-        $return = "<table class='table table-sm'>";
-        $return .= "<tr><th></th><th></th><th>Usage</th></tr>";
-        foreach ($disks as $disk) {
-            $return .= "<tr><td>" . $disk->filesystem . "</td><td>"
-                    . $disk->mounted . "</td><td>" . $disk->usedPercent()
-                    . "%</td></tr>";
-        }
-        $return .= "</table>";
-        return $return;
-    }
-
-    public function status(array $records) : int
-    {
-        $record = end($records);
-        if (! isset($record->data['inodes'])) {
-            return \App\Status::UNKNOWN;
-        }
-
-        $all_status = [];
-        foreach ($this->parse($record->data["inodes"]) as $disk) {
-            /* @var $disk InodesDisk */
-            $status = \App\Status::OK;
-            if ($disk->usedPercent() > 80) {
-                $status = \App\Status::WARNING;
-            } elseif ($disk->usedPercent() > 95) {
-                $status = \App\Status::ERROR;
-            }
-            $all_status[] = $status;
-        }
-
-        return max($all_status);
+        $report->setHTML(view("sensor.inodes", ["disks" => $disks]));
+        
+        return $report->setStatus(Status::max($disks));
     }
 
     public function parse(string $string)
@@ -59,9 +41,13 @@ class Inodes extends \App\Sensor
         preg_match_all(self::REGEXP, $string, $values);
         $disks = array();
         $count = count($values[1]);
+        
+        $disks_sensor = new Disks();
+        
         for ($i = 0; $i < $count; $i++) {
             $fs = $values[1][$i];
-            if (Disks::shouldSkip($fs)) {
+            
+            if ($disks_sensor->shouldSkip($fs)) {
                 continue;
             }
 
diff --git a/app/Sensor/InodesDisk.php b/app/Sensor/InodesDisk.php
index 54d708c4eff46a4e307809dccac68bbedd31abba..e22a5eed2c39ac0f5cfdf88e76756a3ec7f6606e 100644
--- a/app/Sensor/InodesDisk.php
+++ b/app/Sensor/InodesDisk.php
@@ -1,19 +1,16 @@
 <?php
 
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
 namespace App\Sensor;
 
+use App\Status;
+use App\HasStatus;
+
 /**
  * Description of InodesDisk
  *
  * @author tibo
  */
-class InodesDisk
+class InodesDisk implements HasStatus
 {
     public $filesystem = "";
     public $inodes = 0;
@@ -24,4 +21,17 @@ class InodesDisk
     {
         return round(100.0 * $this->used / $this->inodes);
     }
+    
+    public function status() : Status
+    {
+        if ($this->usedPercent() > 95) {
+            return Status::error();
+        }
+        
+        if ($this->usedPercent() > 80) {
+            return Status::warning();
+        }
+        
+        return Status::ok();
+    }
 }
diff --git a/app/Sensor/ListeningPorts.php b/app/Sensor/ListeningPorts.php
index ada94ecc0affa34221a8e8d88c9e46d32ff81bcb..09a859c576b659a4777390e7f4266bc36f4d11c3 100644
--- a/app/Sensor/ListeningPorts.php
+++ b/app/Sensor/ListeningPorts.php
@@ -2,24 +2,32 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Parse the output of netstat to list listening ports.
  *
  * @author tibo
  */
-class ListeningPorts extends \App\Sensor
+class ListeningPorts implements Sensor
 {
 
     const REGEXP = "/(tcp6|tcp|udp6|udp)\s*\d\s*\d\s*(\S*):(\d*).*LISTEN\s*(\S*)/m";
-
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("Listening Ports");
+        $record = $records->last();
 
         // "netstat-listen-tcp" "netstat-listen-udp"
         if (! isset($record->data["netstat-listen-udp"])
                 && ! isset($record->data["netstat-listen-tcp"])) {
-            return "<p>No data available...</p>";
+            return $report->setHTML("<p>No data available...</p>");
         }
 
         $ports = array_merge(
@@ -33,29 +41,9 @@ class ListeningPorts extends \App\Sensor
                     return $port1->port - $port2->port;
             }
         );
-
-        $return = "<table class='table table-sm'>";
-        $return .= "<tr>"
-                . "<th>Port</th>"
-                . "<th>Proto</th>"
-                . "<th>Bind address</th>"
-                . "<th>Process</th>"
-                . "</tr>";
-        foreach ($ports as $port) {
-            $return .= "<tr>"
-                    . "<td>" . $port->port . "</td>"
-                    . "<td>" . $port->proto . "</td>"
-                    . "<td>" . $port->bind . "</td>"
-                    . "<td>" . $port->process . "</td>"
-                    . "</tr>";
-        }
-        $return .= "</table>";
-        return $return;
-    }
-
-    public function status(array $records) : int
-    {
-        return \App\Status::OK;
+        
+        return $report->setStatus(Status::ok())
+                ->setHTML(view("sensor.listeningports", ["ports" => $ports]));
     }
 
     /**
diff --git a/app/Sensor/LoadAvg.php b/app/Sensor/LoadAvg.php
index 04d2303cb70582c38216668c5ee9c56195df8fa2..286e2c6a8a51e94d3512e5d61c59b6c7bf6a3d3a 100644
--- a/app/Sensor/LoadAvg.php
+++ b/app/Sensor/LoadAvg.php
@@ -2,37 +2,52 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
-use \App\Status;
+use App\Record;
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Description of LoadAvg
  *
  * @author tibo
  */
-class LoadAvg extends Sensor
+class LoadAvg implements Sensor
 {
-
-    /**
-     *
-     * @param array<\App\Record> $records
-     * @return string
-     */
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
-        if (! isset($record->data['loadavg'])) {
-            return "<p>No data available...</p>";
+        $threshold = $serverinfo->cpuinfo()["threads"];
+        $report = new Report("Load Average");
+        
+        if (! isset($records->last()->data['loadavg'])) {
+            return $report->setHTML("<p>No data available...</p>");
+        }
+        
+        $current_load = $this->parse($records->last()->data["loadavg"]);
+        $report->setHTML(view("agent.loadavg", ["current_load" => $current_load]));
+        
+        $max_load = $records
+                ->map(function (Record $record) {
+                    $this->parse($record->data["loadavg"]);
+                })
+                ->max();
+        
+        if ($max_load > 2 * $threshold) {
+            return $report->setStatus(Status::error());
         }
-        $current_load = $this->parse($record->data["loadavg"]);
 
-        return view(
-            "agent.loadavg",
-            ["current_load" => $current_load]
-        );
+        if ($max_load > $threshold) {
+            return $report->setStatus(Status::warning());
+        }
+
+        return $report->setStatus(Status::ok());
     }
 
-    public function loadPoints(array $records)
+    public function loadPoints(Collection $records)
     {
         $points = [];
         foreach ($records as $record) {
@@ -44,29 +59,6 @@ class LoadAvg extends Sensor
         return $points;
     }
 
-    public function status(array $records) : int
-    {
-        $threshold = $this->server()->info()->cpuinfo()["threads"];
-        
-        $max = 0;
-        foreach ($records as $record) {
-            $load = $this->parse($record->data["loadavg"]);
-            if ($load > $max) {
-                $max = $load;
-            }
-        }
-        
-        if ($max > 2 * $threshold) {
-            return Status::ERROR;
-        }
-
-        if ($max > $threshold) {
-            return Status::WARNING;
-        }
-
-        return Status::OK;
-    }
-
     public function parse(string $string) : string
     {
         return current(explode(" ", $string));
diff --git a/app/Sensor/MemInfo.php b/app/Sensor/MemInfo.php
index 5ea0f8e5c67149f6cb4e5e4545eca9c725f68309..093eef210a9b43fd5ae1a8d0e6b77e4aa4dcce44 100644
--- a/app/Sensor/MemInfo.php
+++ b/app/Sensor/MemInfo.php
@@ -2,22 +2,37 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Description of MemInfo
  *
  * @author tibo
  */
-class MemInfo extends Sensor
+class MemInfo implements Sensor
 {
-
-    public function report(array $records) : string
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        return view("agent.meminfo", []);
+        $report = new Report("MemInfo");
+        $report->setHTML(view("agent.meminfo"));
+        
+        foreach ($records as $record) {
+            $mem = $this->parseMeminfo($record->data["memory"]);
+            if ($mem->usedRatio() > 0.8) {
+                return $report->setStatus(Status::WARNING);
+            }
+        }
+
+        return $report->setStatus(Status::ok());
     }
 
-    public function usedMemoryPoints(array $records)
+
+    public function usedMemoryPoints(Collection $records)
     {
         $used = [];
         foreach ($records as $record) {
@@ -31,7 +46,7 @@ class MemInfo extends Sensor
         return $used;
     }
 
-    public function cachedMemoryPoints(array $records)
+    public function cachedMemoryPoints(Collection $records)
     {
         $points = [];
         foreach ($records as $record) {
@@ -45,18 +60,6 @@ class MemInfo extends Sensor
         return $points;
     }
 
-    public function status(array $records) : int
-    {
-        foreach ($records as $record) {
-            $mem = $this->parseMeminfo($record->data["memory"]);
-            if ($mem->usedRatio() > 0.8) {
-                return  \App\Status::WARNING;
-            }
-        }
-
-        return \App\Status::OK;
-    }
-
     // used = total - free - cached
     const MEMTOTAL = "/^MemTotal:\\s+([0-9]+) kB$/m";
     const MEMFREE = "/^MemFree:\\s+([0-9]+) kB$/m";
diff --git a/app/Sensor/Netstat.php b/app/Sensor/Netstat.php
index 9c7513b6330bd072388efc994e44b7e21da4e24f..89636c983ef4055cba4cbf2e8d53d9276442e270 100644
--- a/app/Sensor/Netstat.php
+++ b/app/Sensor/Netstat.php
@@ -2,22 +2,33 @@
 
 namespace App\Sensor;
 
-use \App\Sensor;
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
 
 /**
  * Parse netstat
  *
  * @author tibo
  */
-class Netstat extends Sensor
+class Netstat implements Sensor
 {
-
-    public function report(array $records) : string
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        return view("agent.netstat", []);
+        $report = new Report("Netstat : retransmitted TCP segments");
+        $report->setHTML(view("agent.netstat"))
+                ->setStatus(Status::ok());
+        
+        return $report;
     }
 
-    public function points(array $records) : array
+
+
+    public function points(Collection $records) : array
     {
         if (count($records) == 0) {
             return [];
@@ -48,11 +59,6 @@ class Netstat extends Sensor
         return [$dataset];
     }
 
-    public function status(array $records) : int
-    {
-        return \App\Status::OK;
-    }
-
     const TCP_SENT = '/^    (\d+) segments sent out/m';
     const TCP_RETRANSMITTED = '/^    (\d+) segments retransmitted$/m';
 
diff --git a/app/Sensor/Partition.php b/app/Sensor/Partition.php
index 1ea0b5fe9c2a4f19db23c9fd81bd5d1238b4cfe6..19c7385e1c576d3e030c126008c6089e6fc8b641 100644
--- a/app/Sensor/Partition.php
+++ b/app/Sensor/Partition.php
@@ -2,12 +2,15 @@
 
 namespace App\Sensor;
 
+use App\Status;
+use App\HasStatus;
+
 /**
  * Description of Partition
  *
  * @author tibo
  */
-class Partition
+class Partition implements HasStatus
 {
     public $filesystem = "";
     public $blocks = 0;
@@ -34,4 +37,15 @@ class Partition
     {
         return (int) round($this->blocks / 1E6);
     }
+    
+    public function status() : Status
+    {
+        if ($this->usedPercent() > 80) {
+            return Status::warning();
+        } elseif ($this->usedPercent() > 95) {
+            return Status::error();
+        }
+        
+        return Status::ok();
+    }
 }
diff --git a/app/Sensor/PartitionDelta.php b/app/Sensor/PartitionDelta.php
deleted file mode 100644
index 3208498f095f5c7b875773be447d2fbe093570ce..0000000000000000000000000000000000000000
--- a/app/Sensor/PartitionDelta.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-namespace App\Sensor;
-
-use Carbon\Carbon;
-
-/**
- * Represents the time evolution of a single partition.
- */
-class PartitionDelta
-{
-    private $start;
-    private $end;
-
-    public function __construct(Partition $start, Partition $end)
-    {
-        if ($start->filesystem !== $end->filesystem) {
-            throw new \Exception("Comparing different filesystems!");
-        }
-
-        $this->start = $start;
-        $this->end = $end;
-    }
-
-    public function filesystem() : string
-    {
-        return $this->start->filesystem;
-    }
-
-    /**
-     * Return difference of the number of used blocks.
-     * @return int
-     */
-    private function deltaBlocks() : int
-    {
-        return $this->end->used - $this->start->used;
-    }
-
-    /**
-     * Return time difference between 2 partitions
-     * @return int
-     */
-    private function deltaT() : int
-    {
-        return $this->end->time - $this->start->time;
-    }
-
-    /**
-     * Time in second, before this partition gets full.
-     * @return int
-     */
-    public function timeUntillFull() : int
-    {
-        if ($this->deltaBlocks() <= 0) {
-            return PHP_INT_MAX;
-        }
-
-        return ($this->end->blocks - $this->end->used) / $this->deltaBlocks()
-                * $this->deltaT();
-    }
-
-    public function timeUntilFullForHumans() : string
-    {
-        return Carbon::createFromTimeStamp($this->timeUntillFull())->diffForHumans();
-    }
-}
diff --git a/app/Sensor/Perccli.php b/app/Sensor/Perccli.php
index 70a3bf1f78f02e2f50ea44d1780906f65003b490..91dad9c99dff3c91da4bb465eba5485e048b891d 100644
--- a/app/Sensor/Perccli.php
+++ b/app/Sensor/Perccli.php
@@ -2,57 +2,35 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Description of Ssacli
  *
  * @author tibo
  */
-class Perccli extends \App\Sensor
+class Perccli implements Sensor
 {
     const REGEXP = "/(\d+:\d+)\s+\d+\s+(\w+)\s+\d+\s+(.*(GB|TB))\s+\w+\s+(\w+)/";
 
-    public function report(array $records) : string
-    {
-        $record = end($records);
-        if (! isset($record->data['perccli'])) {
-            return "<p>No data available...</p>";
-        }
-
-        $drives = $this->parse($record->data["perccli"]);
-        $return = "<table class='table table-sm'>"
-                . "<tr>"
-                . "<th>Slot</th>"
-                . "<th>Type</th>"
-                . "<th>Size</th>"
-                . "<th>Status</th>"
-                . "</tr>";
-        foreach ($drives as $disk) {
-            $return .= "<tr>"
-                    . "<td>" . $disk->slot . "</td>"
-                    . "<td>" . $disk->type . "</td>"
-                    . "<td>" . $disk->size . "</td>"
-                    . "<td>" . $disk->status . "</td>"
-                    . "</tr>";
-        }
-        $return .= "</table>";
-        return $return;
-    }
-
-    public function status(array $records) : int
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
+        $report = new Report("DELL perccli");
+        
         $record = end($records);
         if (! isset($record->data['perccli'])) {
-            return \App\Status::UNKNOWN;
+            return $report->setHTML("<p>No data available...</p>");
         }
-
+        
         $drives = $this->parse($record->data["perccli"]);
-        foreach ($drives as $disk) {
-            if ($disk->status != "Onln") {
-                return \App\Status::WARNING;
-            }
-        }
-
-        return \App\Status::OK;
+        $report->setHTML(view("sensor.perccli", ["drives" => $drives]));
+        
+        return $report->setStatus(Status::max($drives));
     }
 
     /**
@@ -72,7 +50,7 @@ class Perccli extends \App\Sensor
             $drive->slot = $values[1][$i];
             $drive->type = $values[5][$i];
             $drive->size = $values[3][$i];
-            $drive->status = $values[2][$i];
+            $drive->status = ($values[2][$i] == "Onln") ? Status::ok() : Status::warning();
             $drives[] = $drive;
         }
         return $drives;
diff --git a/app/Sensor/PerccliDrive.php b/app/Sensor/PerccliDrive.php
index 2da7836c015ce3ebb1ac22e6630dbb9612220fd5..2181fb897fccd47a05cb7eac53e95a6ae1d342ee 100644
--- a/app/Sensor/PerccliDrive.php
+++ b/app/Sensor/PerccliDrive.php
@@ -2,15 +2,28 @@
 
 namespace App\Sensor;
 
+use App\Status;
+use App\HasStatus;
+
 /**
  * Represents a single physical drive connected to a Dell RAID controller.
  *
  * @author tibo
  */
-class PerccliDrive
+class PerccliDrive implements HasStatus
 {
     public $slot;
+    
+    /**
+     *
+     * @var \App\Status
+     */
     public $status;
     public $size;
     public $type;
+    
+    public function status() : Status
+    {
+        return $this->status;
+    }
 }
diff --git a/app/Sensor/Reboot.php b/app/Sensor/Reboot.php
index 1053b320e2a13e95a8e490b287e9d9df52dbf5ae..d98a949af769331271297d820ab8f264b7e888db 100644
--- a/app/Sensor/Reboot.php
+++ b/app/Sensor/Reboot.php
@@ -2,51 +2,36 @@
 
 namespace App\Sensor;
 
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Description of Reboot
  *
  * @author tibo
  */
-class Reboot extends \App\Sensor
+class Reboot implements \App\Sensor
 {
-    
-    public function report(array $records) : string
-    {
-        return "<p>Reboot required: "
-            . $this->statusHTML($records)
-            . "</p>";
-    }
-
-    public function statusHTML(array $records)
-    {
-        switch ($this->status($records)) {
-            case \App\Status::OK:
-                return "no";
-
-            case \App\Status::WARNING:
-                return "yes";
-
-            default:
-                return "?";
-        }
-    }
-
-    public function status(array $records) : int
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("Reboot required");
+        
+        $record = $records->last();
+        
         if (! isset($record->data['reboot'])) {
-            return \App\Status::UNKNOWN;
+            return $report->setStatus(Status::unknown())
+                    ->setHTML("<p>No data available!</p>");
         }
 
         if ($record->data["reboot"]) {
-            return \App\Status::WARNING;
+            return $report->setStatus(Status::warning())
+                    ->setHTML("<p>Reboot required: yes</p>");
         }
 
-        return \App\Status::OK;
-    }
-
-    public function name(): string
-    {
-        return "Reboot required";
+        return $report->setStatus(Status::ok())
+                ->setHtml("<p>Reboot required: no</p>");
     }
 }
diff --git a/app/Sensor/Ssacli.php b/app/Sensor/Ssacli.php
index 3c0ea91f82b0e4daabf6b504355c348541745f8d..2760a77f65983ba4dd408902b19de54a1f32661e 100644
--- a/app/Sensor/Ssacli.php
+++ b/app/Sensor/Ssacli.php
@@ -2,61 +2,35 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Description of Ssacli
  *
  * @author tibo
  */
-class Ssacli extends \App\Sensor
+class Ssacli implements Sensor
 {
     const REGEXP = "/\s*physicaldrive .*\(port (.*):box (\d*):bay (\d*), (.*), (.*), (\w*)\)/";
 
-    public function report(array $records) : string
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("HP ssacli");
+        
+        $record = $records->last();
         if (! isset($record->data['ssacli'])) {
-            return "<p>No data available...</p>";
+            return $report->setHTML("<p>No data available...</p>");
         }
-
+        
         $disks = $this->parse($record->data["ssacli"]);
-        $return = "<table class='table table-sm'>"
-                . "<tr>"
-                . "<th>Port</th>"
-                . "<th>Box</th>"
-                . "<th>Bay</th>"
-                . "<th>Type</th>"
-                . "<th>Size</th>"
-                . "<th>Status</th>"
-                . "</tr>";
-        foreach ($disks as $disk) {
-            $return .= "<tr>"
-                    . "<td>" . $disk->port . "</td>"
-                    . "<td>" . $disk->box . "</td>"
-                    . "<td>" . $disk->bay . "</td>"
-                    . "<td>" . $disk->type . "</td>"
-                    . "<td>" . $disk->size . "</td>"
-                    . "<td>" . $disk->status . "</td>"
-                    . "</tr>";
-        }
-        $return .= "</table>";
-        return $return;
-    }
-
-    public function status(array $records) : int
-    {
-        $record = end($records);
-        if (! isset($record->data['ssacli'])) {
-            return \App\Status::UNKNOWN;
-        }
-
-        $disks = $this->parse($record->data["ssacli"]);
-        foreach ($disks as $disk) {
-            if ($disk->status != "OK") {
-                return \App\Status::WARNING;
-            }
-        }
-
-        return \App\Status::OK;
+        $report->setHTML(view("sensor.ssacli", ["disks" => $disks]));
+        
+        return $report->setStatus(Status::max($disks));
     }
 
     /**
@@ -77,7 +51,7 @@ class Ssacli extends \App\Sensor
             $disk->bay = $values[3][$i];
             $disk->type = $values[4][$i];
             $disk->size = $values[5][$i];
-            $disk->status = $values[6][$i];
+            $disk->status = ($values[6][$i] == "OK") ? Status::ok() : Status::warning();
             $disks[] = $disk;
         }
         return $disks;
diff --git a/app/Sensor/Temper.php b/app/Sensor/Temper.php
index 0e93e3db8f092c36f1f18bbd50cb55c798d7cce6..04c9550538d67997740c4cccbedb422a96028ccd 100644
--- a/app/Sensor/Temper.php
+++ b/app/Sensor/Temper.php
@@ -9,16 +9,25 @@ namespace App\Sensor;
  */
 class Temper
 {
-    public $part1= "0a"; //eg : 0a
-    public $part2= "6c"; //eg : 6c
-    public $temp=array();//eg : [26,68]
+    // allows to extract device response
+    // 80 80 09 47 4e 20 00 00
+    const REGEX = "/^80\s80\s([0-9a-fA-F]{2}\s[0-9a-fA-F]{2})/m";
     
-    public function conversion()
+    public function convert(string $string) : float
     {
-        $hexatemp=$this->part1.$this->part2; //eg : 0a6c
-        $decitemp=hexdec($hexatemp); //eg : 2668
-        $this->temp[1]=substr($decitemp, 0, -2); //eg : 26
-        $this->temp[2]=substr($decitemp, -2); //eg : 68
-        return $this->temp;
+        // extract 2 hex values from device response
+        // 09 47
+        $values = [];
+        preg_match(self::REGEX, $string, $values);
+        
+        // remove intermediate white space
+        // 0947
+        $hexatemp = preg_replace("/\s+/", "", $values[1]);
+        
+        // convert to decimal
+        // 2375
+        $decitemp = hexdec($hexatemp);
+        
+        return $decitemp / 100.0;
     }
 }
diff --git a/app/Sensor/Temperature.php b/app/Sensor/Temperature.php
deleted file mode 100644
index 76278e18e84fa84979682ed20ddceb44a87be5f5..0000000000000000000000000000000000000000
--- a/app/Sensor/Temperature.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-namespace App\Sensor;
-
-/**
- * Description of Temperature (core)
- *
- * @author helha
- */
-class Temperature extends Cpu
-{
-    public $name = ""; //eg : core 0
-    public $corevalue= ""; //eg : T° value
-}
diff --git a/app/Sensor/USBtemperature.php b/app/Sensor/USBtemperature.php
index acf6a2f7df2947680af3c1e53b89962f13657c88..3cbcc98bcdd6d2493c9bc6ac125296c098f6630d 100644
--- a/app/Sensor/USBtemperature.php
+++ b/app/Sensor/USBtemperature.php
@@ -2,52 +2,37 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
      * Description of USBTemperature
  *
  * @author helha
  */
-class USBtemperature extends \App\Sensor
+class USBtemperature implements Sensor
 {
-    //get device responce (8 bytes) :
-    const REGEXP = "/^(80 80)\s*([A-z\/0-9]+) \s*([A-z\/0-9]+)/m";
 
-    public function report(array $records) : string
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("USB Temperature");
+        
+        $record = $records->last();
         if (! isset($record->data["TEMPer"])) {
-            return "<p>No data available...</p>"
-                . "<p>Maybe <code>TEMPer</code> is not installed.</p>"
-                . "<p>You can install it following the tutorial on the Gitlab repository</p>";
+            return $report->setHTML("<p>No data available...</p>"
+                . "<p>Maybe <code>TEMPer</code> is not installed? "
+                . "You can install it following the tutorial on the Gitlab repository</p>");
         }
-        $temper = self::parse($record->data['TEMPer']);
-        $return= "<p>Ambient temperature (USB TEMPer) : " . $temper->temp[1] . "." . $temper->temp[2] . " °C " . "</p>";
-        return $return;
-    }
-
-    public function status(array $records) : int
-    {
-        $record = end($records);
-        if (! isset($record->data["TEMPer"])) {
-            return \App\Status::UNKNOWN;
-        }
-        $status = \App\Status::OK;
-        $USBTemp = self::parse($record->data['TEMPer']);
-        if ((int)($USBTemp->temp[1]) > 60) {
-            $status = \App\Status::WARNING;
-        }
-        return $status;
-    }
-
-    public static function parse(string $string)
-    {
-        $values = array();
-        preg_match_all(self::REGEXP, $string, $values); //get 8 bytes response from TEMPerUSB device
-        $USBTemp = new Temper();
-        $USBTemp->part1 = implode($values[2]);
-        $USBTemp->part2 = implode($values[3]);
-        $USBTemp->conversion(); //1st element = integer part, 2th = decimal part
-        $temper=$USBTemp;
-        return $temper;
+        
+        $temper = new Temper();
+        $value = $temper->convert($record->data['TEMPer']);
+        $report->setHTML("<p>Ambient temperature (USB TEMPer) : $value °C " . "</p>");
+        
+        $report->setStatus(Status::ok());
+        return $report;
     }
 }
diff --git a/app/Sensor/Updates.php b/app/Sensor/Updates.php
index 79523ec771c794eecdcc3dd9b51a6c73c3c0cb27..f74d3e8a666f921842d29349da03a35f0e8ffa2d 100644
--- a/app/Sensor/Updates.php
+++ b/app/Sensor/Updates.php
@@ -2,43 +2,44 @@
 
 namespace App\Sensor;
 
+use App\Sensor;
+use App\Status;
+use App\ServerInfo;
+use App\Report;
+
+use Illuminate\Database\Eloquent\Collection;
+
 /**
  * Check if (security) updates are available.
  *
  * @author tibo
  */
-class Updates extends \App\Sensor
+class Updates implements Sensor
 {
 
     const REGEXP = "/(\d+)\spackages? can be updated\.\n(\d+)\supdates? (is a|are) security updates?./";
-
-    public function report(array $records) : string
-    {
-        $record = end($records);
-        if (! isset($record->data['updates'])) {
-            return "<p>No data available...</p>";
-        }
-
-        return "<p>" . nl2br($record->data["updates"]) . "</p>";
-    }
-
-    public function status(array $records) : int
+    
+    public function analyze(Collection $records, ServerInfo $serverinfo): Report
     {
-        $record = end($records);
+        $report = new Report("Updates available");
+        
+        $record = $records->last();
         if (! isset($record->data['updates'])) {
-            return \App\Status::UNKNOWN;
+            return $report->setHTML("<p>No data available...</p>");
         }
 
+        $report->setHTML("<p>" . nl2br($record->data["updates"]) . "</p>");
+        
         $status = $this->parse($record->data["updates"]);
         if ($status == null) {
-            return \App\Status::UNKNOWN;
+            return $report->setStatus(Status::unknown());
         }
 
         if ($status["security"] != 0) {
-            return \App\Status::WARNING;
+            return $report->setStatus(Status::warning());
         }
 
-        return \App\Status::OK;
+        return $report->setStatus(Status::ok());
     }
 
     public function parse($string)
diff --git a/app/SensorWrapper.php b/app/SensorWrapper.php
deleted file mode 100644
index 5238e9bb782d8a11d8aeab08e0f286fab2c6b778..0000000000000000000000000000000000000000
--- a/app/SensorWrapper.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace App;
-
-use Illuminate\Support\Facades\Log;
-
-/**
- * A wrapper around a sensor, used to catch possible exceptions.
- */
-class SensorWrapper
-{
-    private $sensor;
-    private $records;
-
-    private $report;
-    private $status;
-
-    public function __construct(Sensor $sensor, $records)
-    {
-        $this->sensor = $sensor;
-        $this->records = $records;
-    }
-
-    public function id() : string
-    {
-        return \get_class($this->sensor);
-    }
-
-    public function name(): string
-    {
-        return $this->sensor->name();
-    }
-
-    public function report(): string
-    {
-        if (is_null($this->report)) {
-            try {
-                $this->report = $this->sensor->report($this->records);
-            } catch (\Exception $ex) {
-                Log::error('Sensor failed : ' . $ex->getTraceAsString());
-                $this->report = "<p>Sensor " . $this->name() . " failed :-(</p>";
-            }
-        }
-
-        return $this->report;
-    }
-
-    public function status(): Status
-    {
-        if (is_null($this->status)) {
-            try {
-                $this->status = new Status($this->sensor->status($this->records));
-            } catch (\Exception $ex) {
-                Log::error('Sensor failed : ' . $ex->getTraceAsString());
-                $this->status = new Status(Status::UNKNOWN);
-            }
-        }
-
-        return $this->status;
-    }
-}
diff --git a/app/Server.php b/app/Server.php
index b052fd42d3edf9a6a874df36e2172f8479e20c19..508400bb9b612a270fe5bd3c9d29aaf114fc0d3f 100644
--- a/app/Server.php
+++ b/app/Server.php
@@ -3,6 +3,7 @@
 namespace App;
 
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Support\Facades\Log;
 
 /**
@@ -56,7 +57,6 @@ class Server extends Model
         \App\Sensor\Date::class,
         \App\Sensor\ClientVersion::class,
         \App\Sensor\Heartbeat::class,
-        // \App\Sensor\DiskEvolution::class,
         \App\Sensor\CPUtemperature::class,
         \App\Sensor\USBtemperature::class
     ];
@@ -89,11 +89,14 @@ class Server extends Model
     /**
      * Get the last day of data.
      */
-    public function lastRecords1Day() : array
+    public function lastRecords1Day() : Collection
     {
         if ($this->records_1day == null) {
             $start = time() - 24 * 3600;
-            $this->records_1day = $this->records()->where("time", ">", $start)->get()->all();
+            $this->records_1day = $this->records()
+                    ->where("time", ">", $start)
+                    ->orderBy("time")
+                    ->get();
         }
 
         return $this->records_1day;
@@ -119,44 +122,43 @@ class Server extends Model
      */
     public function status() : Status
     {
-        return Status::max($this->statusArray());
-    }
-
-    public function statusArray()
-    {
-        $status_array = [];
-        foreach ($this->getSensors() as $sensor) {
-            $sensor_name = $sensor->id();
-            try {
-                $status_array[$sensor_name] = $sensor->status();
-            } catch (\Exception $ex) {
-                $status_array[$sensor_name] = Status::UNKNOWN;
-                Log::error("Sensor $sensor_name failed : " . $ex->getTraceAsString());
-            }
-        }
-        return $status_array;
+        return Status::max($this->reports());
     }
 
     public function getSensorsNOK()
     {
         $sensorsNOK = [];
-        foreach ($this->getSensors() as $sensor) {
+        foreach ($this->reports() as $sensor) {
             if ($sensor->status()->code() > 0) {
                 $sensorsNOK[] = $sensor;
             }
         }
         return $sensorsNOK;
     }
+    
+    private $reports = null;
 
-    public function getSensors()
+    public function reports()
     {
-        $records = $this->lastRecords1Day();
-
-        $sensors = [];
-        foreach (self::$sensors as $sensor) {
-            $sensors[] = new SensorWrapper(new $sensor($this), $records);
+        if (is_null($this->reports)) {
+            $records = $this->lastRecords1Day();
+            $serverinfo = $this->info();
+
+            $this->reports = [];
+            foreach (self::$sensors as $sensor) {
+                try {
+                     $report = (new $sensor)->analyze($records, $serverinfo);
+                     $this->reports[] = $report;
+                } catch (\Exception $ex) {
+                    Log::error('Sensor failed : ' . $ex->getTraceAsString());
+                    $report = new Report($sensor, Status::unknown());
+                    $report->setHTML("<p>Agent crashed...</p>");
+                    $this->reports[] = $report;
+                }
+            }
         }
-        return $sensors;
+        
+        return $this->reports;
     }
     
     public function changes()
diff --git a/app/Status.php b/app/Status.php
index 428871602171999fcb7fb54cbb2cf01073fe3970..e83c5a1afafd61429ffb3d05bffd795fa8c8d722 100644
--- a/app/Status.php
+++ b/app/Status.php
@@ -19,7 +19,7 @@ class Status
         $this->code = $code;
     }
 
-    public function name() : string
+    public function __toString() : string
     {
         switch ($this->code) {
             case 0:
@@ -52,18 +52,6 @@ class Status
         }
     }
 
-    public static function max(array $statuses) : Status
-    {
-        $max = new Status(self::UNKNOWN);
-        foreach ($statuses as $status) {
-            if ($status->code() > $max->code()) {
-                $max = $status;
-            }
-        }
-
-        return $max;
-    }
-
     public function color() : string
     {
         switch ($this->code) {
@@ -77,4 +65,39 @@ class Status
                 return 'secondary';
         }
     }
+    
+    /**
+     *
+     * @param array<HasStatus> $items
+     * @return Status
+     */
+    public static function max(array $items) : Status
+    {
+        return max(array_map(
+            function (HasStatus $item) {
+                return $item->status();
+            },
+            $items
+        ));
+    }
+    
+    public static function ok() : Status
+    {
+        return new Status(0);
+    }
+    
+    public static function warning() : Status
+    {
+        return new Status(10);
+    }
+    
+    public static function error() : Status
+    {
+        return new Status(20);
+    }
+    
+    public static function unknown() : Status
+    {
+        return new Status(-1);
+    }
 }
diff --git a/resources/views/sensor/cputemperature.blade.php b/resources/views/sensor/cputemperature.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..317c7a63c464c4618c21301f934e2b16c38fef28
--- /dev/null
+++ b/resources/views/sensor/cputemperature.blade.php
@@ -0,0 +1,24 @@
+<table class='table table-sm'>
+    <tr>
+        <th>Name</th>
+        <th class="text-right">Temperature (°C)</th>
+        <th class="text-right">T°crit (°C)</th>
+    </tr>
+
+@foreach ($cpus as $CPU) 
+    <tr>
+        <td><b>CPU {{ $CPU->name }}</b></td>
+        <td class="text-right"><b> {{ $CPU->value }}</b></td>
+        <td class="text-right"><b>{{ $CPU->critvalue }}</b></td>
+    </tr>
+    
+    @foreach ($CPU->cores as $core) 
+    <tr>
+        <td>{{ $core->name }}</td>
+        <td class="text-right">{{ $core->value  }}</td>
+        <td class="text-right">{{ $CPU->critvalue }}</td>
+    </tr>
+    @endforeach
+@endforeach
+
+</table>
\ No newline at end of file
diff --git a/resources/views/sensor/inodes.blade.php b/resources/views/sensor/inodes.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..378bcc59a3e8a7f2f1509dca6e6c35d003ba46fe
--- /dev/null
+++ b/resources/views/sensor/inodes.blade.php
@@ -0,0 +1,15 @@
+<table class='table table-sm'>
+<tr>
+    <th></th>
+    <th></th>
+    <th>Usage</th>
+</tr>
+
+@foreach ($disks as $disk)
+<tr>
+    <td>{{ $disk->filesystem }}</td>
+    <td>{{ $disk->mounted }}</td>
+    <td>{{ $disk->usedPercent() }}%</td>
+</tr>
+@endforeach
+</table>
\ No newline at end of file
diff --git a/resources/views/sensor/listeningports.blade.php b/resources/views/sensor/listeningports.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..d13b589779a871fb9663a084382cf04fe60c9a15
--- /dev/null
+++ b/resources/views/sensor/listeningports.blade.php
@@ -0,0 +1,17 @@
+<table class='table table-sm'>
+<tr>
+    <th>Port</th>
+    <th>Proto</th>
+    <th>Bind address</th>
+    <th>Process</th>
+</tr>
+
+@foreach ($ports as $port) 
+<tr>
+    <td>{{ $port->port }}</td>
+    <td>{{ $port->proto }}</td>
+    <td>{{ $port->bind }}</td>
+    <td>{{ $port->process }}</td>
+</tr>
+@endforeach
+</table>
\ No newline at end of file
diff --git a/resources/views/sensor/perccli.blade.php b/resources/views/sensor/perccli.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..745e4375d573ce5114b89f7be7aba44d77971ceb
--- /dev/null
+++ b/resources/views/sensor/perccli.blade.php
@@ -0,0 +1,18 @@
+<table class='table table-sm'>
+<tr>
+    <th>Slot</th>
+    <th>Type</th>
+    <th>Size</th>
+    <th>Status</th>
+</tr>
+
+@foreach ($drives as $disk)
+<tr>
+    <td>{{ $disk->slot }}</td>
+    <td>{{ $disk->type }}</td>
+    <td>{{ $disk->size }}</td>
+    <td>{{ $disk->status }}</td>
+</tr>
+@endforeach
+
+</table>
\ No newline at end of file
diff --git a/resources/views/sensor/ssacli.blade.php b/resources/views/sensor/ssacli.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..4da321f159667efa3f8bf69e23305768b7f5709a
--- /dev/null
+++ b/resources/views/sensor/ssacli.blade.php
@@ -0,0 +1,22 @@
+<table class='table table-sm'>
+<tr>
+    <th>Port</th>
+    <th>Box</th>
+    <th>Bay</th>
+    <th>Type</th>
+    <th>Size</th>
+    <th>Status</th>
+</tr>
+
+@foreach ($disks as $disk)
+<tr>
+    <td>{{ $disk->port }}</td>
+    <td>{{ $disk->box }}</td>
+    <td>{{ $disk->bay }}</td>
+    <td>{{ $disk->type }}</td>
+    <td>{{ $disk->size }}</td>
+    <td>{{ $disk->status }}</td>
+</tr>
+@endforeach
+
+</table>
\ No newline at end of file
diff --git a/resources/views/server/show.blade.php b/resources/views/server/show.blade.php
index 1f24646383128967b3ed573babbe2e8e11d6b5d6..8b9421858a2d4efa52bfa3f6158859b5ebf1fe52 100644
--- a/resources/views/server/show.blade.php
+++ b/resources/views/server/show.blade.php
@@ -75,7 +75,7 @@ window.monitorServerToken = "{{ $server->read_token }}";
             </h1>
 
             @if ($server->hasData())
-            @foreach ($server->getSensors() as $sensor)
+            @foreach ($server->reports() as $sensor)
             <div class="card">
                 <div class="card-header">
                     {{ $sensor->name() }}
@@ -85,7 +85,7 @@ window.monitorServerToken = "{{ $server->read_token }}";
                     </div>
                 </div>
                 <div class="card-body">
-                    {!! $sensor->report() !!}
+                    {!! $sensor->html() !!}
                 </div>
             </div>
             @endforeach
diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php
index 622c6be8599269c199c5e638d57adfd8817e0c2b..a7463d3f2bfcf13195394e5eb8438a886514e291 100644
--- a/tests/Unit/ExampleTest.php
+++ b/tests/Unit/ExampleTest.php
@@ -6,6 +6,8 @@ use App\User;
 use App\Organization;
 use App\Server;
 use App\Record;
+use App\Status;
+
 use Tests\TestCase;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 
@@ -40,6 +42,20 @@ class ExampleTest extends TestCase
             $user->organizations()->first()->name
         );
     }
+    
+    /**
+     * @group status
+     */
+    public function testStatusComparison()
+    {
+        $warning = Status::warning();
+        $error = Status::error();
+        
+        $this->assertGreaterThan($warning, $error);
+        $this->assertTrue($error > $warning);
+        
+        $this->assertEquals(Status::error(), max($warning, $error));
+    }
 
 
     /**
diff --git a/tests/Unit/SensorsTest.php b/tests/Unit/SensorsTest.php
index 6bfb28114d6cc301bd2bf86d4bacff16ef239139..6012745b63e301be0ccef429cc1a4b691ec8e4ed 100644
--- a/tests/Unit/SensorsTest.php
+++ b/tests/Unit/SensorsTest.php
@@ -3,12 +3,14 @@
 namespace Tests\Unit;
 
 use App\Server;
+use App\Status;
+
 use App\Sensor\Disks;
 use App\Sensor\CPUtemperature;
-use App\Sensor\USBtemperature;
 use App\Sensor\Ifconfig;
 use App\Sensor\Updates;
 use App\Sensor\Netstat;
+use App\Sensor\Temper;
 
 use Tests\TestCase;
 
@@ -26,7 +28,7 @@ class SensorsTest extends TestCase
     public function testIfconfig()
     {
         $string = file_get_contents(__DIR__ . "/ifconfig");
-        $sensor = new Ifconfig(new Server());
+        $sensor = new Ifconfig();
         $interfaces = $sensor->parseIfconfig($string);
         $this->assertEquals(2, count($interfaces));
         $this->assertEquals("enp0s31f6", $interfaces[0]->name);
@@ -44,7 +46,7 @@ class SensorsTest extends TestCase
     public function testIfconfig1804()
     {
         $string = file_get_contents(__DIR__ . "/ifconfig1804");
-        $sensor = new Ifconfig(new Server());
+        $sensor = new Ifconfig();
         $interfaces = $sensor->parseIfconfig($string);
         $this->assertEquals(2, count($interfaces));
         $this->assertEquals("eno1", $interfaces[0]->name);
@@ -60,7 +62,7 @@ class SensorsTest extends TestCase
     public function testDisksSensor()
     {
         $string = file_get_contents(__DIR__ . "/df");
-        $sensor = new Disks(new Server());
+        $sensor = new Disks();
         $disks = $sensor->parse($string);
         $this->assertEquals(2, count($disks));
         $this->assertEquals("/dev/sda1", $disks[0]->filesystem);
@@ -70,7 +72,7 @@ class SensorsTest extends TestCase
     public function testNetstatListening()
     {
         $string = file_get_contents(__DIR__ . "/netstat-tcp");
-        $sensor = new \App\Sensor\ListeningPorts(new Server());
+        $sensor = new \App\Sensor\ListeningPorts();
         $ports = $sensor->parse($string);
         $this->assertEquals(16, count($ports));
         $this->assertEquals("31933/cloud-backup-", $ports[4]->process);
@@ -81,7 +83,7 @@ class SensorsTest extends TestCase
     public function testSsacli()
     {
         $string = file_get_contents(__DIR__ . "/ssacli");
-        $sensor = new \App\Sensor\Ssacli(new Server());
+        $sensor = new \App\Sensor\Ssacli();
         $disks = $sensor->parse($string);
         $this->assertEquals("OK", $disks[0]->status);
     }
@@ -89,16 +91,17 @@ class SensorsTest extends TestCase
     public function testPerccli()
     {
         $string = file_get_contents(__DIR__ . "/perccli");
-        $sensor = new \App\Sensor\Perccli(new Server());
+        $sensor = new \App\Sensor\Perccli();
         $disks = $sensor->parse($string);
-        $this->assertEquals("Onln", $disks[0]->status);
+        
+        $this->assertEquals(Status::ok(), $disks[0]->status);
         $this->assertEquals("SSD", $disks[0]->type);
         $this->assertEquals("446.625 GB", $disks[0]->size);
     }
 
     public function testUpdates()
     {
-        $sensor = new Updates(new Server());
+        $sensor = new Updates();
 
         $string1 = "6 packages can be updated.
 2 updates are security updates.";
@@ -131,11 +134,12 @@ class SensorsTest extends TestCase
     public function testCPUtemp()
     {
         $string = file_get_contents(__DIR__ . "/sensors");
-        $sensor = new CPUtemperature(new Server());
-        $CPUTEMPS = $sensor->parse($string);
-        $this->assertEquals(4, count($CPUTEMPS));
-        $this->assertEquals("Core 3", $CPUTEMPS[3]->name);
-        $this->assertEquals("34.0", $CPUTEMPS[3]->value);
+        $sensor = new CPUtemperature();
+        
+        $cpus = $sensor->parse($string);
+        $this->assertEquals(4, count($cpus[0]->cores));
+        $this->assertEquals("Core 3", $cpus[0]->cores[3]->name);
+        $this->assertEquals("34.0", $cpus[0]->cores[3]->value);
     }
     /**
      * @group USBtemp
@@ -143,23 +147,9 @@ class SensorsTest extends TestCase
     public function testTEMPer()
     {
         $string = file_get_contents(__DIR__ . "/TEMPer");
-        $TEMPer = new USBtemperature(new Server());
-        $USBTemp = $TEMPer->parse($string);
-        $this->assertEquals("09", $USBTemp->part1);
-        $this->assertEquals("47", $USBTemp->part2);
-        $this->assertEquals("23", $USBTemp->temp[1]);
-        $this->assertEquals("75", $USBTemp->temp[2]);
-    }
-    /**
-     * @group multicpu
-     */
-    public function testmultiCPUtemp()
-    {
-        $string = file_get_contents(__DIR__ . "/sensors");
-        $sensor = new CPUtemperature(new Server());
-        $CPUTEMPS = $sensor->parseCPUtemperature($string);
-        $this->assertEquals(4, count($CPUTEMPS));
-        $this->assertEquals("Core 3", $CPUTEMPS[3]->name);
-        $this->assertEquals("34.0", $CPUTEMPS[3]->corevalue);
+        
+        $temper = new Temper();
+        $t = $temper->convert($string);
+        $this->assertEquals(23.75, $t);
     }
 }