PHP class for filtering Siemens Protool log files and port them to a webpage

Posted in "News"

image 1

A while ago I was asked at work for a possibility to pull a log file out of a PLC (Simatic Multi Panel) and be able to port it to Microsoft Excel or other programs. The purpose was to gather statistics and try to show a top 10 of the faults that caused the longest breakdown times of the day. 


Since we work with a web application for error reporting which I've programmed and where our technicians write their reports for the breakdowns they've solved, I saw the possibility to link those two together. This way we could pick a log entry straight from the PLC and write our report for that entry, describing what actions we have taken to solve that particular breakdown. 


This week I've written a class in PHP5 which you can use to pull out data from the Siemens Simatic MP370 panel log file and output it any way you want. The class makes it able for you to port the log file to SQL, Microsoft Excel, select boxes in our web reporting application or just a plain web page which can be viewed on our Intranet. You can find an example for how to use it in the commented code in the start of the class. 


The class: 

	Class PLC_alarm for Siemens Protool Logs
	| alarm.class.php                                                        |
	| This program is free software; you can redistribute it and/or modify   |
	| it under the terms of the GNU General Public License version 2 as      |
	| published by the Free Software Foundation.                             |
	|                                                                        |
	| This program is distributed in the hope that it will be useful,        |
	| but WITHOUT ANY WARRANTY; without even the implied warranty of         |
	| GNU General Public License for more details.                           |
	|                                                                        |
	| You should have received a copy of the GNU General Public License      |
	| along with this program; if not, write to the                          |
	|   Free Software Foundation, Inc., 59 Temple Place, Suite 330,          |
	|   Boston, MA 02111-1307 USA                                            |
	|                                                                        |
	| Please give credit on sites that use alarm.class and submit changes    |
	| of the script so other people can use them as well.                    |
	| This script is free to use, don't abuse.                               |

	@version:	0.1
	@author:	Geoffrey Timmerman <https://www.geoffke.be> 
	@license:	http://opensource.org/licenses/gpl-license.php GNU Public License
	@copyright:	Geoffrey Timmerman

	This class is used to filter alarm entries from a Siemens Protool HMI, in our case the MP370 model.
	You can fetch the alarms shown on the panel over a RS232 connection With Putty or Hyperterminal and save them into a text log file.
	We read out the logfile with a simple PHP script and pass each entry to this class which filters out every block on each line.
	This way you get the alarm-id, date, time, PLC, status and text seperately which you can use again to create your own custom 
	alarmlist, table or even output it to Microsoft Excel with all data placed in seperate collumns.	 

	$alarm = new PLC_alarm();

	$line = The line which you pulled out of the logfile using  file() with foreach lines as line
	$id = $alarm->id($line); 		//Alarm id)
	$datum = $alarm->datum($line);		//Alarm date
	$tijd = $alarm->tijd($line);		//Alarm time
	$plc = $alarm->plc($line);		//PLC name
	$status = $alarm->status($line);	//Alarm status (K = active en K(G) = solved)
	$tekst = $alarm->tekst($line);		//Alarm text
	$full = $alarm->full($line);		//Pull the full logline


	require_once("alarm.class.php");	//include the class
	$file = "test.log";			//set the path and filename of the logfile

	$alarm = new PLC_alarm();		//Start the class

	//Since the logfile uses 2 lines per alarm we need this function to paste each entry together as one line
	function isOdd($num) {
		return !!($num & 1);    

	//Read the logfile

	//Pick out each line of the logfile using foreach
	foreach ($data as $num=>$line) {

		//Use the function above to paste the odd and even lines together as one line as seen on the protool screen
		if (!isOdd($num)) {
			$line1 = $line;
		} else {
			//Delecte paces at the start and the end of each log line
			$line = rtrim($line1).rtrim($line);

			//Change all special characters to valid HTML
			$line = htmlspecialchars($line);
			//Set the variables
			$id = $alarm->id($line);
			$datum = $alarm->datum($line);
			$tijd = $alarm->tijd($line);
			$plc = $alarm->plc($line);
			$status = $alarm->status($line);
			$tekst = $alarm->tekst($line);
			//Print each line in the order you decide.
			print $datum." &raquo; ".$tijd." &raquo; ".$status." &raquo; ".$plc." &raquo; ".$id." &raquo; ".$tekst."<br />n";



// class definition
class PLC_alarm {
	private $line;

	//Get alarm ID
	public function id($line) {
		preg_match("/00000000d{4}/", $line, $a_id);
		$id = substr($a_id[0], 8); 
		$this->alarm_id = $id;
		return $this->alarm_id;

	//Get the date
	public function datum($line) {
		preg_match("/d{1,2}/d{1,2}/d{2,4}/", $line, $a_datum);
		$this->alarm_datum = $a_datum[0];
		return $this->alarm_datum;

	//Get the time
	public function tijd($line) {
		//preg_match("/(d+:d+:d+)/", $line, $a_tijd); //Alarm tijd hh:mm:ss uit de string halen naar $a_tijd[0];
		preg_match("#([0-1]{0,1}[0-9]{1}|[2]{1}[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}#", $line, $a_tijd); 
		$this->alarm_tijd = $a_tijd[0];
		return $this->alarm_tijd;

	//Get the PLC name
	public function plc($line) {
		preg_match("/SEddd/", $line, $a_plc); 
		$this->alarm_plc = $a_plc[0];
		return $this->alarm_plc;

	//Get the alarm status: K or (K)G
	public function status($line) {
		if (preg_match("/(K)G/", $line, $a_status)) {
			$this->alarm_status = $a_status[0];
		} elseif (preg_match("/ K /", $line, $a_status)) {
			$a_status = preg_replace("/ K /", "K", $a_status[0]);
			$this->alarm_status = $a_status;
		} else {
			$this->alarm_status = "?";
		return $this->alarm_status;

	//Get the alarmtext
	public function tekst($line) {
		//Remove the id, date, time, PLC number and the status from the log entry untill only the text is left over
		$line = preg_replace("/00000000d{4}/", "", $line); //Remove the alarm id
		$line = preg_replace("/d{1,2}/d{1,2}/d{2,4}/", "", $line); //Remove the date
		$line = preg_replace("/SEddd/", "", $line); //Remove the PLC number
		$line = preg_replace("/(K)G/", "", $line); //Remove the alarm status if it's equal to (K)G
		$line = preg_replace("/ K /", "", $line); //Remove the if it's equal to K
		$line = preg_replace("/(d{1,2}):(d{1,2}):(d{1,2})/", "", $line); //Remove the time
		$line = preg_replace("/_/", " ", $line); //Remove all underscores from the entry if any
		$this->alarm_tekst = trim($line); //Only a clean alarm text should be left
		return $this->alarm_tekst;

	//This function shows the raw data from the log per entry but without any underscores and without the white space at beginning and the end
	public function full($line) {
		$line = preg_replace("/_/", " ", $line); //Remove underscores
		$this->alarm_full = trim($line); //Remove the white space
		return $this->alarm_full;



For any questions just email me using the contact form.

Article was posted on Saturday 16th of April 2011 @ 18:39 PM CEST   comment(s)