<?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) { $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; } 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()){ //Logger::debug("lenght: ".$u->lenght, true); $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; 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 switch($version) { case self::STATIC_VERSION: return StaticSmartData::fromJson($json, $u, $v, $e, $c, $x, $y, $z, $t, $d); case self::MOBILE_VERSION: return MobileSmartData::fromJson($json, $u, $v, $e, $c, $x, $y, $z, $t, $d); default: throw new \Exception("Unsupported SmartData version [{$version}]"); return null; } } public function __toString() { $string = "u={$this->unit}, "; $string .= "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}"; 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, $signature) { parent::__construct(SmartData::MOBILE_VERSION, $u, $v, $e, $c, $x,$y,$z, $t, $dev); $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}}"; } }