<?php
$response = [];
$response['context'] = "poi3dSensorQuery";

function generateSasToken($resourceUri, $key, $policyName, $expiryInSeconds = 3600) {
  $expiry = time() + $expiryInSeconds;
  $stringToSign = urlencode($resourceUri) . "\n" . $expiry;
  $key = base64_decode($key);
  $hash = hash_hmac('sha256', $stringToSign, $key, true);
  $signature = urlencode(base64_encode($hash));

  return "SharedAccessSignature sr=$resourceUri&sig=$signature&se=$expiry&skn=$policyName";
}

function queryDeviceTwin($iotHubName, $sasToken, $query) {
  $apiVersion = "2021-04-12"; // Latest API version
  $url = "https://$iotHubName.azure-devices.net/devices/query?api-version=$apiVersion";

  $headers = [
      "Authorization: $sasToken",
      "Content-Type: application/json"
  ];

  $postData = json_encode(["query" => $query]);

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);

  if (curl_errno($ch)) {
    echo 'Request Error: ' . curl_error($ch) . "\n";
    return null;
  }

  $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($httpStatus == 200) {
      return $response;
  } else {
    echo "Error querying device shadow. HTTP Status: $httpStatus\n";
    echo "Response: $response\n";
    return null;
  }
}



if ( isset($_POST['data']) ) {
  
  $postData = json_decode ( $_POST['data']);
  $queryData = $postData->queryData;
  
  //format of posted data:
  /*
  data:
  {
    queryData:
    {
      sensorUrl:"", //the id or URL which accesses the sensor
      uName:"",     //the user name
      uPwd:""       //the password
    }
  }
  */
  
  if($queryData == null)
  {
    $response['success'] = false;
    $response['infoText'] = "invalid post data";
    $response['value'] = 0.0;
    echo json_encode($response);  
    exit;
  }
  
  //enable CORS
  //Allow from any origin https://stackoverflow.com/questions/8719276/cross-origin-request-headerscors-with-php-headers
  if(isset($_SERVER["HTTP_ORIGIN"]))
  {
    // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
  }
  else
  {
    //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
    header("Access-Control-Allow-Origin: *");
  }
  
  header("Access-Control-Allow-Credentials: true");
  header("Access-Control-Max-Age: 600");    // cache for 10 minutes
  
  if($_SERVER["REQUEST_METHOD"] == "OPTIONS")
  {
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
      header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
      header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
  
    //Just exit with 200 OK with the above headers for OPTIONS method
    exit(0);
  }

  if ( empty( $queryData->sensorUrl ) ) {
    $response['success'] = false;
    $response['infoText'] = "no sensor URL given";
    $response['value'] = 0.0;
    echo json_encode($response);  
    exit;
  }
  
  // ---------- query implementation for sensors in Azure IoT Hub ----------
  
  $iotHubName = $queryData->uName;
  $policyName = "iothubowner";
  $sharedAccessKey = $queryData->uPwd;
  $thingName = $queryData->sensorUrl;  //Thing Name (passed in $queryData->sensorUrl
  
  try {
    // Generate SAS token
    $resourceUri = "$iotHubName.azure-devices.net";
    $sasToken = generateSasToken($resourceUri, $sharedAccessKey, $policyName);

    // Define SELECT query
    $query = "SELECT * FROM devices WHERE deviceId = '" . $thingName . "'";

    // Query device twin
    $result = queryDeviceTwin($iotHubName, $sasToken, $query);
    $sensorData = null;
    
    if($result != null){
      $sensorData = json_decode($result);
      
      if(is_array($sensorData) && (count($sensorData) > 0))
        $sensorData = json_encode($sensorData[0], true);
      else
        $sensorData = null;
    }
        
    if($sensorData != null) {
      $response['success'] = true;
      $response['infoText'] = "sensor object returned";
      $response['value'] = json_decode($sensorData, true);   
      //print_r($sensorData);
      echo json_encode($response); 
      exit;
    }

  } catch (Exception $e) {
    $response['success'] = false;
    $response['infoText'] = "could not query sensor" . $e->getMessage();
    $response['value'] = 0.0;
    echo json_encode($response);  
  }

  // ------------------------------------------------------------

  //std error
  $response['success'] = false;
  $response['infoText'] = "could not query sensor";
  $response['value'] = 0.0;
  echo json_encode($response);  
}
else {
  // initial condition failed
  $response['success'] = false;
  $response['infoText'] = "no query data given";
  $response['value'] = 0.0;
  echo json_encode($response);  
}
?>
