Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Where to start - Moving rotating looping messages into an array 1

Status
Not open for further replies.

jtwood

IS-IT--Management
Aug 5, 2010
7
0
0
US
I need to use a small vbscript to move messages out of a changing string variable into elements of an array.

Some detailed background:

I am using: (For any body familiar with these types of software or these particular packages)

Think & Do from Phoenix Contact (a SCADA software package) where the HMI has the ability to use vbscript with the variables (tags) within Think & Do
An OPC Server built into Think & Do
Spectre Instruments Win911 - An alarming and notification software that can communicate through the OPC Software.

Win911 has an available Group Data Poke that allows messages from Win911 to be sent through OPC to the Think & Do tag database (variables)
In the event of multiple alarms within an alarm group, this string that is sent through OPC is updated with each alarm condition in a cycle.

I need to capture each of these alarm conditions into an array so that all of the conditions can be available to the operators.


Lets say that I have a string called LoopingMessage.

At some interval (and I can't base anything off of the interval because of the multiple pieces of software involved) the message may or may not change. The number of messages it loops through vary by the number of alarms and this number is unavailable to the script.

So for instance, say I have 4 alarm conditions that are being written to Looping Message:

Condition 1 - ALARM HIHI DATE TIME REFLUX UNIT DIFFERENTIAL PRESSURE
Condition 2 - ALARM LOLO DATE TIME REFLUX UNIT PRESSURE
Condition 3 - ALARM HI DATE TIME BOTTOM TEMPERATURE CONTROL
Condition 4 - ALARM LO DATE TIME PRESSURE CONTROL VALVE

I need to be able to catch each of these alarms into an array. When one of these alarm conditions resolve it will no longer be in the loop. If another alarm condition occurs it will be added to the loop. (The array will need to be redim as needed.) Order in the array is not important, as long as all active alarm conditions that are displayed in the changing string are captured and any that have resolved and are not in this changing string are not captured/retained.

For whatever reason, I can't seem to get my head wrapped around a place to even start for a solution. If anybody has any suggestion of where to start, that would be terrific. Then we can get some code up and take a look at this.


Thanks in advance.

Justin Wood
 
how is the string delimited? i mean between each 'alarm'?

how do you know when one of these alarms have been resolved? is that that the 'alarm' instance no longer appears in the LoopingMessage string?

the suggestion of the use of dictionary is a good one.

i would be interested how the 'Condition 1' 'Condition 2' are determined...are the integer part unique between each presentation of LoopingMessage string?
 
ok, so perhaps your strLoopingMessage is delimited by VbCrLf?
Dim strLoopingMessage, aAlarm, dicGAlarms
strLoopingMessage = "dont know what you are going to do hrere"
Set dicGAlarms = CreateObject("Scripting.Dictionary")
Call UpdateAlarms(strLoopingMessage, dicGAlarms)
Wscript.Echo "UpdateAlarms.Count = " & CStr(dicGAlarms.Count)
For Each aAlarm In dicGAlarms
Wscript.Echo aAlarm & " = " & dicGAlarms.Item(aAlarm)
Next


Sub UpdateAlarms(ByVal strLoopingMessage, ByRef dicAlarms, ByVal blnClearOut)
Dim arrTemp, strItem, strKey, strValue
'remove all the old ones? as we are expecting strLoopingMessage to contain the current status? this is not something which has been made clear in the spec
If blnClearOut = True Then
dicAlarms.RemoveAll
End If
'
arrTemp = Split(strLoopingMessage, vbCrLf)
For Each strItem In arrTemp
strKey = ""
strItem = ""
'presume we need to split based on -?
If InStr(strItem, " - ") Then
strKey = Left(strItem, InStr(strItem, " - "))
'this is silly :)
strItem = Replace(strItem, strKey & " - ", "")
If Not dicAlarms.Exists(strKey) Then
dicAlarms.Add strKey, strItem
Else
Wscript.Echo "oh dear we have a duplicate " & strKey
End If
Else
Wscript.Echo "strItem not formatted correctly, " & strItem
End If
Next


End Sub


'Class clsAlarm???
'End Class
 
The looping message is not delimited in any way. It is basically overwritten through OPC by the alarming software. The way I can "detect" the alarm condition is by part of the descriptive text in the alarm condition.

When a new alarm condition is added it just merely sends the alarm string into the loop of different strings it sends.

When an alarm condition resolves and is no longer present the string is no longer sent by the software. Exactly the part that seems to make this difficult.

So for example:

I have four alarm conditions:

ALARM 1 - HIHI DATE TIME
ALARM 2 - HI DATE TIME
ALARM 3 - LOLO DATE TIME
ALARM 4 - LOLO DATE TIME

(Alarm 1, Alarm 2, etc being an alarm name within the software)


These might cycle, say every 2 seconds--completely replacing the string

Lets say that ALARM 2 Resolves.

Now the string merely shows each of the following (1 every 2 seconds, perhaps) replacing the string completely

ALARM 1 - HIHI DATE TIME
ALARM 3 - LOLO DATE TIME
ALARM 4 - LOLO DATE TIME

Now if a new alarm condition exists, the following would loop.

ALARM 1 - HIHI DATE TIME
ALARM 3 - LOLO DATE TIME
ALARM 4 - LOLO DATE TIME
ALARM 5 - HI DATE TIME

Consider each ALARM # line to be a total replacement of the string.

 
Is this script run independently or does it get passed into OPC and OPC executes it whenever it has a spare moment.
 
You can't run scripts within OPC. OPC is used to move numerical and text data back and forth between software in a standardized format.

The OPC Server received the alarm string from the OPC client in Spectre WIN911. Then the string gets passed to Think & Do.

The problem is, the only part that my script will no about it the text string. Thats it, no delimiters, no bits/flags, nothing. It just knows that there is text.
 
It just knows that there is text
What text ?
Can't you post an hexadecimal dump of this text ?

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
What does your script need to do with these alarm values? From your opening post it sounds like the VBscript is just holding onto the values so the operator can see them? Does VBscript need to pass them back and forth between programs or process them in any way?
 
It would be nice to be able to get the text into an object or several strings so that each could be displayed, say in a grid. Otherwise the operator will have to wait and watch the message to see each alarm.

The string changes on an interval (say 5 seconds)-everything about this string is completely independent and untouchable except the string itself. There is no way to tell the string to move to the next message, previous message, etc. All the script will be able to see is the actual string.

The text will be in some similar format:

[DATE] [TIME] [ALARMTAG] [ALARMCOND] [ALARMVAL] [ALARMMESSAGE]

Of course, the text will change depending on the date, time, the variable name with an alarm condition, the alarm condition, the alarm value, the alarm message--

This may not be solvable. Let me know if you see it that way. I am use only limited portions of vbscript. Most of what I have done has been with ADO and some WSH.
 
I think it is too early to say it is unsolvable. What would greatly help us now is if you could post an example of the output you are getting and an example of what you want it to look like when the script is done with it.

From what I can gather so far, you have program A that is spitting out info in one long string (no delimiters whatsoever) and you want to parse out the alarm conditions so the operator can see what is going on.

I get the impression you are getting something like this:
"shaft spinning at 109 rpm widget angle 33 degrees alarm pressure too high 08/06/2010 14:10 temperature within limits"

and from it want:
"alarm pressure too high 08/06/2010 14:10"

That's just my guess, though. Again, some example input/output data would help greatly.

How is this alarm information going to be displayed to the user? VBScript itself is pretty limited on output.
 
Well, you are close on how I get the information.

Lets say that there are 5 alarm conditions currently.

For a period of time (perhaps 5 seconds) the value of the looping string would be:

DATE TIME ALARM1 HIHI BLAHBLHA

Then after that 5 seconds it would be:

DATE TIME ALARM2 HIHI BLAHBLHABLA

Then after 5 more seconds it would be:

DATE TIME ALARM3 LO BLAHABLHABALHA

--I think you get the idea. The problem is that it just sends a new string at time intervals that overwrite the same variable.

I would like to be able to get the multiple messages into an array. From here I can use the software to place the information into a nice, neat grid.

I agree that calling this unsolvable is a bit too easy. I just can't even think of a way to start this.

The problem knowing whether the alarm is currently active or not. It just disappears from the looping message. So instead of being displayed at some point every 5 seconds it just isnt, making it very difficult to determine when the message is gone.

I just thought of this, though. One option that might be better is to parse the string information, send it to a database keyed to the date/time and alarm tagname and then display the information on the screen only as long as there is an identical date/time and alarm tagname. (in otherwords, a duplicate key)

But even then, I sit here and think, how do I know when it is gone?

I am confortable enough with ADO that I would definitely go this route if I could figure out how to remove the alarm after it disappears from the string.

I have timers and time based triggers available in the software that this vbscript will be written in. (Indusoft HMI Studio)

I don't know. I am getting frustrated with what seems to be such a minor problem, but so important to the operators. A message that changes every 5 seconds is a lot less useful than a list of messages that shows every condition.

There is one thing that I do know. There is no chance that the software package that I use for alarming will make a change. It is a very stable piece of software with limited features, but has a long history of always working and being very well programmed.
 
>I think you get the idea...

Not quite yet. If you have more than one alarm being reported does the string look like;

DATE TIME ALARM1 HIHI BLAHBLHADATE TIME ALARM2 HIHI BLAHBLHABLA

or is it delimited with a vbCrLf as in

DATE TIME ALARM1 HIHI BLAHBLHA
DATE TIME ALARM2 HIHI BLAHBLHABLA

In the second case you can Split using vbCrLf as a delimiter, in the first you will need to detect where a 'BLAHBLHA' ends and a 'DATE' begins and devize code to 'split' on that.


 
Based on the info you have given so far, I'm not convinced you need to explicitly remove any alarms. If you go with the array idea your VBscript can parse the info, clear out the array, and write the new info to the array each time it receives info. If an alarm is not in the string, it will disappear on its own.

If you want help with the parsing, you will need to post some actual input/output.
 
@HughLerwill --neither.

When the alarm string changes it is replaced from an external source. The string that for alarm1 is completely replaced by the string for alarm2.
 
> being very well programmed

The alarm strings are not well programmed ...


 
Something like the following will maintain a Dictionary containing live alarm messages. This example assumes that there is a 2 second interval between each alarm message update
Code:
[blue]Public AlarmMsgQueue
Public Const ExpiryInterval = 2 ' Number of seconds between message updates

Public Sub Initialise()
    Set AlarmMsgQueue = CreateObject("Scripting.Dictionary")
End Sub

Public Sub StringArrives(strAlarm)
    Dim lp
    Dim Expiry
    Dim Items
    Dim Keys
    
    Expiry = (UBound(AlarmMsgQueue.Items) + 2) * ExpiryInterval ' Calculate expiry interval for a message based on number of messages in queue
    
    ' if this message already in the queue, in which case we are now looping
    If AlarmMsgQueue.Exists(strAlarm) Then
        'Ok, look for all expired items in the queue
        For lp = UBound(AlarmMsgQueue.Items) To 0 Step -1
            Items = AlarmMsgQueue.Items
            Keys = AlarmMsgQueue.Keys
            If DateDiff("s", Items(lp), Time) > Expiry Then
                AlarmMsgQueue.Remove Keys(lp)
            End If
        Next
        
        ' Refresh timestamp for any remaining, non-expired matching entries
        For lp = 0 To UBound(AlarmMsgQueue.Items)
            Items = AlarmMsgQueue.Items
            Keys = AlarmMsgQueue.Keys
            If Keys(lp) = strAlarm Then ' refresh local timestamp of existing entry
                AlarmMsgQueue.Item(Keys(lp)) = Time
                Exit For ' there should be only one match, so exit
            End If
        Next
        
    Else
        AlarmMsgQueue.Add strAlarm, Time
    End If

End Sub[/blue]
 
The unfortunate thing with the piece of software that does the alarming is that this OPC link for the alarm strings seems to be nothing more than an afterthought. Most likely a feature add that was put into place without changing any of the core of the software.

As far as its stability, its only hampered by Windows and its wonderful quirks!

@strongm : I'll be working on this today. I appreciate the direction you've given me. I seem to have limited creativity when it comes to some of this type of stuff.

I'll let you all know what finally ends up working well for this. Thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top