This topic provides the script template and a sample script for parsing Thing Specification Language (TSL) data in PHP.

Script template

You can write a data parsing script in PHP based on the following script template.

Note This template applies only to products whose Data Format is Custom.
<? php
/**
 * Converts Alink data to a data format that can be recognized by devices before the data is sent to the devices from IoT Platform.
 * Input parameter: the $jsonObj association array.
 * Output parameter: the $rawData array. Each array element must be an integer within a value range of [0,255]. Array elements cannot be left empty.
 */
function protocolToRawData($jsonObj)
{
    $rawData = array();
    return $rawData;
}

/**
 * Converts custom data of devices to Alink data. This function is called when devices submit data to IoT Platform.
 * Input parameter: the $rawData array. Each element must be an integer.
 * Output parameter: the $jsonObj association array. Each key value must be a string and cannot be a numeric string such as "10". Key values cannot be left empty.
 */
function rawDataToProtocol($rawData)
{
    $jsonObj = array();
    return $jsonObj;
}

/**
 * Converts custom topic data of devices to JSON data. The function is called when devices submit data to IoT Platform.
 * Input parameter: the $topic string that indicates a topic used by devices to submit data.
 * Input parameter: the $rawData array. Each element must be an integer.
 * Output parameter: the $jsonObj association array. Each key value must be a string and cannot be a numeric string such as "10". Key values cannot be left empty.
 */
function transformPayload($topic, $rawData)
{
    $jsonObj = array();
    return $jsonObj;
}

Additional considerations

  • Do not use global variables or static variables. Otherwise, results may be inconsistent.
  • In the script, data is processed by using the two's complement operation. The complement range for values in the range of [-128,127] is [0,255]. For example, the complement of -1 is 255 in decimal.
  • The input parameter of the rawDataToProtocol function is an integer array. The function is used to parse data submitted by devices. Use 0xFF for the bitwise AND operation to retrieve the complement. The returned result is an association array. The key value must contain non-array characters. For example, if a key value is "10", the PHP array retrieves the integer 10.
  • The protocolToRawData function parses downstream data sent by IoT Platform and returns an array. The array must be a common PHP array. Each element must be an integer within a value range of [0,255].
  • The input parameter of the transformPayload function is an integer array. Use 0xFF for the bitwise AND operation to retrieve the complement. The returned result is an association array. The key value must contain non-array characters. For example, if a key value is "10", the PHP array retrieves the integer 10.
  • The PHP runtime environment is significantly strict for exception handling. If an error occurs, an exception is thrown and subsequent code is not executed. To ensure code robustness, you need to capture and process exceptions.

Example

The following script is based on the properties and protocol defined in Example for parsing TSL data.

<? php
/*
Sample data
Submit device data
Input parameters:
    0x0000000001003201
Output result:
    {"method":"thing.event.property.post","id":"1","params":{"prop_int16":50,"prop_bool":1},"version":"1.0"}

Response after property configurations
Input parameters:
    0x0300223344c8
Output result:
    {"code":"200","id":"2241348","version":"1.0"}
*/
function rawDataToProtocol($bytes)
{
    $data = [];
    $length = count($bytes);
    for ($i = 0; $i < $length; $i++) {
        $data[$i] = $bytes[$i] & 0xff;
    }

    $jsonMap = [];
    $fHead = $data[0]; //The command field.
    if ($fHead == 0x00) {
        $jsonMap['method'] = 'thing.event.property.post '; //The topic that is used to submit properties. Data format: ALink JSON.
        jsonMap['version'] = '1.0'; //The version of the protocol. This field is fixed. Data format: ALink JSON.
        $jsonMap['id'] = '' . getInt32($data, 1); //The ID of the request. Data format: ALink JSON.
        $params = [];
        $params['prop_int16'] = getInt16($data, 5); //The value of the prop_int16 property of the product.
        params['prop_bool'] = $data[7]; //The value of the prop_bool property of the product.
        jsonMap['params'] = params; //The params field. Data format: ALink JSON.
    } else if ($fHead == 0x03) {
        jsonMap['version'] = '1.0'; //The version of the protocol. This field is fixed. Data format: ALink JSON.
        $jsonMap['id'] = '' . getInt32($data, 1); //The ID of the request. Data format: ALink JSON.
        $jsonMap['code'] = getInt8($data, 5);
    }

    return $jsonMap;
}

/*
Sample data
Configure properties
Input parameters:
    {"method":"thing.service.property.set","id":"12345","version":"1.0","params":{"prop_int16":333, "prop_bool":1}}
Output result:
    0x013039014d01

Response after data submission
Input data:
    {"method":"thing.event.property.post","id":"12345","version":"1.0","code":200,"data":{}}
Output result:
    0x023039c8
*/
function protocolToRawData($json)
{
    $method = $json['method'];
    $id = $json['id'];
    $version = $json['version'];
    $payloadArray = [];
    if ($method == 'thing.service.property.set ') //Configure properties.
    {
        $params = $json['params'];
        $prop_int16 = $params['prop_int16'];
        $prop_bool = $params['prop_bool'];
        //Raw data is concatenated based on the custom protocol format.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(0x01)));//The command field.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(intval($id)))); //The ID of the request. Data format: ALink JSON.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex($prop_int16))); //The value of the prop_int16 property.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex($prop_bool))); //The value of the prop_bool property.
    } else if ($method == 'thing.event.property.post ') { //The response after data submission.
        $code = $json['code'];
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(0x02))); //The command field.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(intval($id)))); //The ID of the request. Data format: ALink JSON.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex($code)));
    } Else {//Unknown commands. Certain commands are not processed.
        $code = $json['code'];
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(0xff))); //The command field.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex(intval($id)))); //The ID of the request. Data format: ALink JSON.
        $payloadArray = concat($payloadArray, hexStringToByteArray(toHex($code)));
    }
    return $payloadArray;
}

/*
  Sample data
  Custom Topic for reporting data: /user/update
  Input parameters:  
     topic: /{productKey}/{deviceName}/user/update 
     bytes: 0x000000000100320100000000
  Output parameters:
  {
     "prop_float": 0,
     "prop_int16": 50,
     "prop_bool": 1,
     "topic": "/{productKey}/{deviceName}/user/update"
   }
 */
function transformPayload($topic, $bytes)
{
    $data = array();
    $length = count($bytes);
    for ($i = 0; $i < $length; $i++) {
        $data[$i] = $bytes[$i] & 0xff;
    }

    $jsonMap = array();

    if (strpos($topic, '/user/update/error') ! == false) {
        $jsonMap['topic'] = $topic;
        $jsonMap['errorCode'] = getInt8($data, 0);
    } else if (strpos($topic, '/user/update') ! == false) {
        $jsonMap['topic'] = $topic;
        $jsonMap['prop_int16'] = getInt16($data, 5);
        $jsonMap['prop_bool'] = $data[7];
    }

    return $jsonMap;
}

function getInt32($bytes, $index)
{
    $array = array($bytes[$index], $bytes[$index + 1], $bytes[$index + 2], $bytes[$index + 3]);

    return hexdec(byteArrayToHexString($array));
}

function getInt16($bytes, $index)
{
    $array = array($bytes[$index], $bytes[$index + 1]);

    return hexdec(byteArrayToHexString($array));
}

function getInt8($bytes, $index)
{
    $array = array($bytes[$index]);
    return hexdec(byteArrayToHexString($array));
}

function byteArrayToHexString($data)
{
    $hexStr = '';
    for ($i = 0; $i < count($data); $i++) {
        $hexValue = dechex($data[$i]);

        $tempHexStr = strval($hexValue);

        if (strlen($tempHexStr) === 1) {
            $hexStr = $hexStr . '0' . $tempHexStr;
        } else {
            $hexStr = $hexStr . $tempHexStr;
        }
    }

    return $hexStr;
}

function hexStringToByteArray($hex)
{
    $result = array();
    $index = 0;
    for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
        $result[$index++] = hexdec($hex[$i] . $hex[$i + 1]);
    }
    return $result;
}


function concat($array, $data)
{
    return array_merge($array, $data);
}

function toHex($data)
{
    $var = dechex($data);
    $length = strlen($var);
    if ($length % 2 == 1) {
        $var = '0' . $var;
    }
    return $var;
}