GE Cimplicity 2022 Embedded Graphics & $OBJECT usage

nicherbert

Member
Join Date
Apr 2024
Location
Emmen
Posts
21
Hello everyone!

This is my first time posting, though I have been to this site a few times hunting for some random problem like we all do. I have run into an issue myself. I am starting out now using Cimplicity 2022 and attempting to leverage Classes/Objects along with the Graphic Templates that go along with it. I apologize for the lengthy thread, but the details are what is keeping me from being successful.

The issue I am running into is a scenario that I'm fighting to overcome. We have defined several Classes, some of which leverage embedded (Composite Members) classes within another. Several things I ran into that have been difficult to overcome, and now I'm looking for a good workaround, but each step of the way, I am finding what I think are bugs in Cimplicity, or I don't quite understand how to leverage the tool. I have read the documentation, but as normal, the help files and examples don't go quite far enough to do what should be possible.

First issue I ran into was related to the CIMPLICITY reserved variables. We are using an OPC-UA server and attempting to build the address by assigning parameters to do so. Part of doing this is to leverage the Object instance to make this work. There are 3 variables we are looking at: $ADDRESS, $OBJECT, and $ID. I will be using the following information in my examples to best explain what I am seeing:
  • VALVE Class - this has all the typical parameters, but also has Data Items STS_OPEN, STS_CLOSED, CMD_OPEN, CMD_CLOSED
  • TANK Class - this has all the typical parameters, has it's own Data Items LEVEL and HI_ALARM, but also has composite members INLET and OUTLET that are of type VALVE.
When we create a Tank Object called TANK1, we get the following points created:
  • [PATH].TANK1.LEVEL
  • [PATH].TANK1.HI_ALARM
  • [PATH].TANK1.INLET.STS_OPEN
  • [PATH].TANK1.INLET.STS_CLOSED
  • [PATH].TANK1.INLET.CMD_OPEN
  • [PATH].TANK1.INLET.CMD_CLOSED
  • [PATH].TANK1.OUTLET.STS_OPEN
  • [PATH].TANK1.OUTLET.STS_CLOSED
  • [PATH].TANK1.OUTLET.CMD_OPEN
  • [PATH].TANK1.OUTLET.CMD_CLOSED
What I have found is this:
  • $ADDRESS: This does not seem to be configured automatically at any point by CIMPLICITY that I can find or have tested. I'm not sure why it's reserved, but leveraging it doesn't seem to be useful accept if we want to define it as a parameter to fill in.
  • $OBJECT: This works great most of the time. When we have an Object created of a class instance, this is the Object name. Using the example and looking at "[PATH].TANK1.LEVEL", we find that $OBJECT would be TANK1. This works great to build the path accordingly for the OPC UA Address. For scripting, this is also great. Now, this is where it gets weird. When we look at "[PATH].TANK1.INLET.STS_OPEN", we find that $OBJECT is now TANK1.INLET. Now, this seems to make sense, except when you look at what $ID does as well.
  • $ID: This also works great most of the time. Using the same examples from before "[PATH].TANK1.LEVEL", we find that $ID is LEVEL just as you would expect. Now moving down into a composite member, this changes. Looking at "[PATH].TANK1.INLET.STS_OPEN", we find that $ID is now INLET.STS_OPEN.

As you can see, $OBJECT and $ID have duplicate items, so if using {$OBJECT}.{$ID} to build an address, we have an issue when using composite members. To solve this issue, we can take advantage of the $ADDRESS variable and in the parameter definition of the object, we can assign the {$OBJECT} or {..\$OBJECT} to the $ADDRESS variable and instead of using {$OBJECT}.{$ID} to build the OPC address, we can simply use {$ADDRESS}.[Composite Member Data Item Name]. Ok, so for the point itself, this works great and the point has the correct OPC path. Now, onto the graphics.

On the graphics front, we also build up Class templates to use. In our example, we could leverage the VALVE independently, and when done, we have no issue with the display. Keep in mind, building graphic templates requires you define $OBJECT and set it public. This is so we get the Object Instance name as the $OBJECT variable to use in our design. Again, as a standalone instance, this works great. Now, when we go to embedded one graphic template into another (we are using a linked copy) as in the TANK1 case, the TANK1 items work great, but the composite members do not. One would think the $OBJECT variable would take on the parent $OBJECT and be passed down, or built up to also include the compositive member name as it does in the above example, but here, we find that not to be the case. Instead, $OBJECT is just blank (or not defined, not sure which). You can note this by looking at Expressions and Point Control Panel to see the path is not fully formed. Ok, so simple enough, I can set the $OBJECT parameter by passing {..\$OBJECT} that will, in this case, pass TANK1 to the graphic template and then I can build the rest using another cOBJECT variable since I know what that item is easily (remember, reusing of this screen means we don't know if this is TANK1 or TANK9. For graphic display purposes, everything shows up great because the $OBJECT string has the {..\$OBJECT} value replaced by the actual object instance name. Now the problem, once again, is that in scripting, when I get the $OBJECT of the composite member, I am now getting {..\$OBJECT} instead of the replaced value.

I have been looking at scripting to solve this problem, but the documentation is very weak, and figuring out how to reference the composite member graphic and assign the $OBJECT variable on a SCREEN OPEN event is also not going well. Seems like every point I turn, I run into some sort of problem. So here I am, hoping I'm not the only person that has run into this sort of issue before.

So, Im curious, has anyone actually leveraged using embedded classes as points and also with graphics successfully, and how have you done it? Am I just doing something wrong here, or is there a bug or setting in Cimplicity 2022 that I am not finding?
 
I'm not sure if there is a better way, but this is what I have done. It would be nice if the built in method would work, but here is what I did.

I changed by OPC address by using {$OBJECT} instead of {$ADDRESS}, then appending the composite member name directly onto the end. This works standalone and when it's embedded. Next, on the graphics side, I removed the $ADDRESS parameter and only use $OBJECT. I create the $OBJECT public variables on the main screen/object like it requests we normally do. When the graphics is standalone and not embedded within another, this works fine as Cimplicity automatically assigned the value. When it's embedded, I went ahead and made an OPEN SCREEN event to assign the $OBJECT variable of the object on the screen. This was a bit tricky, and I ended up using obselete functions since the newer functions don't seem to permit access (or none that I could easily fine to do it - again, the online help document is pretty weak). I ended up using CimObject's, and with cimGetScriptOwner(), I have access to the GetObject() procedure that allows me to select it by name. To make this work, you have to understand the entire tree of objects on your screen, and all objects should be named (Under General -> Name). Many times, I had grouped items, so if you are referring to something that is nested in a group, you will need to first get the group object by name, then the actual object you want (also by name). If I have a group called Parameters, and in this group I have P1, P2, P3, etc..., and the script is running on the main screen, then the code would look like this:

Code:
Dim oObject As GefObjectVariable
Dim cObject As CimObject

Set oObject = CimGetObject.GetVariable("$OBJECT") 'Variable assigned automatically by Cimplicity
Set cObject = CimGetScriptOwner() 'Could be CimGetRootObject()

cObject.GetObject("Parameters").GetObject("P1").GetVariable("$OBJECT").Value = oObject.Value

I don't know if this was intended or not, but that is the ONLY way I have been able to find a way to make this work effectively. As you can see, this is very meticulous and not exactly easily figure out. For those looking, use General Tab of the object and look for the name. If it's a group, you can use the Group tab to find the tree of objects you need to navigate. Any other more experienced Cimplicity programmers want to chime in and confirm this, or have a better way?
 
hi,
I am guessing you are trying to use a class object with graphic. You can create a screen file to put the object graphic in and assign a variable called "$Object", check "Public", and give it a general name eg. "Tank". Then save. Next, fill out the screen file path and name (browser..) in the class's tab general ->Graphics file. Create an class object by that class. In the other screen, under drawing menu, insert a class object. Select that class object. The graphic should show up in the screen with the "$Object" variable automatically filled with the object's ID. Now you are going to deal with then variable "$object" instead of object's name. If you have different graphics but similar objects, you can put them in the same screen file. After you insert a class object, right click on the graphic, there will be optional graphics let you choose. The names are the general names. eg. TankType1, TankType2.
 

Attachments

  • aa.jpg
    aa.jpg
    24.5 KB · Views: 4
hi,
I am guessing you are trying to use a class object with graphic. You can create a screen file to put the object graphic in and assign a variable called "$Object", check "Public", and give it a general name eg. "Tank". Then save. Next, fill out the screen file path and name (browser..) in the class's tab general ->Graphics file. Create an class object by that class. In the other screen, under drawing menu, insert a class object. Select that class object. The graphic should show up in the screen with the "$Object" variable automatically filled with the object's ID. Now you are going to deal with then variable "$object" instead of object's name. If you have different graphics but similar objects, you can put them in the same screen file. After you insert a class object, right click on the graphic, there will be optional graphics let you choose. The names are the general names. eg. TankType1, TankType2.
I am indeed doing that. For most class objects with graphics, this works very well. The issue I am running into is when I put a class object within a class object (as a composite member), then that is where $OBJECT variable breaks down. The breakdown occurs mostly with using it in the class object definition to build the OPC address, as the $OBJECT variable isn't just the name of the object instance (the ID), but also the name of the composite member name as well (i.e. Tank1.Valve1). We also use $ID, and this should just be the Data Item of the class object, but when you are dealing with composite members, this will be the full composite member name and data item (i.e. Valve1.OPEN_STATUS). When this occurs, we cannot use {$OBJECT}.{$ID} to build an OPC Address or tag name from, as the composite member name is duplicated (i.e. the value would then be Tank1.Valve1.Valve1.OPEN_STATUS). Does that make sense? That is the specific issue I ran into. Quite frustrating. When doing it with the composite member setup, one way to "fix" this issue would be to define the $OBJECT (or what we were trying to do) by using $ADDRESS (a reserved word in Cimplicity to set the base address), but if we type in {$OBJECT} as the value to enter for $ADDRESS, or in the composite member case, {..\$OBJECT}, this works fine when it's truly a composite member only. If we use it as a stand along object with graphic, the $ADDRESS variable has {$OBJECT} in the path because Cimplicity doesn't do multiple replacement steps, only once. Hence the need for a script to update it.

I know it's difficult to explain the exact situation I am running into here, and I hope that clarifies things.
 
Ok, basically you are trying to pass variable value, instead of replacement string, from group level to its child which has the same variable. At this point, I believe scripting is the only way to achieve this. You can do that at Cimedit using smart object event to assign permanently or Cimview at opening screen or other events every time.
Here is the code if you would like to take a look. Use "item" property to scan the child objects and no worries about their names.

Option Compare Text
Option CStrings On
Sub OnScreenOpen()

On Error GoTo errMsg
Dim grpObj As GefObject
Set grpObj = CimGetScreen.Object.Objects.Item("Parameters")

For i = 0 To grpObj.Objects.count-1

Set objVar = CimGetObject.Objects.Item(i).GetVariable("$Object")

If IsNull(objVar) Then
GoTo Skip
Else
grpObj.Objects.Item(i).GetVariable("$Object").Value = grpObj.GetVariable("$Object").Value
End If
Skip:
Next
GoTo Done
errMsg:
MsgBox "Line: " & Erl & "\n" & Error(Err)
Err = -1
Done:

CimGetScreen.refresh false
End Sub
 

Similar Topics

Hi all, I am having issues accessing my Cimplicity software - the site code changed after re-install and I am no longer able to attain a new key...
Replies
10
Views
176
Hi good day Everyone, I have a cimplicity v10 project with 7 to 8k tags communicating with AB PLC through OPC and Rslinx classic. I have this...
Replies
3
Views
225
Hi All, I am trying to program some new Versamax micro PLCs through PAC using some programs saved in our archive however whenever i go to import...
Replies
2
Views
128
Hi All, Im using Cimplicity 8.2. after the last restart Server Scada, the PTDL_RP process can not running. so Process can not be login to database...
Replies
2
Views
164
Good morning, I have a Emerson/GE PLC with Cimplicity SCADA. I need to export data of a specific point/object to a CSV file and load the CSV file...
Replies
7
Views
289
Back
Top Bottom