Author Topic: Changing a sub property  (Read 1954 times)

paxel

  • Newbie
  • *
  • Posts: 1
    • View Profile
Changing a sub property
« on: December 14, 2018, 03:33:31 PM »
I have been using the following VB code to convert PLC tags to their modbus equivalent. When I run this code it looks in the properties of all the controls on a form, and checks if they start with PLCaddress, and will look in the CSV to see if that tag has an associated modbus address. This has worked great up until trying it with the Analog Value Display control. Because the "PLCAddress" Property is a subproperty of "PLCAddressValue" I am not sure how to access it.

    Public Sub FixPLCAddresses(ByVal ctrlParent As Control)
        'Call this from a form to translate the PLC Tags to the Modbus addresses.
        ' ie Call FixPLCAddresses(me), in the Form_Load procedure.
        Dim I As Integer, propertyIndex As Integer

        For I = 0 To ctrlParent.Controls.Count - 1
            Dim p() As Reflection.PropertyInfo = ctrlParent.Controls(I).GetType().GetProperties
            For propertyIndex = 0 To p.Length - 1
                If (p(propertyIndex) IsNot Nothing) AndAlso (Not String.IsNullOrEmpty(p(propertyIndex).Name)) AndAlso ((p(propertyIndex).PropertyType) Is GetType(String)) Then
                    '* Does this property start with "PLCAddress"?
                    If p(propertyIndex).Name.IndexOf("PLCAddress", StringComparison.CurrentCultureIgnoreCase) = 0 Then
                        'Dim value As String = LookupModbusAddr(Me.Controls(i).Name & "." & p(propertyIndex).Name)
                        Dim value As String = LookupModbusAddr(p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing))
                        p(propertyIndex).SetValue(ctrlParent.Controls(I), value, Nothing)

                    End If
                End If
            Next
            'Fix anything in a container control, such as a panel or groupbox
            If ctrlParent.Controls(I).HasChildren Then
                FixPLCAddresses(ctrlParent.Controls(I))
            End If
        Next

    End Sub

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #1 on: December 14, 2018, 03:59:38 PM »
You will have to check the property type to see if it is a String or a MfgControl.AdvancedHMI.Drivers.PLCAddressItem type. if it is the latter, you will then have to set the PLCAddress property of that object.

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #2 on: December 19, 2018, 11:58:55 AM »
Archie,

I working with Paxel on trying to get this to work, but we're having trouble setting the sub property.  We are able to get the Property value, but the set is not working.  Also, it seems the sub properties are only available if there is a value, so I know I'll have to add some checks for that.

Was wondering if you had any helpful tips on how we can do this?

Our goal for this is to be able to use tag names in the software to make it more readable and then have them converted to Modbus addresses on the fly.  If it comes down to it we can always get the same look with a basic label and the issue would go away for now.

Thanks for any help you can provide.

Rich

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #3 on: December 21, 2018, 12:45:42 PM »
This may be what you are trying to do:
Code: [Select]
    Public Sub FixPLCAddresses(ByVal ctrlParent As Control)
        'Call this from a form to translate the PLC Tags to the Modbus addresses.
        ' ie Call FixPLCAddresses(me), in the Form_Load procedure.
        Dim I As Integer, propertyIndex As Integer

        For I = 0 To ctrlParent.Controls.Count - 1
            Dim p() As Reflection.PropertyInfo = ctrlParent.Controls(I).GetType().GetProperties
            For propertyIndex = 0 To p.Length - 1
                If (p(propertyIndex) IsNot Nothing) AndAlso (Not String.IsNullOrEmpty(p(propertyIndex).Name)) Then

                    If ((p(propertyIndex).PropertyType) Is GetType(String)) Then
                        '* Does this property start with "PLCAddress"?
                        If p(propertyIndex).Name.IndexOf("PLCAddress", StringComparison.CurrentCultureIgnoreCase) = 0 Then
                            Dim value As String = LookupModbusAddr(p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing))
                            p(propertyIndex).SetValue(ctrlParent.Controls(I), value, Nothing)
                        End If
                    ElseIf (p(propertyIndex).PropertyType Is GetType(MfgControl.AdvancedHMI.Drivers.PLCAddressItem)) Then
                        '* Does the PCAddress property point to an object instance?
                        If p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing) IsNot Nothing Then
                            Dim PLCAddressObject = p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing)
                            Dim SubProperty() As Reflection.PropertyInfo = PLCAddressObject.GetType().GetProperties
                            '* Check all of the properties of the PLCAddressItem
                            For SubIndex = 0 To SubProperty.Length - 1
                                If ((SubProperty(SubIndex).PropertyType Is GetType(String) AndAlso SubProperty(SubIndex).Name.IndexOf("PLCAddress") >= 0)) Then
                                    '* Set the value of the sub proprty
                                    SubProperty(SubIndex).SetValue(PLCAddressObject, "NewValue", Nothing)
                                End If
                            Next
                        End If
                    End If
                End If

            Next
            'Fix anything in a container control, such as a panel or groupbox
            If ctrlParent.Controls(I).HasChildren Then
                FixPLCAddresses(ctrlParent.Controls(I))
            End If
        Next

    End Sub

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #4 on: January 09, 2019, 08:16:54 AM »
Archie,

Here is the final code and it works well to replace all of the Tag names with the Modbus addresses.

Code: [Select]
Public Sub FixPLCAddresses(ByVal ctrlParent As Control)
        'Call this from a form to translate the PLC Tags to the Modbus addresses.
        ' ie Call FixPLCAddresses(me), in the Form_Load procedure.
        Dim I As Integer, propertyIndex As Integer, SubIndex As Integer

        For I = 0 To ctrlParent.Controls.Count - 1
            Dim p() As Reflection.PropertyInfo = ctrlParent.Controls(I).GetType().GetProperties
            For propertyIndex = 0 To p.Length - 1
                If (p(propertyIndex) IsNot Nothing) AndAlso (((p(propertyIndex).PropertyType) Is GetType(String) Or (p(propertyIndex).PropertyType) Is GetType(MfgControl.AdvancedHMI.Drivers.PLCAddressItem))) Then
                    '* Does this property start with "PLCAddress"?
                    If p(propertyIndex).Name.IndexOf("PLCAddress", StringComparison.CurrentCultureIgnoreCase) = 0 AndAlso (p(propertyIndex).PropertyType) Is GetType(String) Then
                        'Dim value As String = LookupModbusAddr(Me.Controls(i).Name & "." & p(propertyIndex).Name)
                        Dim value As String = LookupModbusAddr(p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing))
                        If value <> "" Then p(propertyIndex).SetValue(ctrlParent.Controls(I), value, Nothing)

                    ElseIf (p(propertyIndex).PropertyType Is GetType(MfgControl.AdvancedHMI.Drivers.PLCAddressItem)) Then
                        '* Does the PCAddress property point to an object instance?
                        If p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing) IsNot Nothing Then
                            Dim PLCAddressObject = p(propertyIndex).GetValue(ctrlParent.Controls(I), Nothing)
                            Dim SubProperty() As Reflection.PropertyInfo = PLCAddressObject.GetType().GetProperties
                            '* Check all of the properties of the PLCAddressItem
                            For SubIndex = 0 To SubProperty.Length - 1
                                If ((SubProperty(SubIndex).PropertyType Is GetType(String) AndAlso SubProperty(SubIndex).Name.IndexOf("PLCAddress") >= 0)) Then
                                    '* Set the value of the sub proprty
                                    Dim subvalue As String = LookupModbusAddr(SubProperty(SubIndex).GetValue(PLCAddressObject, Nothing))
                                    SubProperty(SubIndex).SetValue(PLCAddressObject, subvalue, Nothing)
                                End If
                            Next
                        End If
                    End If
                End If
            Next
            'Fix anything in a container control, such as a panel or groupbox
            If ctrlParent.Controls(I).HasChildren Then
                FixPLCAddresses(ctrlParent.Controls(I))
            End If
        Next

    End Sub

All of the PLCAddress properties get updated, however when I run my program the AnalogValueDisplay still gives an error for the original tag name. 

My form has DisableSubscriptions=true on the ComComponent.  In form Load I run the FixPLCAddress routine and then turn DisableSubscritions=false in code.

The only way it seems to work is if I set the ComComponent for the AnalogValueDisplay =None on the form, run the FixPLCAddress routine and then set the ComComponent and set DisableSubscritions=false in form load.

For a basic label it works straight away, but appears that the PLCAddressItem Type is treated differently on creation of the form.

Let me know if you have any thoughts on how I may be able to get around this.

Thanks,

Rich

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #5 on: January 09, 2019, 08:56:01 AM »
There may be a better way to approach this. As far as I know every control passes its subscriptions through a SubscriptionHandler. Within the SubscriptionHandler you can check for the address replacement.

At line 102 :                         Dim temp As New SubscriptionDetail(PLCAddress, callBack)
the replacement can be done.

At line 236 :                If (e.PlcAddress Is Nothing) OrElse (String.Compare(address, e.PlcAddress, True) = 0) Then
a reverselookup will need to be done.


I will look at this more in depth later. The address alias may be incorporated into the SubscriptionDetail object.

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #6 on: January 09, 2019, 09:55:24 AM »
Archie,

I appreciate you looking at this for me.  My lookup is from a dictionary object, so creating the reverselookup will be simple enough.

The subscriptionHandler code looks interesting, but also a bit more involved than I'd be willing to go after on my own.  If you can provide guidance then I'm sure we can make it work.

Thanks,

Rich

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #7 on: January 09, 2019, 08:58:01 PM »
This will be a first go round:

1) In the AdvancedHMIControls project, replace SubscriptionDetail.vb and SubscriptionHandler.vb with the 2 attached files
2) In the AdvancedHMI project add the attached file TagAlias.txt
3) Set the property of CopyToOutputDirectory for TagAlias.txt to CopyIfNewer
4) Edit TagAlias.txt using the pattern of the sample items

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #8 on: January 11, 2019, 09:19:43 AM »
Archie,

This works perfectly, even with my original code commented out.

I'm glad you said this was a first go around, because I want to give you a bit more background.

We're using a PAC3000, from AutomationDirect and the Productivity Suite creates a CSV file of the tags every time you save the project, including the Modbus addresses.  In my code I'm querying this csv file to create my lookup dictionary object.

If we do have to use this separate txt file then we'll come up with a way to create is using a macro or something.

Let me know your thoughts and we appreciate all of the help you've given us and others.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #9 on: January 11, 2019, 09:50:36 AM »
What does the file look like from Productivity Suite. Maybe it is easy enough to use that file directly.

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #10 on: January 11, 2019, 11:52:38 AM »
See the attached for the file.

See below for the routine we use to query it.

Code: [Select]
Public Sub LoadFromSpreadsheet()
        Try
            'Create the Tags required by this object
            Dim dbPLCTags As clsDataBase = New clsDataBase()
            dbPLCTags.OpenDatabase("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""D:\Visual Studio Projects\CTO Tester\Data\"";Extended Properties=""text;HDR=Yes;FMT=Delimited""")
            'dbPLCTags.OpenDatabase("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""C:\Users\paxel\Documents\CTO PLc\"";Extended Properties=""text;HDR=Yes;FMT=Delimited""")

            Dim sql As String = "SELECT * FROM [PLC Tags_basic.csv]"
            sql += " Where [MODBUS Start Address] is not null"
            Dim dsTags As DataSet = dbPLCTags.ByQuery(sql, "Tags")
            Dim myRow As DataRow
            ModbusAddressLookup = New Dictionary(Of String, String)
            'Iterate through the list of tags and add an item for each

            For Each myRow In dsTags.Tables(0).Rows
                Try
                    Dim MOD_Prefix As String = ""
                    Dim myType As String = myRow("## System ID")
                    myType = myType.Substring(0, myType.IndexOf("-"))

                    Select Case myType
                        Case "F32"
                            MOD_Prefix = "F"
                        Case "S32"
                            MOD_Prefix = "L"
                        Case Else
                            MOD_Prefix = ""
                    End Select

                    'put all of the tagnames in the Dictionary object in Upper case to prevent mismatch due to case
                    'add leading 0s to contacts adressed 1,2... etc
                    Dim ModAddress As String = (myRow("MODBUS Start Address"))
                    Dim x As Byte = 0
                    If ModAddress.Length < 5 Then
                        For x = 1 To 4
                            If ModAddress.Length < 5 Then
                                ModAddress = "0" & ModAddress
                            End If
                        Next

                    End If
                    ModbusAddressLookup.Add(myRow("Tag Name").ToString.ToUpper, MOD_Prefix & ModAddress)
                    TagNameLookup.Add(MOD_Prefix & ModAddress, myRow("Tag Name").ToString.ToUpper)

                    'myPLCconn.Subscribe(MOD_Prefix & ModAddress, 1, 500, AddressOf TagProcessor)

                Catch ex As Exception
                    Logger.WriteToLog(ex.Message, True, True, ex.StackTrace, Me.ToString & " LoadFromSpreadsheet Row Processing")
                End Try
            Next
            dbPLCTags.CloseDatabase()
        Catch ex As Exception
            Logger.WriteToLog(ex.Message, True, True, ex.StackTrace, Me.ToString & " LoadFromSpreadsheet Row Processing")
        End Try
    End Sub

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #11 on: January 11, 2019, 12:11:54 PM »
In SubcriptionHandler at line 119:

TagAlias.Add(Items(0), Items(1))

The Items(1) can be changed to Items(4), but it looks like there will need to be some further processing on the Modbus address. Kind of merge your code to end up with something like this:

Dim MbAddress as string=Items(4)
'**** Your processing code here to modify MbAddress
.
.
.
TagAlias.Add(Items(0),MAddress)

rbelknap

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
Re: Changing a sub property
« Reply #12 on: January 14, 2019, 12:59:20 PM »
Archie,

This worked out well.  I had to add some code to get by the headers, to eliminate the quotes in the files, and also not to process any lines without Modbus addresses.

Code: [Select]
                        If Not TagAliasFileRead Then
                            If (System.IO.File.Exists(".\PLC Tags_basic.csv")) Then
                                TagAlias = New Dictionary(Of String, String)
                                Using sr As New System.IO.StreamReader(".\PLC Tags_basic.csv")
                                    Dim Line As String
                                    Dim Items() As String
                                    While Not sr.EndOfStream
                                        Line = sr.ReadLine()
                                        Items = Line.Split(","c)
                                        If Items(0).Substring(1, 1) <> "#" AndAlso Items(4) <> "" Then
                                            If Items.Count > 1 Then
                                                '* Item(0)=Alias, Item(1)=PLC Address
                                                Dim MbAddress As String = Items(4)
                                                Dim MOD_Prefix As String = ""
                                                Dim myType As String = Items(0)
                                                myType = myType.Substring(0, myType.IndexOf("-"))

                                                Select Case myType
                                                    Case "F32"
                                                        MOD_Prefix = "F"
                                                    Case "S32"
                                                        MOD_Prefix = "L"
                                                    Case Else
                                                        MOD_Prefix = ""
                                                End Select

                                                'put all of the tagnames in the Dictionary object in Upper case to prevent mismatch due to case
                                                'add leading 0s to contacts adressed 1,2... etc
                                                'Dim ModAddress As String = (myRow("MODBUS Start Address"))
                                                Dim x As Byte = 0
                                                If MbAddress.Length < 5 Then
                                                    For x = 1 To 4
                                                        If MbAddress.Length < 5 Then
                                                            MbAddress = "0" & MbAddress
                                                        End If
                                                    Next

                                                End If
                                                MbAddress = MOD_Prefix & MbAddress
                                                TagAlias.Add(Items(1).Substring(1, Items(1).Length - 2), MbAddress) ' Items(4))
                                            End If
                                        End If
                                    End While
                                End Using
                            End If
                            TagAliasFileRead = True
                        End If

Thanks for all of the help.

Alpaslan

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Changing a sub property
« Reply #13 on: February 02, 2019, 01:44:10 PM »
I like you guys. You are very impressive and brilliant.

I am using Mitsubishi FX5U with ModbusTCP.

Aliases works while reading values from PLC however doesn't work while writing to PLC.

I mean; an alias in TagAlias.txt is Counter,40001@L
when i use AnalogValueDisplay with properties PLCAddressKeypad is Counter and PLCAddressValue is Counter
Value is shown in analog value display however when i try to change value "Failed to write value. Invalid address Counter - startIndex" error is displayed.

If i use PLCAddressKeypad is 40001@L no problem is occured.
« Last Edit: February 02, 2019, 02:04:17 PM by aakici »
One step at a time baby, One step at a time.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5269
    • View Profile
    • AdvancedHMI
Re: Changing a sub property
« Reply #14 on: February 13, 2019, 08:51:53 AM »
I like you guys. You are very impressive and brilliant.

I am using Mitsubishi FX5U with ModbusTCP.

Aliases works while reading values from PLC however doesn't work while writing to PLC.

I mean; an alias in TagAlias.txt is Counter,40001@L
when i use AnalogValueDisplay with properties PLCAddressKeypad is Counter and PLCAddressValue is Counter
Value is shown in analog value display however when i try to change value "Failed to write value. Invalid address Counter - startIndex" error is displayed.

If i use PLCAddressKeypad is 40001@L no problem is occured.
This is currently being worked on. Hopefully this week there will be an update with a fix that makes tag aliases work on writing also.