PHP Classes
PHP Classes
elePHPant
Icontem

Controlling Autonomous Hardware Devices Using PHP Software Agents

Recommend this page to a friend!
  Blog PHP Classes blog   RSS 1.0 feed RSS 2.0 feed   Blog Controlling Autonomou...   Post a comment Post a comment   See comments See comments (10)   Trackbacks (0)  

Author:

Posted on:

Categories: PHP Tutorials

Some hardware devices can perform useful actions autonomously by the means of software agents, like for instance monitoring objects in the space around an unmanned vehicle (robot).

Read this article to learn how to implement PHP software agents that can process actions using sequences of actions defined in JSON.




Contents

Introduction

What Are Software Agents?

Defining Process Agents using JSON

Brief Introduction to the JSON syntax

PHP Functions Relevant to Agents

A Software Agent as a JSON Document

Enabling the JSON Agent Documents

The Need for Securing JSON Process Agent Documents

Conclusion


Introduction

This article is the continuation of a previous article on which it was covered how to communicate with sensors in hardware devices using PHP.

What Are Software Agents?

Agent-oriented software is about enabling a series of actions based on sensed conditions or the context of a process.

For example, an agent is embedded in a processor, monitoring the space around an unmanned vehicle. If there is an object present, the agent can query its movement, static or moving. If moving, it can acquire its current location, speed and direction.

Defining Process Agents using JSON

Process agents can be defined through JSON documents. A process document contains the sequence of operations and physical objects used in the process. And, PHP has the constructs needed to enable agent operation through such JSON documents.

Brief Introduction to the JSON syntax

To start with, the structure of a JSON document, or object, begins with { and ends with }. Between these brackets is a list of name/value pairs with the format

<label>: <value>

<label> is a string delimited by double quotes and is the name of an attribute. Name and value pairs are separated by commas, except for the last pair in the list.

<value> can be a string, a number, true, false, or null. A number can be an integer, float, or double value. A string is any number of Unicode characters, except double quotes ("") backslash (\) or a control character delimited by double quotes. As an example, "model": "XYZ" is an attribute of a product object describing the product's model number.

<value> can also be full JSON document delimited by brackets ({,}) or an array (a list of values delimited by square brackets ([, ]) and separated by commas).

An example of a JSON document is the following description of a product,

{
 "model_number": "X-6754",
 "design_specs": "https://acme.com/specs/X-6754.pdf",
 "mfg_plant": "TN",
 "version": 14,
 "distributors": ["Acme", "United", "Paramount"]
}

Note that numbers are are not delimited by any character. Also, the distributors attribute is an example of an array value.

PHP Functions Relevant to Agents

To begin with, we make use of the popen and pclose functions. popen enables an executable, refered to as a session, residing in the host. It takes 2 arguments:

popen( <command>, <mode>)

where,

<command> = a full path description of an executable program as a string,

<mode> = same as the mode used for the function fopen and indicating direction of  the data flow (read, write, append, etc.)

The executable is contained in the host running the PHP environment. pclose simply closes the session opened through popen and has no arguments.

In addition, we also have the function json_decode that can convert a standard JSON document into a PHP object or array. When converting to an array, it is defined as follows:

json_decode(<json_doc>, true)

where,

<json_doc> = a string representing a full JSON document as per above syntax

The second parameter is either true or false and lets the decoder know the output format; true for an array or false for an object.

A Software Agent as a JSON Document

JSON documents, as was shown in the example above, tend to be used passive structures that carry data. In effect, they act like rows in a database. But, JSON documents can be more.

As in the case of the popen function, invocation of a host resident executable can be stated as a string. So, one of the attributes in a JSON document describing a process or workflow is a physical object used in the process and associated with the invocation of that executable.

Take, for example, a JSON document that describes a process that fills a tank with a fluid, heats the fluid, and releases it from the tank once it reaches a certain temperature. So, there is:

  1. a tank inlet valve that can be turned on or off in order to fill the tank

  2. a tank heater that can be set to one of many levels including off

  3. a tank outlet valve that can be turned on or off in order to drain the tank

  4. a fluid temperature sensor acquiring the current temperature of the fluid in the tank

  5. a fluid level sensor acquiring the current level of the fluid within the tank

The structure of the JSON document describing tank structure and operation, in effect the tank agent can be:

{
 "inlet_valve" : "/home/tank/SetValve inlet",
 "outlet_valve": "/home/tank/SetValve outlet",
 "heater": "/home/tank/SetHeat"
 "fluid_temp": "/home/tank/GetTemp",
 "fluid_level": "/home/tank/GetLevel",
 "sequence": [
  "inlet_valve", "on",
  "fluid_level", "<top>",
  "inlet_valve", "off",
  "heater", "<level>",
  "fluid_temp", "<setpoint>",
  "heater", "off",
  "outlet_valve", "on",
  "fluid_level", "<empty>",
  "outlet_valve", "off"
 ]
}

In this JSON process agent document, the attribute sequence is standard regardless of the process specifics. In effect, it is like a reserved label in his type of document.

In this example, the sequence starts by opening the inlet valve, filling the tank with fluid, heating the fluid to pre-set temperature, and opening the outlet valve to release the heated fluid. The other attributes are physical objects used in the process defined as follows:

  1. attribute label describing a physical object that is part of the process, and

  2. a value that is a string containing the full path description of an executable enabling a specific physical process associated with this object.

In this example, the value of inlet_valve is an executable (SetValve) that handles the details of activating or deactivating a valve. Its parameters are:

  1. the type of valve (inlet, outlet), and

  2. the state of the valve (on, off).

Now, how is the executable paired with its parameters ? That takes us back to sequence. Note that the value of sequence is a JSON array.

The values in this array are pairs consisting of an attribute label and an executable parameter that is attached (concantenated) to the value associated with the attributed value. So, in the first pair, the value of the inlet_valve attrribute is attached to the next entry, on, and so on.

Following the array in the order shown provides the flow of the process: open the inlet valve until the tank is full, shut the inlet valve, heat the tank until it reaches a set point temperature, open the outlet valve until the tank reaches the empty level, close the outlet valve.

The values enclosed by "<" and ">" are parameters supplied through a JSON process configuration document. The labels between the "<" and ">" are attribute labels in the configuration document. An associated configuration document to the above example process agent document is:

{
 "top": 100,
 "level": "mid",
 "setpoint": 350,
 "empty": 0.01
}

In this way, activating a process description starts with a JSON agent document and a JSON process configuration document.

Enabling the JSON Agent Documents

Now, what does it take to enable the process agent ? Here is a class used to load and enable a process agent description:

class ProcessCycle
{
 public $Proc_Err;	// error log for any method in this class
 private $Proc_Cycle;	// description of the JSON process cycle document

 /*
   Load the process cycle definition.

   inputs:

   1. The contents of a JSON process agent document
   2. The contents of is associated JSON configuration
      document output: a configured process agent ready for use
 */

 function __construct($Agent, $Config)
 {
  $this->Proc_Err = ""; // initialize the process error log
  $this->Proc_Cycle = null; // initialize the process cycle descriptor

  // convert the contents of the JSON process agent document to an array
  $this->Proc_Cycle = json_decode($Agent, true);

  // if there was any issue with the conversion ....
  if(is_null($this->Proc_Cycle))
  {
   // issue a messsage in the error log and exit
   $this->Proc_Err = "\n1.The agent JSON process agent document cannot be decoded.";
   return;
  }

  // convert the contents of the JSON configuration document to an array
  $Cfg = json_decode($Config, true);

  // if there was any issue with the conversion ....
  if(is_null($Cfg))
  {
   // issue a messsage in the error log and exit
   $this->Proc_Err = "\n2.The agent JSON configuration document cannot be decoded.";
   return;
  }

  // retrieve the cycle sequence
  $seq = $this->Proc_Cycle["sequence"];

  // for each process object parameter ....
  for($i = 0; $i < count( $seq ); $i = $i + 2)
  {
   // if this is a configured value ....
   if(is_numeric( ereg( "<.+>", $seq[ $i + 1 ] )))
   {
    // retrieve the label in the parameter value (between '<' and '>')
    $lbl = trim( substr( $seq[ $i + 1 ], 1, strlen( $seq[ $i + 1 ]) - 2));

    // replace the parameter value with the configured value
    // using the retrieved label
    $seq[$i+1] = $Cfg[$lbl];
   }
  }

  // replace the cycle sequence with the configured sequence
  $this->Proc_Cycle["sequence"] = $seq;

  // .... that's all, people !!
 }

 // Run the process sequence for a prescribed number of times
 function DoIt($CycleCount)
 {
  $RunMsgs = "";

  // initialize the process runs log
  $this->Proc_Err = "";

  // initialize the process error log
  $Seq = $this->Proc_Cycle["sequence"];	// get the configured
process sequence
  for( $i = 0; $i < $CycleCount ; $i++)
  {
   $cnt = $i + 1;
   $RunMsgs .= "\n\n**** RUN [". $cnt ."] ****\n";

   // for each sequence step ....
   for($j = 0; $j <count( $Seq ); $j = $j + 2)
   {
    // retrieve the executable for the process object,
    // attaching the configured parameter value to it
    // as a parameter for the executable
    $exec = $this->Proc_Cycle[$Seq[$j]]." ".$Seq[$j+1];
    $ep = popen($exec,"r");	// enable the executable
    if($ep == false)		// if the executable could not be enabled ....
    {
     // issue a message to the error log and exit
     $this->Proc_Err = "\n3. Run [".$i."]: ";
     $this->Proc_Err .= $exec." cannot be enabled.";
     return -3;
    }

    // retrieve the feedback message from the executable
    $msg = fgets($ep);
    if($msg == false)		// if the feedback message failed to appear ....
    {
     // issue a message to the error log and exit
     $this->Proc_Err = "\n4. Run [".$i."]: ";
     $this->Proc_Err .= $exec." did not provide feedback.";
     return -4;
    }

    // add this feedback message to 
    // the process runs log
    $RunMsgs .= "\n".$msg;

    // if the executable stream cannot be closed ....
    if(pclose($ep) == -1) 
    {
     // issue a message to the error log and exit
     $this->Proc_Err = "\n5. Run [". $i. "]: ";
     $this->Proc_Err .= $exec." stream cannot be closed.";
     return -5;
    }
   }
  }

  // exit and transfer process runs log
  return $RunMsgs;
 }
}

A PHP script utilizing this class passes the contents of a process agent document and associated configuration document as follows:

<?php

 include 'ProcessCycle.php';

 $CycleCount = 3; // number of cycle runs requested

 // full path description of the JSON process agent and configuration documents
 $Docs = array("proc" => "/home/tank/tank.json", "config" => "/home/tank/tank.cfg");

 // get the JSON process agent and configuration documents for the tank process
 $JSON = null;

 foreach($Docs as $key => $itm)
 {
  $fp = fopen($itm, "r") or exit("**** document ($itm) cannot be accessed");
  $JSON[$key] = fread($fp,filesize($itm)) or exit("**** document ($itm) cannot be read");
  fclose($fp) or exit("**** document ($itm) cannot be closed");
 }

 // create an instance of a tank process
 $tank = new ProcessCycle($JSON["proc"], $JSON["config"]);

 if($tank->Proc_Err == "")
 {
  // run it for the prescribed number of cycles
  $tank_run = $tank->DoIt($CycleCount);

  if(!is_numeric($tank_run))
  {
   // display the cycle runs log
   print("____ RUN LOG ____\n".$tank_run."\n");
  }
  else
  {
   // display the error log during cycle run(s)
   print("____ RUN ERRORS ____\n".$tank->Proc_Err."\n");
  }
 }
 else
 {
  // display the error log during instance creation
  print("____ LOAD ERRORS ____\n".$tank->Proc_Err."\n");
 }
?>

In effect, a similar PHP script uses pre-defined JSON process and configuration documents in the host while the number of cycles to run can be provided via a CGI parameter.

The run log or error log can be also provided as an HTML process feedback page. The contents of the feedback for our example tank process agent document simply look like this:

**** RUN [1] ****

inlet valve is open
fluid level in tank now at 100 percent
inlet valve is close
heater set at mid
fluid temperature now at 350 degrees
heater set at off
outlet valve is open
fluid level in tank now at 0 percent
outlet valve is close

These messages are supplied by the executable programs described in the example tank JSON process agent document above.

The Need for Securing JSON Process Agent Documents

A key element of enabling such process documents is maintaining a secure environment which minimizes risk of malicious or unintended use of a PHP script enabling a process.

Measures should be in place that secure access to PHP sctipts that manipulate a process via such documents; as well as control access to the JSON documents themselves.

Conclusion

A methodology for remotely enabling a process using JSON documents and PHP is to define a general process enabling class driving by a process agent document and associated configuration document in order to run a physical process.

The ProcessCycle class, along with the sample JSON documents, serves as a template that can be emulated and modified in order to illustrate the ability of PHP to manage and enable cyber-physical systems.

If you liked this article or have questions, post a comment here.




You need to be a registered user or login to post a comment

Login Immediately with your account on:

FacebookGmail
HotmailStackOverflow
GitHubYahoo


Comments:

1. But how do you read the sensors? - Dimitry Codreanu (2015-07-13 20:57)
Using PHP for many applications is something that makes it very... - 7 replies
Read the whole comment and replies

2. Doubts - Julio Villalba (2015-07-13 19:11)
questions... - 1 reply
Read the whole comment and replies



  Blog PHP Classes blog   RSS 1.0 feed RSS 2.0 feed   Blog Controlling Autonomou...   Post a comment Post a comment   See comments See comments (10)   Trackbacks (0)