<?php
namespace SmartData;
require_once( __DIR__ . '/Exception.php');
require_once( __DIR__ . '/Packer.php');
require_once( __DIR__ . '/Unit.php');
use SmartData\Utility\Pack;
use SmartData\Utility\Unpack;
abstract class SmartData
{
const STATIC_VERSION = (1<<4)+(1<<0);
const MOBILE_VERSION = (1<<4)+(2<<0);
public $version;
private $unit;
public $value;
public $error;
public $confidence;
public $x;
public $y;
public $z;
public $time;
public $dev;
public $gw; //TODO
public function __construct($version, $u, $v, $e, $c, $x,$y,$z, $t, $dev, $gw = -1)
{
$this->version = $version;
$this->unit = ($u instanceof Unit) ? $u : Unit::interpret($u);
$this->value = $v;
$this->error = $e;
$this->confidence = $c;
$this->x = $x;
$this->y = $y;
$this->z = $z;
$this->time = $t;
$this->dev = $dev;
$this->gw = $gw;
}
public function unit()
{
return $this->unit;
}
//public function put()
//{
// return API::put($this->pack());
//}
public function pack(array $suppress = array())
{
$bin = '';
if(!in_array("version", $suppress))
$bin .= Pack::uInt8($this->version);
if(!in_array("unit", $suppress))
$bin .= Pack::uInt32($this->unit->cod);
if(!in_array("value", $suppress)){
if($this->unit()->is_digital())
$bin .= Pack::d64($this->value); //TODO
else
$bin .= Pack::d64($this->value);
}
if(!in_array("error", $suppress))
$bin .= Pack::uInt8($this->error);
if(!in_array("confidence", $suppress))
$bin .= Pack::uInt8($this->confidence);
if(!in_array("x", $suppress))
$bin .= Pack::int32($this->x);
if(!in_array("y", $suppress))
$bin .= Pack::int32($this->y);
if(!in_array("z", $suppress))
$bin .= Pack::int32($this->z);
if(!in_array("t", $suppress))
$bin .= Pack::uInt64($this->time);
if(!in_array("dev", $suppress))
$bin .= Pack::uint32($this->dev);
return $bin;
}
public static function unpack(& $bin, array $compl = array())
{
$ver = $compl['version'] ?? Unpack::uInt8($bin, true);
if(array_key_exists('unit', $compl))
$u = Unit::interpret($compl['unit']);
else
$u = Unit::unpack($bin);
if(array_key_exists('value', $compl)) {
$v = $compl['value'];
} else {
if($u->is_digital()){
$v = substr($bin, 0, $u->lenght);
$bin = substr($bin, $u->lenght);
//$v = Unpack::d64($bin, true); // TODO
}else
$v = Unpack::d64($bin, true); //value
}
$e = $compl['error'] ?? Unpack::uInt8($bin, true);
$c = $compl['confidence'] ?? Unpack::uInt8($bin, true);
$x = $compl['x'] ?? Unpack::int32($bin, true);
$y = $compl['y'] ?? Unpack::int32($bin, true);
$z = $compl['z'] ?? Unpack::int32($bin, true);
$t = $compl['t'] ?? Unpack::uInt64($bin, true);
if($t<0)
$t = PHP_INT_MAX;
$d = $compl['dev'] ?? Unpack::uint32($bin, true);
switch($ver) {
case self::STATIC_VERSION:
return StaticSmartData::unpack($bin, $compl, $u, $v, $e, $c, $x, $y, $z, $t, $d);
case self::MOBILE_VERSION:
return MobileSmartData::unpack($bin, $compl, $u, $v, $e, $c, $x, $y, $z, $t, $d);
default:
throw new \Exception("Unsupported SmartData version [{$ver}]");
return null;
}
}
public function __get($property)
{
if (property_exists($this, $property)) {
switch ($property) {
case 'unit':
if($this->unit instanceof Unit)
return $this->unit->cod;
else
return $this->unit;
default:
return $this->$property;
}
}
}
public function toArray()
{
$json = array();
$ver_human = ($this->version>>4).'.'.($this->version&0x01);
$json['version'] = $this->version;
$json['unit'] = $this->unit->cod;
$json['timestamp'] = $this->time;
$json['value'] = $this->value;
$json['error'] = $this->error;
$json['confidence'] = $this->confidence;
$json['x'] = $this->x;
$json['y'] = $this->y;
$json['z'] = $this->z;
$json['dev'] = $this->dev;
$json['gateway'] = $this->gw;
$json['type'] = $this->type ?? 'OLD';
$json['period'] = $this->period ?? 0;
return $json;
}
public function toJson()
{
$json = json_encode( $this->toArray() );
$json = preg_replace('/:"([0-9]*)"/',':$1',$json);
return $json;
}
public static function fromJson(\stdClass $json)
{
$version = $json->version;
if(is_numeric($version) && is_int($version+0)){
// nothing
} else {
$version = explode(".", $version);
$version = ($version[0]<<4) + $version[1];
}
$u = Unit::interpret($json->unit);
if($u->is_digital()) {
$v = base64_decode($json->value);
} else {
$v = $json->value;
}
$e = $json->error;
$c = $json->confidence;
$x = $json->x;
$y = $json->y;
$z = $json->z;
$t = $json->t ?? $json->time ?? $json->timestamp; // TODO: remove this
$d = $json->dev ??0; // TODO: remove this
$gw = $json->gateway ?? -1;
$sig = $json->signature ?? null;
switch($version) {
case self::STATIC_VERSION:
return StaticSmartData::fromJson($json, $u, $v, $e, $c, $x, $y, $z, $t, $d, $gw);
case self::MOBILE_VERSION:
return MobileSmartData::fromJson($json, $u, $v, $e, $c, $x, $y, $z, $t, $d, $gw, $sig);
default:
throw new \Exception("Unsupported SmartData version [{$version}]");
return null;
}
}
public function __toString()
{
$string = "u={$this->unit}, ";
if ($this->unit->is_digital()){
$string .= "v={<digital data>}, ";
} else {
$string .= "v={<SI value>}, "; // "v={$this->value}, ";
}
$string .= "e={$this->error}, ";
$string .= "c={$this->confidence}, ";
$string .= "x={$this->x}, ";
$string .= "y={$this->y}, ";
$string .= "z={$this->z}, ";
$string .= "t={$this->time}, ";
$string .= "d={$this->dev}, ";
$string .= "gw={$this->gw}";
return $string;
}
}
class StaticSmartData extends SmartData {
public function __construct($u, $v, $e, $c, $x,$y,$z, $t, $dev)
{
parent::__construct(SmartData::STATIC_VERSION, $u, $v, $e, $c, $x,$y,$z, $t, $dev);
}
public function pack(array $suppress = array())
{
return parent::pack($suppress);
}
public static function unpack(& $bin, array $compl = array(), ...$fields)
{
return new self(...$fields);
}
public static function fromJson(\stdClass $json, ...$fields)
{
return new self(...$fields);
}
public function __toString() {
return '{S, '.(string)parent::__toString().'}';
}
}
class MobileSmartData extends SmartData
{
public $signature;
public function __construct($u, $v, $e, $c, $x,$y,$z, $t, $dev, $gw = -1, $signature = 0)
{
parent::__construct(SmartData::MOBILE_VERSION, $u, $v, $e, $c, $x,$y,$z, $t, $dev, $gw);
$this->signature = $signature;
}
public function pack(array $suppress = array())
{
$bin = parent::pack($suppress);
if(!in_array("signature", $suppress))
$bin .= Pack::uInt64($this->signature);
return $bin;
}
public static function unpack(& $bin, array $compl = array(), ...$fields)
{
$s = $compl['signature'] ?? Unpack::uInt64($bin, true);
array_push($fields, $s);
return new self(...$fields);
}
public static function fromJson(\stdClass $json, ...$fields)
{
array_push($fields, $json->signature);
return new self(...$fields);
}
public function __toString()
{
return '{M, '.(string)parent::__toString().", sig={$this->signature}}";
}
public function toArray()
{
$json = parent::toArray();
$json['signature'] = $this->signature;
return $json;
}
}