Programmatically update FactoryTalk View SE client recipe list

nbet

Member
Join Date
May 2014
Location
Washington
Posts
8
In FactoryTalk View Studio I can add recipes to my project/application using the tree view. Those recipies can then be restored/downloaded in the running Client application by use of the Recipe control. The Recipe control only lists the recipes that were added to the application using the tree view in Studio.
My goal is to allow a programmer to drop recipes into a Windows folder and have the operator restore/download recipies from that Windows folder without having to open the appliction in SE View Studio to add the recipies. I can get the path/filename, just need a way to have it open in the client.

Is there a way to pass the Client a Windows path and file name and have it restore/download that recipe?

Alternatively, is there a way to programmatically update the list of recipes that are linked to by the Recipe control?
 
Like so much with FTView, the recipe manager is the basest form of garbage. You would be much better served to put some VBA in there and handle the recipes externally. My preference there is to use SQL server for the back end, with some simple front end that anyone can use to add/edit/change them.
 
Thanks for your thoughts :D I am proficient with .net languages and VBA for a number of applications, but never for FT View Studio. I did explore the available FTView Studio VBA controls, methods, and properties but did not see anything looked like a way to pass recipes to the running client app. Would you please give me guidance on an approach to "handle the recipes externally" using FTView Studio VBA, is there a particular method or property I should be looking at?
 
Store the recipies in a SQL server database, then when the display with the recipe manager is opened, I scan the database, and populate either buttons or a selector list with the recipe names from the database. If there are more than will fit on one page, I usually put "Next Page" / "Prior Page" buttons to update the display with the more information from the database.

Once one is selected, bring in all the fields, assign them to a SE I/O tags (don't use direct references, trust me), and then write the entire tag group to the controller.

For the comms, you basically create a tag group, then fill it with the tags that you want to write. Once they are populated with the data you need, you issue a WritePendingValues( MyTagGroup ) command. For oddball SE reasons, I generally write the tag group two times, and then read them back from the controller to verify that they got there correctly.
 
I have to second rdrast on that. The FTView recipe (and RSView recipe before that) is so useless that I programmed my own.

My first few generations of recipes consisted of separate text files. Using Win API calls the FTV app opens a standard file browser to the folder where the recipe files are saved and then opens the text file and loads it into the matching tags.

The file format is just a list of values using this form:
TAGNAME=Value

The nice thing about that is the files could be edited with any word processor. Later I wrote a VBA app for excel that parsed the recipe files into a spreadsheet form that applied limits and verified the settings.

This served me well for years and it might meet your needs since text file reads and parsing is fairly trivial. However, I am now using an MSSQL DB. What I've found is that the DB is a lot easier to administrate and making changes is a lot simpler. For example, with a DB something like adding a field to all recipes is as simple as running one SQL statement, while it required opening and editing every single text file with the old method.

To see some examples of how to code FTV VBA to create tag groups, retrieve tag objects, and write values to the tags open the FTV help and browse down until you find the Tag object models and tag group object models and open those help files. There are some VBA examples included in there that should be helpful.

Also, if this is a stand alone application and not something where lots of clients are accessing the same recipe DB then you could use MSAccess as your DB instead. The AB KB had lots of example code for working with MSAccess DB files.

Good luck.

edit to add:
Most of the time in my applications recipes are selected by barcode reader, however once in a while its necessary to have the operator select the recipe manually such as when running an engineering test. In these cases I have two fields, the first is a filter field and the second is a drop down field with a list of recipe names that match the filter, so a blank filter field will retrieve all recipe names, which makes for a long drop down list. But a letter 'A' in the filter field will retrieve only recipe names that begin with 'A' to populate the drop down list. I have hundreds of recipes so you may or may not need this feature but I thought I would pass on the idea.

BTW, welcome to the forum.
 
Last edited:
Thanks again for the assistance. Seems that a poor software selection by others has left me with a mess to clean up. So, I'm going to give this a go if I end up being allowed the time to. I'll post progress/code here for others if I can manage to make progress. I'll need some pointers with using the FTView COM API to get/set tag values. The recipe file parsing is no problem.

This FTView SE project that was supplied to me defines tags as residing on the device. I am able to read the System\Second tags as shown in sample code so that confirms that some things are working. But I am not able to read/set the device tags I need access to. Code below produces the following message when I hover on the last line: myTag.Value = <Unable to read the tag '/::StripName\00'.>

Dim myGroup As TagGroup
Dim myTag As Tag
Set myGroup = Application.CreateTagGroup(Me.AreaName)
Set myTag = myGroup.Add("StripName\00")
myGroup.Active = True
Set myTag = myGroup.Item("StripName\00")
myTag.Value = "Test"

In the studio I can see the following info for the tag definition used above:
Name: StripName\00
Type: String
Security: *
Description: Strip Name - Strip 00
Length: 15
DataSource Type: Device
Address: [GritTape]Grit_Tape_StripName[0]

Any ideas on how to write a value to this tag?
 
In FactoryTalk View Studio I can add recipes to my project/application using the tree view. Those recipies can then be restored/downloaded in the running Client application by use of the Recipe control. The Recipe control only lists the recipes that were added to the application using the tree view in Studio.
My goal is to allow a programmer to drop recipes into a Windows folder and have the operator restore/download recipies from that Windows folder without having to open the appliction in SE View Studio to add the recipies. I can get the path/filename, just need a way to have it open in the client.

I do not know about your application so pardon me for asking why you want to add recipes through such an elaborate manner. There isn't any need to open FTView Studio to add new Recipes. One can add new recipes in the running client itself via the Recipe Object.

I usually create Tags for Storing all the Recipe data. I then use a Button and name it "Download" to trigger the movement of these data from the recipe tags to the actual tags.
So to create a new recipe one just has to:
1.Enter all the data for the new Recipe
2.Then open the Recipe Object
3.Type a new file name in the shown field
4. Click Save

Only one extra step gets added in this method which is that the operator has to click the download button after restoring the required recipe.
 
Last edited:
Thanks, but the length of the recipe does not permit this to be done as you suggested (in some cases 3000 tags), where a user inputs the data manually through the client and saves a new recipe. The approach suggested by rdrast and TCon was to parse the text-file-based-recipe into the tags. It sounds easy, especially because the files I have to parse clearly describe the tag names and values:
!
1,"PartNumberA" !StripName\00
2,4.000 !Recipe\00\00
3,12.0000 !Recipe\00\01
4,2.900 !Recipe\00\02
5,10.200 !Recipe\00\03
51,"PartNumberB" !StripName\01
52,4.000 !Recipe\01\00
53,12.000 !Recipe\01\01

So, back to my question. The suggested approach is to parse these values into the tags. When I tried, I received the noted error. In other words, I don't know how to perform step 1 of your 4 step solution with myTag.Value. The client graphical interface, that was designed by a contractor and given to me, has a screen which displays all of the tags when a user selects a recipe from the Recipe control, pushes a Restore button, and then a Download button. But this only works for recipes that were added in the FTView Studio. I'd like to replicate Tcon's approach using a file browser to select a file and then parse it into the tags. Any suggestions on why I'm getting errors when trying to set tag values like this?

Dim myGroup As TagGroup
Dim myTag As Tag
Set myGroup = Application.CreateTagGroup(Me.AreaName)
Set myTag = myGroup.Add("StripName\00")
myGroup.Active = True
Set myTag = myGroup.Item("StripName\00")
myTag.Value = "Test"
 
Huh, I just found that the test code above, to write a tag value, works when I run it in the original FTView SE project delivered by the contractor. I had imported and renamed a testing copy of the original project to mess with, so I wouldn't risk breaking the original one delivered by the contractor. But I checked and found that the copied/imported project doesn't work, with zero changes to it.
 
Thanks for the help. Below code takes file name that is typed or barcode-read into a text box on the client. It parses the Unicode file into an array of strings for each line. Then each line is searched to see which tag group it is setting and what the value is.


Private Sub Button18_Released()
Dim myWorkDir As String
myWorkDir = "c:\temp\"
Dim myFileName As String
myFileName = Me.StringInput1.Value
Dim myTags() As String
myTags = LoadLanguageFileUnicode(myWorkDir & myFileName & ".rcp")
Dim TagGroup1NameRegEx As String
TagGroup1NameRegEx = "StripName\\\d\d"
Dim TagGroup1ValueRegEx As String
TagGroup1ValueRegEx = """(.*?)"""
Dim TagGroup2NameRegEx As String
TagGroup2NameRegEx = "Recipe\\\d\d\\\d\d"
Dim TagGroup2ValueRegEx As String
TagGroup2ValueRegEx = "\,(\-)?(\.)?\d+(\.\d+)?"
Dim regEx As New VBScript_RegExp_55.RegExp
regEx.IgnoreCase = False
regEx.Global = False
Dim myMatches
Dim myGroup As TagGroup
Dim myTag As Tag
Set myGroup = Application.CreateTagGroup(Me.AreaName)
myGroup.Active = True
Dim TagGroupName As String
Dim TagGroupValue As String
For i = 0 To UBound(myTags)
'find StripName tag group
regEx.Pattern = TagGroup1NameRegEx
Set myMatches = regEx.Execute(myTags(i))
For Each Match In myMatches
TagGroupName = Match.Value

'get the tag value
regEx.Pattern = TagGroup1ValueRegEx
Set myMatches = regEx.Execute(myTags(i))
For Each Match2 In myMatches
TagGroupValue = Replace(Match2.Value, Chr(34), "")
Next

'assign the tag
Set myTag = myGroup.Add(TagGroupName)
myTag.Value = TagGroupValue
Next


'find Recipe tag group
regEx.Pattern = TagGroup2NameRegEx
Set myMatches = regEx.Execute(myTags(i))
For Each Match In myMatches
TagGroupName = Match.Value

'get the tag value
regEx.Pattern = TagGroup2ValueRegEx
Set myMatches = regEx.Execute(myTags(i))
For Each Match2 In myMatches
TagGroupValue = Replace(Match2.Value, ",", "")
Next
'assign the tag
Set myTag = myGroup.Add(TagGroupName)
myTag.Value = TagGroupValue
Next
Next


End Sub

Private Function LoadLanguageFileUnicode(strPath As String) As String()
Dim lngFileNum As Long
Dim strResult() As String
Dim bytResults() As Byte
Dim iCounter As Long
On Error GoTo ErrorHandler
lngFileNum = FreeFile()
Open strPath For Binary Access Read As #lngFileNum
ReDim bytResults(LOF(lngFileNum) - 1)
Get #lngFileNum, , bytResults
Close #lngFileNum
If bytResults(0) = 255 And bytResults(1) = 254 Then 'UTF16LE
strResult = Split(Mid$(bytResults, 2), vbCrLf)
ElseIf bytResults(0) = 254 And bytResults(1) = 255 Then 'UTF16BE Unicode format not supported
Exit Function
ElseIf bytResults(0) = 239 And bytResults(1) = 187 And bytResults(2) = 191 Then 'UTF8 Unicode format not supported
Exit Function
End If

LoadLanguageFileUnicode = strResult()
Exit Function
ErrorHandler:
End Function
 

Similar Topics

I have a field device (flowmeter) using HART wired to a 200SP HART input card. I need to read flow totalization. Configuring the actual card to...
Replies
2
Views
574
MELSEQ "intelligent modules" configuration, programmatically resetting the CPU Hello. This is for the Mitsubishi experts, and thanks in advance...
Replies
5
Views
1,010
So instead of copying a bat file manually to a panelview plus during commissioning of a project, I would like to save the bat file into the...
Replies
5
Views
1,325
I'd like to have one of my displays tell what the firmware version is of the panelview that its running on without having to quit the application...
Replies
0
Views
581
Hi Guys, I'm trying to get the IP address of my L33ER Compactlogix to show up on my PV+ 600. I know about answer 26779 and have tried it but I...
Replies
17
Views
2,676
Back
Top Bottom