<?php
namespace SmartData;
require_once( __DIR__ . '/Exception.php');
require_once( __DIR__ . '/Packer.php');
require_once( __DIR__ . '/Unit.php');
require_once( __DIR__ . '/SmartData.php');
use SmartData\Utility\Pack;
use SmartData\Utility\Unpack;
use SmartData\Exception\{AuthenticationException,BadRequestException,InternalException};
class MultiSmartData
{
public $version;
public $unit;
public $unit_code;
public $value;
public $error;
public $uncertainty;
public $x;
public $y;
public $z;
public $time;
public $dev;
public $gw;
public $blob;
public $type;
public $encoding;
public $workflow;
public $signature;
public $datapoints; // keep to send to workflow, encoded sent to the Cassandra Table.
public function __construct() { }
public static function unpackMultiValue(& $bin)
{
$datapoints = array();
$ver = Unpack::uInt8($bin, true);
$unit_code = Unpack::uInt32($bin, true);
$u = Unit::interpret($unit_code);
$x = Unpack::int32($bin, true);
$y = Unpack::int32($bin, true);
$z = Unpack::int32($bin, true);
$t0 = Unpack::uInt64($bin, true);
$dev = Unpack::uint32($bin, true);
$flags = Unpack::uInt8($bin, true);
$period = 0;
$all_uncert = 0;
if (($flags & 0x01) != 0) {
$period = Unpack::int32($bin, true);
}
if (($flags & 0x02) != 0) {
$uncertainty = Unpack::int32($bin, true);
$all_uncert = 1;
}
if ($period === 0 or $all_uncert === 0) {
$n = 0;
while ($bin) {
if ($period == 0) {
$offset = Unpack::uint32($bin, true);
} else {
$offset = $n * $period;
}
$n = $n + 1;
$v = Unpack::d64($bin, true);
if ( $all_uncert == 1 ) {
$uncert = $uncertainty;
} else {
$uncert = Unpack::uint32($bin, true);
}
$e = ( $uncert & 0xFF000000 ) >> 24;
$c = ( $uncert & 0x00FF0000 ) >> 16;
$t = $t0 + $offset;
$sd = new StaticSmartData( $u, $v, $e, $c, $x, $y, $z, $t, $dev);
array_push($datapoints, $sd);
}
return $datapoints;
} else {
$sd = new MultiSmartData();
$sd->version = $ver;
$sd->unit = $u;
$sd->unit_code = $unit_code;
if ($unit_code == 0x00000001) {
$code = 8; // for digital switches.
} else {
$code = ($unit_code & 0x60000000) >> 28;
}
switch( $code ) {
case 0 : $sd->encoding = 'I32'; break;
case 2 : $sd->encoding = 'I64'; break;
case 4 : $sd->encoding = 'F32'; break;
case 6 : $sd->encoding = 'D64'; break;
}
$sd->x = $x;
$sd->y = $y;
$sd->z = $z;
$sd->time = $t0;
$sd->dev = $dev; // TODO: remove this
$sd->gw = -1;
$sd->error = 0;
$sd->uncertainty = $uncertainty;
$sd->type = 'TTH';
$sd->period = $period;
$cont = 0;
$nbin = '';
while ($bin) {
$v = Unpack::d64($bin, true);
switch ( $code ) {
case 0 : $val = (int) $v; $straux = Pack::int32( $val ); break;
case 2 : $val = (int) $v; $straux = Pack::int64( $val ); break;
case 4 : $val = (float) $v; $straux = Pack::f32( $val ); break;
case 6 : $val = (float) $v; $straux = Pack::d64( $val ); break;
case 8 : $aux = base64_decode( $v );
if ($aux != false) {
$val = ord($aux[0]);
$straux = Pack::uint8( $val );
} else {
$val = (float) $v;
$straux = Pack::d64( $val ); // being pessimistic!
}
break; // for digital switches.
}
$nbin .= $straux;
$cont += 1;
}
$sd->blob = $nbin;
return $sd;
}
return $datapoints;
}
public static function unpackMultiDevice(& $bin)
{
$datapoints = array();
$ver = Unpack::uInt8($bin, true);
$u = Unit::unpack($bin);
$x = Unpack::int32($bin, true);
$y = Unpack::int32($bin, true);
$z = Unpack::int32($bin, true);
$t0 = Unpack::uInt64($bin, true);
while ($bin) {
$offset = Unpack::uint32($bin, true);
$v = Unpack::d64($bin, true);
$dev = Unpack::uint32($bin, true);
$uncert = Unpack::uint32($bin, true);
$e = ( $uncert & 0xFF000000 ) >> 24;
$c = ( $uncert & 0x00FF0000 ) >> 16;
$t = $t0 + $offset;
$sd = new StaticSmartData( $u, $v, $e, $c, $x, $y, $z, $t, $dev);
array_push($datapoints, $sd);
}
return $datapoints;
}
public static function unpackMultiUnit(& $bin)
{
$datapoints = array();
$ver = Unpack::uInt8($bin, true);
$x = Unpack::int32($bin, true);
$y = Unpack::int32($bin, true);
$z = Unpack::int32($bin, true);
$t0 = Unpack::uInt64($bin, true);
while ($bin) {
$u = Unpack::uint32($bin, true);
$set = array();
if (array_key_exists($u, $datapoints)) {
$set = $datapoints[$u];
}
$offset = Unpack::uint32($bin, true);
$v = Unpack::d64($bin, true);
$dev = Unpack::uint32($bin, true);
$uncert = Unpack::uint32($bin, true);
$e = ( $uncert & 0xFF000000 ) >> 24;
$c = ( $uncert & 0x00FF0000 ) >> 16;
$t = $t0 + $offset;
$sd = new StaticSmartData( $u, $v, $e, $c, $x, $y, $z, $t, $dev);
array_push($set, $sd);
$datapoints [ $u ] = $set;
}
return $datapoints;
}
public static function parseJson(\stdClass $json)
{
}
public static function multi_values(\stdClass $json)
{
// echo "Testando... ";
$header = $json->MultiValueSmartData;
$version = $header->version;
if (!(is_numeric($version) && is_int($version+0))){
$version = explode(".", $version);
$version = ($version[0]<<4) + $version[1];
}
$u = Unit::interpret($header->unit);
$x = $header->x;
$y = $header->y;
$z = $header->z;
$t0 = $header->t0;
$dev = $header->dev ?? 0; // TODO: remove this
$type = $header->type ?? 'OLD';
$data = $header->datapoints;
$gw = $header->gateway ?? -1;
$signature = $header->signature ?? 0;
$wf = $header->workflow ?? 0;
$period = 0;
if (isset($header->period)) {
$period = $header->period;
}
$uncertainty = -1;
if (isset($header->uncertainty)) {
$uncertainty = $header->uncertainty;
}
$n = 0;
$smartdatas = array();
if ($type != 'TTH') {
foreach($data as $point) {
$val = $point->value;
if ($period == 0) {
if (!isset($point->offset)) {
throw new BadRequestException("Period not defined in header neither in points (offset)");
}
$offset = $point->offset;
} else {
$offset = $n * $period;
$n = $n + 1;
}
$t = $t0 + $offset;
if (isset($point->uncertainty)) {
$uncert = $point->uncertainty;
} else {
$uncert = 0;
}
$e = ( $uncertainty & 0xFF000000 ) >> 24;
$c = ( $uncertainty & 0x00FF0000 ) >> 16;
if ($version == SmartData::STATIC_VERSION) {
$sd = new StaticSmartData($u, $val, $e, $c, $x, $y, $z, $t, $dev);
} else {
$sd = new MobileSmartData($u, $val, $e, $c, $x, $y, $z, $t, $dev, $gw, $signature);
}
array_push($smartdatas, $sd);
}
return $smartdatas;
} else {
$tam = count($data);
$sd = new MultiSmartData();
$sd->version = $version;
$sd->unit = $u;
$sd->x = $x;
$sd->y = $y;
$sd->z = $z;
$sd->time = $t0;
$sd->dev = $dev; // TODO: remove this
$sd->gw = $gw;
$sd->error = $header->error ?? 0;
$sd->uncertainty = $header->uncertainty ?? 0;
$sd->signature = $header->signature ?? null;
$sd->type = 'TTH';
$sd->period = $period;
$sd->workflow = $wf;
$sd->datapoints = $data;
if ($header->unit == 0x00000001) {
$code = 8; // for digital switches.
} else {
$code = ($header->unit & 0x60000000) >> 28;
}
switch( $code ) {
case 0 : $sd->encoding = 'I32'; break;
case 2 : $sd->encoding = 'I64'; break;
case 4 : $sd->encoding = 'F32'; break;
case 6 : $sd->encoding = 'D64'; break;
case 8 : $sd->encoding = 'I8'; break; // for digital switches.
}
$bin = '';
foreach($data as $point) {
switch ( $code ) {
case 0 : $val = (int) $point->value; $straux = Pack::int32( $val ); break;
case 2 : $val = (int) $point->value; $straux = Pack::int64( $val ); break;
case 4 : $val = (float) $point->value; $straux = Pack::f32( $val ); break;
case 6 : $val = (float) $point->value; $straux = Pack::d64( $val ); break;
case 8 : $aux = base64_decode( $point->value );
if ($aux != false) {
$val = ord($aux[0]);
$straux = Pack::uint8( $val );
} else {
$val = (float) $point->value;
$straux = Pack::d64( $val ); // being pessimistic!
}
break; // for digital switches.
}
$bin .= $straux;
}
$sd->blob = $bin;
return $sd;
}
return $smartdatas;
}
public static function multi_devices(\stdClass $json)
{
$header = $json->MultiDeviceSmartData;
$version = $header->version;
if (!(is_numeric($version) && is_int($version+0))) {
$version = explode(".", $version);
$version = ($version[0]<<4) + $version[1];
}
$u = Unit::interpret($header->unit);
$x = $header->x;
$y = $header->y;
$z = $header->z;
$t0 = $header->t0;
$gw = $header->gateway ?? -1;
$signature = $header->signature ?? 0;
$data = $header->datapoints;
$smartdatas = array();
foreach($data as $point) {
$val = $point->value;
$offset = $point->offset;
$t = $t0 + $offset;
$uncertainty = $point->uncertainty;
$e = ( $uncertainty & 0xFF000000 ) >> 24;
$c = ( $uncertainty & 0x00FF0000 ) >> 16;
$dev = $point->dev;
if ($version == SmartData::STATIC_VERSION) {
$sd = new StaticSmartData($u, $val, $e, $c, $x, $y, $z, $t, $dev);
} else {
$sd = new MobileSmartData($u, $val, $e, $c, $x, $y, $z, $t, $dev, $gw, $signature);
}
array_push($smartdatas, $sd);
}
return $smartdatas;
}
// returns a map, with each unit refering to a list of all datapoints of this unit.
public static function multi_units(\stdClass $json)
{
$header = $json->MultiUnitSmartData;
$version = $header->version;
if(is_numeric($version) && is_int($version+0)){
// nothing
} else {
$version = explode(".", $version);
$version = ($version[0]<<4) + $version[1];
}
$x = $header->x;
$y = $header->y;
$z = $header->z;
$t0 = $header->t0;
$data = $header->datapoints;
$smartdatas = array();
foreach($data as $point) {
$u = $point->unit;
$set = array();
if (array_key_exists($u, $smartdatas)) {
$set = $smartdatas[$u];
}
$val = $point->value;
$offset = $point->offset;
$t = $t0 + $offset;
$uncertainty = $point->uncertainty;
$e = ( $uncertainty & 0xFF000000 ) >> 24;
$c = ( $uncertainty & 0x00FF0000 ) >> 16;
$dev = $point->dev;
$sd = new StaticSmartData($u, $val, $e, $c, $x, $y, $z, $t, $dev);
array_push($set, $sd);
$smartdatas[ $u ] = $set;
}
return $smartdatas;
}
public function toArray()
{
$header['version'] = $this->version;
$header['unit'] = $this->unit->cod;
$header['x'] = $this->x;
$header['y'] = $this->y;
$header['z'] = $this->z;
$header['t0'] = $this->time;
$header['dev'] = $this->dev;
$header['type'] = $this->type ?? 'OLD';
if( $this->period ?? false) {
$header['period'] = $this->period;
}
if ($this->uncertainty ?? false) {
$header['uncertainty'] = $this->uncertainty;
}
$header['workflow'] = $this->workflow ?? 0;
$header['gateway'] = $this->gw ?? -1;
if ($this->signature ?? false) {
$header['signature'] = $this->signature;
}
$header['datapoints'] = $this->datapoints;
$mv = array("MultiValueSmartData" => $header);
return array("series" => $mv);
}
public function toJson()
{
$json = json_encode($this->toArray());
//$json = preg_replace('/:"([0-9]*)"/',':$1',$json);
//$json = preg_replace('/\"t0\":\"/', "\"t0\":", $json);
//$json = preg_replace('/\"t1\":\"/', "\"t1\":", $json);
return $json;
}
}