OSISOFT PI historian has become very popular in the process industry. Its unique features are best suited for process data which are temporal in nature. In this post we will try to create a system to generate SMS’s based on process parameter deviation in real time. You can trigger the SMS generation by using any logic. We will take an example here and will try to send SMSes to concerned people in the case of power plant outage.
So our logic would be to monitor plant generation and as soon as that become zero ( or less than zero ) we will try to generate and send SMS to concerned person.
So our steps would be as follows:
1) Set a timer with some frequency (interval) as per your requirement. For e.g. you want to check the current plant generation ( reflected by PITag “UNIT_1_GEN_MW”) at regular interval.
Public MyTimer As Timers.Timer
You can initialize and set the interval anywhere. E.g. in the constructor (of the WPF Form/Winform/Silverlight Page) itself using
MyTimer = New Timers.Timer MyTimer.Interval = 60000 ‘set the timeinterval in miliseconds AddHandler MyTimer.Elapsed, AddressOf MyTimerElapsed
2) Start the timer as per your requirement (e.g at button click or at the launch of the application itself)
You can also stop the timer as per your requirement by using MyTimer.Stop()
3) Put the code in Timer elapsed call back routine
Private Sub MyTimerElapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) DoProcess() End Sub Private Sub DoProcess() 'Where DoProcess() is the subroutine where you will perform these tasks 'Retrieve the current value of the parameter 'Check whether it has exceeded the limits or not 'Send SMS if it does
Now to retrieve the value from PI historian you can use various techniques. You can explore as per your requirement. We will discuss a few of methods here :
- Directly using PI-SDK : OSISOFT provides PI-SDK (Software Development Kit) which can be used to directly get the current snapshot value from the desired PIServer
- Use PI-Oledb : PI-Oledb connection is another option, although PI-OLEDB queries are finally get converted in PI-SDK call only but if you are familiar with traditional SQL queries , this approach may suit you better e.g.
' Modify this Connection string if necessary. Dim con As New OleDbConnection("Provider = PIOLEDB; " _ & "Data Source = " _ & ServerName _ & " ; User ID = " _ & UserName _ & "; Password = " _ & Password _ & "; Command Timeout=0;") 'And then you can execute the SQL query to retrieve the snapshot value e.g. SELECT TAG, TIME, VALUE, DIGSTRING(STATUS) AS STATUS FROM PIARCHIVE..PISNAPSHOT WHERE TAG Like ‘UNIT_1_GEN_MW’
- Use Web Services: You can create web services which in turn execute PI-SDK or PI-OLEDB sql queries. Benefit of this approach would be that you won’t need PI-SDK dll’s at the client end. Otherwise you have to install PI-SDK at the client machines also. This approach is very useful in any enterprise level environment. You can create these web services using WCF also.
You can get details of using these techniques on OSISOFT website. I will discuss about these methods in subsequent posts also
Now suppose you have retrieved the value and it has exceeded the limits, you can now trigger the SMS generation. To do so mainly two methods are available :
- Use Internet based solution: Many vendors are available (to name a few clickatell, timesms, way2sms) which can provide you bulk SMS feature. The requisite for the same is availability of internet from the server or client where the code will be executed. These vendors do also provide certain API’s which can directly be used for SMS generation. You can try them as they do also provide demo accounts with few free SMS sending option. The other issue with this solution is DND (Do Not Disturb) feature of TRAI. Persons who have registered with DND might not get the SMS. So, take care of all Pros and Cons before you take any path.
- Phone or GSM/GPRS modem: Another way is to use phone or GSM modems. These Modems can be connected to server using USB/COM Port/Parallel Port/Bluetooth. Once the connection is established “AT Commands” Can be used to send the SMS directly from the code. We will discuss about the process in this post. SMS Generation: Create a Class name MySMS
Imports System Imports System.Threading Imports System.ComponentModel Imports System.IO.Ports Public Class MySMS Public COMMPort As String = "COM16" 'You can change the COM port to which your ' modem/phone is connected Private WithEvents SMSPort As SerialPort Private SMSThread As Thread Private ReadThread As Thread Shared _Continue As Boolean = False Shared _ContSMS As Boolean = False Private _Wait As Boolean = False Shared _ReadPort As Boolean = False Public Event Sending(ByVal Done As Boolean) Public Event DataReceived(ByVal Message As String) Public Sub New() 'initialize all values SMSPort = New SerialPort With SMSPort .PortName = COMMPORT .BaudRate = 19200 .Parity = Parity.None .DataBits = 8 .StopBits = StopBits.One .Handshake = Handshake.RequestToSend .DtrEnable = True .RtsEnable = True .NewLine = vbCrLf End With AddHandler SMSPort.DataReceived, AddressOf DataReceivedEventCallBack End Sub Public Function SendSMS(ByVal Reciepent As String, ByVal Message As String) As Boolean If SMSPort.IsOpen = True Then 'sending AT commands SMSPort.WriteLine("AT") 'set command message format to text mode(1) SMSPort.WriteLine("AT+CMGF=1") 'set SMCC number (Service Center Number, this one is for Airtel Delhi ' Region) SMSPort.WriteLine("AT+CSCA=""+919810051914""") ' enter the reciepent number SMSPort.WriteLine("AT+CMGS=""" & Reciepent & """") _ContSMS = False SMSPort.Write(Message & Chr(26)) 'SMS Message 'chr(26) = Ctrl + V SMSPort.Close() End If End Function Public Sub Open() If Not (SMSPort.IsOpen = True) Then SMSPort.Open() End If End Sub Public Sub Close() If SMSPort.IsOpen = True Then SMSPort.Close() End If End Sub Public ResponseString As String = "" Private Sub DataReceivedEventCallBack(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) ResponseString = ResponseString & vbCrLf & Now.ToString & " ResponseString :" & SMSPort.ReadExisting End Sub End Class
Now you can use the above class to send the SMS from your code as shown below.
Public Sub DoProcess() Dim _MySMS as New MySMS() ‘if value exceed the limit then _MySMS.Open() _MySMS.SendSMS(Reciepent,Message) ‘Pass the value as per your need End Sub
Note: If it is not working well, then one of the possible reasons could be that AT commands are fired too soon to the modem. So, You can use various methods to get the response first from the modem and then fire the next AT command or you can introduce some delay using Timer.Sleep(1000) in between. Once you will start debugging you will eventually figure it out the best way.
I have tried the above approach and its working quite well.
So, The above mentioned approach can be tweaked in unlimited way to suit your requirement. Keep in touch for more posts related to intelligent system development for process industries.