PHP Parsing ELA Temperature Sensor raw data - php

I have successfully converted the positive temperature data from below raw data
array (
'timestamp' => '2020-06-11T11:09:21.335Z',
'type' => 'Unknown',
'mac' => 'F64BB46181EF',
'bleName' => 'P RHT 900350',
'rssi' => -63,
'rawData' => '02010605166E2AC90A04166F2A240D09502052485420393030333530',
)
$cutdata = str_split($rawData,2);
$humidity_cut = hexdec($cutdata[13]);
$x_cut = $cutdata[8].$cutdata[7]; //gives 0AC9
$c_cut = hexdec($x_cut);
$temp_cut = $c_cut/100;
echo $temp_cut;exit;
But when i am getting negative temperature values it giving me issues it increase the temp value more then 600
Here is the negative Temp Raw Data
array (
'timestamp' => '2020-07-03T10:05:53.049Z',
'type' => 'Unknown',
'mac' => 'EDF2F589DCAE',
'bleName' => 'P RHT 900351',
'rssi' => -79,
'rawData' => '02010605166E2AB4FA04166F2A310D09502052485420393030333531',
)
I have asked the support team they said
You have to do a 2 complement, which is reversing all the bits, and add 1 in binary.

I'm assuming that the output is OK, but for a 32 bit number, this code checks if the high bit is set (using & 32768) and if it is, it xors the number with 65535 (all 16 bits set) to invert it and then just adds 1 (the result is then made a -ve number)...
if ( $c_cut & 32768 ) {
$c_cut = -(($c_cut ^ 65535)+1);
}
which gives -13.56 as the result.

Related

Is this normal behaviour in php arrays? Array size get shortened when using numbered indexes out of order

So I'm learning Php, so as I was messing around with arrays to see how they work, I stumbled into this when I made two arrays.
$TestArray1 = array( 1 => 1, "string" => "string", 24, "other", 2 => 6, 8);
$TestArray2 = array( 6 => 1, "string" => "string", 24, "other", 1 => 6, 8);
But when I print them out with print_r() this is what I get (this also happens with var_dump by the way)
Array ( [1] => 1 [string] => string [2] => 6 [3] => other [4] => 8 )
Array ( [6] => 1 [string] => string [7] => 24 [8] => other [1] => 6 [9] => 8 )
As far as I can tell, by putting the two in the second array it overwrites the next possible spot with no key and then keeps going, shortening the array. So I thought that meant that if I use a 1 it would put it at the start but that does not happen either.
Is this normal or is there something wrong with my php installation?
Im using Ampps in windows 10 with php 7.3.
Thanks in advance
Good question.
What's happening is that when determining automatic numeric indexes, PHP will look to the largest numeric index added and increment it (or use 0 if there are none).
The key is optional. If it is not specified, PHP will use the increment of the largest previously used integer key.
What's happening with your first array is that as it is evaluated left-to-right, 24 is inserted at index 2 because the last numeric index was 1 => 1.
Then when it gets to 2 => 6, it overwrites the previous value at index 2. This is why 24 is missing from your first array.
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.
Here's a breakdown
$TestArray1 = [1 => 6]; // Array( [1] => 6 )
// no index, so use last numeric + 1
$TestArray1[] = 24; // Array( [1] => 6, [2] => 24 )
$TestArray1[2] = 6; // Array( [1] => 6, [2] => 6 )
When you manually add numeric indexes that are lower than previous ones (ie $TestArray2), they will be added as provided but their position will be later.
This is because PHP arrays are really maps that just pretend to be indexed arrays sometimes, depending on what's in them.
References are from the PHP manual page for Arrays

Sort a multi-dimensional array on two subarray values

I would like to sort an array on eta ASC then ab ASC.
Here's the input array:
$res_ubr=array(
"0"=>array(
"ab"=>"jdfd",
"bb"=>"iweuiru",
"eta"=>4
),
"1"=>array(
"ab"=>"dsdjdfd",
"bb"=>"iuiru",
"eta"=>5
),
"2"=>array(
"ab"=>"jdgfd",
"bb"=>"edfguiru",
"eta"=>2
),
"3"=>array(
"ab"=>"err",
"bb"=>"iuierru",
"eta"=>2
),
"4"=>array(
"ab"=>"fdfdf",
"bb"=>"dfdf",
"eta"=>3
)
);
Here is my expected result:
[
['ab'=>'err', 'bb'=>'iuierru', 'eta'=>2],
['ab'=>'jdgfd', 'bb'=>'edfguiru', 'eta'=>2],
['ab'=>'fdfdf', 'bb'=>'dfdf', 'eta'=>3],
['ab'=>'jdfd', 'bb'=>'iweuiru', 'eta'=>4],
['ab'=>'dsdjdfd', 'bb'=>'iuiru', 'eta'=>5]
]
This is what I've tried:
$res2=$res_ubr;
$temp=array();
foreach($res_ubr as $key=>$val){
foreach($res2 as $k=>$v){
if($val['eta']>$v['eta']){
$temp[]=$res_ubr[$key];
$res_ubr[$key] =$res_ubr[$k];
$res_ubr[$k]=$temp[];
}
}
}
print_r($res_ubr);
For context, the eta value is the time in minutes that the cab is expected to arrive.
You only need to assign a unique temporary key. There are two eta's with a value of 2 in your input array, so you will need to provide a "tie breaker". I am using the ab value to dictate the sorting order when two duplicate etas exist. I'm arbitrarily padding the eta values to an 8 digit number to ensure that numeric sorting occurs as intended. Without left padding with zeros, 10 would come before 2 because the temporary keys will be sorted as strings (one character at a time from left to right) and 1 comes before 2.
foreach($res_ubr as $sub){
$result[str_pad($sub["eta"],8,'0',STR_PAD_LEFT).$sub["ab"]]=$sub;
}
ksort($result);
var_export(array_values($result));
Because you say the eta are taxi arrival times, I'd bet your business that no eta is going to be in the tens of millions of minutes, so you can reduce the padding amount from 8 down to what ever is reasonably expected.
Keep in mind that if there is ever a duplicate temporary key (a matching pair of eta & ab), then my method will overwrite the first element with the second and you will have missing data. If this is a remote possibility, you should also append bb to the temporary key. If this, again, at risk of being a duplicate, you should add a randomly generated string of numbers to prevent your data being erased.
Output with eta ASC, ab ASC:
array (
0 =>
array (
'ab' => 'err',
'bb' => 'iuierru',
'eta' => 2,
),
1 =>
array (
'ab' => 'jdgfd',
'bb' => 'edfguiru',
'eta' => 2,
),
2 =>
array (
'ab' => 'fdfdf',
'bb' => 'dfdf',
'eta' => 3,
),
3 =>
array (
'ab' => 'jdfd',
'bb' => 'iweuiru',
'eta' => 4,
),
4 =>
array (
'ab' => 'dsdjdfd',
'bb' => 'iuiru',
'eta' => 5,
),
)

PHP-RRD Wasn't Work

I am trying to create rrd graph by php5-rrd libraires.
I am trying to draw (LASTHOUR,LASTDAY,LASTWEEK,LASTMONTH) graphs. but not work well, (maybe my RRA settings are missing). i try to use "rrd_update" function. but doesn't work. so try to use "rrd_fetch" function. but all data appear on -NaN.
This is my console log.
1426322479:6249:1817
Array
(
[start] => 1426318800
[end] => 1426322700
[step] => 300
[data] => Array
(
[Users] => Array
(
[1426319100] => NAN
[1426319400] => NAN
[1426319700] => NAN
[1426320000] => NAN
[1426320300] => NAN
[1426320600] => NAN
[1426320900] => NAN
[1426321200] => NAN
[1426321500] => NAN
[1426321800] => NAN
[1426322100] => NAN
[1426322400] => NAN
[1426322700] => NAN
)
[Games] => Array
(
[1426319100] => NAN
[1426319400] => NAN
[1426319700] => NAN
[1426320000] => NAN
[1426320300] => NAN
[1426320600] => NAN
[1426320900] => NAN
[1426321200] => NAN
[1426321500] => NAN
[1426321800] => NAN
[1426322100] => NAN
[1426322400] => NAN
[1426322700] => NAN
)
)
)
This is my PHP Code
$rrdFile = dirname(__FILE__) . "/speed.rrd";
//create rrd file
rrd_create($rrdFile,
array(
"DS:Users:GAUGE:600:0:U",
"DS:Games:GAUGE:600:0:U",
"RRA:AVERAGE:0.5:1:1440",
"RRA:AVERAGE:0.5:5:1440",
"RRA:AVERAGE:0.5:30:800",
"RRA:AVERAGE:0.5:120:800",
"RRA:AVERAGE:0.5:1440:80"
)
);
//update rrd file
if(!(rrd_update($rrdFile,
array(
"N:".rand(0,9999).":".rand(0,9999)
)
))) {
$err = rrd_error();
echo "rrd_update() ERROR: $err\n";
}
// TEST CODE
$result = rrd_fetch( $rrdFile, array( "AVERAGE", "--resolution", "100", "--start", "-1h", "--end", "start+1h" ) );
print_r($result);
//graph output
if(!is_array(rrd_graph(dirname(__FILE__) . "/speed.png",
array(
"--start", "-1h",
"--title", "Status",
"--vertical-label", "Users & Games",
"--width", "600",
"--height", "200",
"DEF:Users=$rrdFile:Users:AVERAGE",
"DEF:Games=$rrdFile:Games:AVERAGE",
"CDEF:cUsers=Users",
"CDEF:cGames=Games",
"LINE:cUsers#FF0000",
"LINE:cGames#00FF00"
)
))) {
$err = rrd_error();
echo "rrd_graph() ERROR: $err\n";
}
You do not have enough sample data, hence your graph and RRAs are empty.
Your graph is set to graph the last 1 hour; since you have the default interval (5min) this means only 12 samples from the highest-resolution RRA.
However, you don't have any data being put in! You only call rrd_update once, with a timestamp of 'now', and this is insufficient to fill even one RRA entry (you will need at least two samples, with a 5min time separation, to completely fill an RRA entry).
If you wish to generate some test data, start with a timestamp 3600 seconds in the past, and add 12 samples, increasing the timestamp by 300 each iteration. This will result in 11 entries in your primary (5-minute) RRA, and maybe 2 in your secondary 25-minute RRA.

Using unpack() to convert to a byte array in PHP

I'm trying to convert a binary string to a byte array of a specific format.
Sample binary data:
ê≤ÚEZêK
The hex version of the binary string looks like this:
00151b000000000190b2f20304455a000003900000004b0000
The Python script uses struct package and unpacks the above string (in binary) using this code:
data = unpack(">hBiiiiih",binarydata)
The desired byte array looks like this. This is also the output of the data array is:
(21, 27, 0, 26260210, 50611546, 912, 75, 0)
How can I unpack the same binary string using PHP's unpack() function and get the same output? That is, what's the >hBiiiiih equivalent in PHP?
So far my PHP code
$hex = "00151b000000000190b2f20304455a000003900000004b0000";
$bin = pack("H*",$hex);
print_r(unpack("x/c*"));
Which gives:
Array ( [*1] => 21 [*2] => 27 [*3] => 0 [*4] => 0 [*5] => 0 [*6] => 0 [*7] => 1 [*8] => -112 [*9] => -78 [*10] => -14 [*11] => 3 [*12] => 4 [*13] => 69 [*14] => 90 [*15] => 0 [*16] => 0 [*17] => 3 [*18] => -112 [*19] => 0 [*20] => 0 [*21] => 0 [*22] => 75 [*23] => 0 [*24] => 0 )
Would also appreciate links to a PHP tutorial on working with pack/unpack.
This produces the same result as does Python, but it treats signed values as unsigned because unpack() does not have format codes for signed values with endianness. Also note that the integers are converted using long, but this is OK because both have the same size.
$hex = "00151b000000000190b2f20304455a000003900000004b0000";
$bin = pack("H*", $hex);
$x = unpack("nbe_unsigned_1/Cunsigned_char/N5be_unsigned_long/nbe_unsigned_2", $bin);
print_r($x);
Array
(
[be_unsigned_1] => 21
[unsigned_char] => 27
[be_unsigned_long1] => 0
[be_unsigned_long2] => 26260210
[be_unsigned_long3] => 50611546
[be_unsigned_long4] => 912
[be_unsigned_long5] => 75
[be_unsigned_2] => 0
)
Because this data is treated as unsigned, you will need to detect whether the original data was negative, which can be done for 2 byte shorts with something similar to this:
if $x["be_unsigned_1"] >= pow(2, 15)
$x["be_unsigned_1"] = $x["be_unsigned_1"] - pow(2, 16);
and for longs using
if $x["be_unsigned_long2"] >= pow(2, 31)
$x["be_unsigned_long2"] = $x["be_unsigned_long2"] - pow(2, 32);

Get timestamp from base64Binary in PHP

A webservice returns a timestamp field in base64Binary format. It looks like this in SOAP response:
<a:TimeStamp>AAAAAAMpI9Q=</a:TimeStamp>
PHP __soapCall, however, b64_decode()s that and I get a binary string looking like ')#▒'. How do I get actual timestamp out of this? I tried to unpack('L') it but it gives me Array([1] => 0) as a result. Is there really zero i.e. 1970-01-01 or have I missed something?
This test program:
$b = "AAAAAAMpI9Q=";
$ts = base64_decode($b);
print_r(array_map("ord", str_split($ts)));
outputs:
Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 3
[5] => 41
[6] => 35
[7] => 212
)
showing that the base64-encoded string gives you an 8-character string when unpacked. So presumably it represents a 64-bit integer, which might be signed or unsigned, and no, it isn't zero.
Given the values above it looks like the value is 53027796 - is that what you're expecting?

Categories