Results 1 to 19 of 19

Thread: Should I use a Class instead of a Function

  1. #1

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Should I use a Class instead of a Function

    I am still learning VB.Net and been reading up on various topics.

    I have the following code. The code represents an Analog Type that is used in a PLC program. (The code creates the PLC objects that are imported into the PLC program.) The VB code "auto generates" the code for the PLC so that the user does not have to do it manually. There are also Drive types, etc.

    One parameter, the Device Number, is passed to the function. The function then calculated the addresses of the various elements and builds the string as required by the PLC.

    I have written the code as a Function. Would it be better to write it as a Class and then reference the attributes?


    Code:
    #Region "ANL01m - Analog Input"
    
        '~~> ANL01m Global Var
        Public Function DUT_ANL(strDeviceNumber As String, strChannel As String) As String
    
            Dim strDUTValue As String = ""
    
            Dim intDevicenumber As Int16 = CType(strDeviceNumber, Int16)
    
            Dim strCommandAddr As String = CType(0 + (2 * intDevicenumber), String)
            Dim strAlarmAddr As String = CType(1 + (2 * intDevicenumber), String)
            Dim strStatusAddr As String = CType(1000 + (2 * intDevicenumber), String)
            Dim strBusInputAddr As String = CType(2000 + (2 * intDevicenumber), String)
            Dim strInterlocksAddr As String = CType(3000 + (2 * intDevicenumber), String)
            Dim strFirstUpAddr As String = CType(4000 + (2 * intDevicenumber), String)
            Dim strAuxilaryAddr As String = CType(5000 + (2 * intDevicenumber), String)
            Dim strAnalog_InAddr As String = CType(6000 + (2 * intDevicenumber), String)
            Dim strDelay_HLAddr As String = CType(7000 + (2 * intDevicenumber), String)
            Dim strDelay_HHLLAddr As String = CType(7001 + (2 * intDevicenumber), String)
            Dim strNo_ErrorsAddr As String = CType(8000 + (2 * intDevicenumber), String)
            Dim strLLow_LimitAddr As String = CType(9000 + (2 * intDevicenumber), String)
            Dim strLow_LimitAddr As String = CType(10000 + (2 * intDevicenumber), String)
            Dim strPV_ValueAddr As String = CType(11000 + (2 * intDevicenumber), String)
            Dim strHHigh_LimitAddr As String = CType(12000 + (2 * intDevicenumber), String)
            Dim strHigh_LimitAddr As String = CType(13000 + (2 * intDevicenumber), String)
            Dim strHysteresis_ValueAddr As String = CType(14000 + (2 * intDevicenumber), String)
            Dim strReal_ValueAddr As String = CType(15000 + (2 * intDevicenumber), String)
    
            'Command Word
            Dim strCommand = "Command: R" & strCommandAddr
            Dim strBypass_Req = "Bypass_Req: R" & strCommandAddr & ".0"
            Dim strCommand_9 = "Command_9: R" & strCommandAddr & ".1"
            Dim strReset_Req = "Reset_Req: R" & strCommandAddr & ".2"
            Dim strCommand_B = "Command_B: R" & strCommandAddr & ".3"
            Dim strCommand_C = "Command_C: R" & strCommandAddr & ".4"
            Dim strCommand_D = "Command_D: R" & strCommandAddr & ".5"
            Dim strCommand_E = "Command_E: R" & strCommandAddr & ".6"
            Dim strCommand_F = "Command_F: R" & strCommandAddr & ".7"
            Dim strCommand_0 = "Command_0: R" & strCommandAddr & ".8"
            Dim strCommand_1 = "Command_1: R" & strCommandAddr & ".9"
            Dim strCommand_2 = "Command_2: R" & strCommandAddr & ".A"
            Dim strCommand_3 = "Command_3: R" & strCommandAddr & ".B"
            Dim strCommand_4 = "Command_4: R" & strCommandAddr & ".C"
            Dim strCommand_5 = "Command_5: R" & strCommandAddr & ".D"
            Dim strActive_Req = "Active_Req: R" & strCommandAddr & ".E"
            Dim strSimulate_Req = "Simulate_Req: R" & strCommandAddr & ".F"
    
            Dim strCommandWordString As String = strCommand & vbLf &
                                                  strBypass_Req & vbLf &
                                                   strCommand_9 & vbLf &
                                                    strReset_Req & vbLf &
                                                     strCommand_B & vbLf &
                                                      strCommand_C & vbLf &
                                                       strCommand_D & vbLf &
                                                        strCommand_E & vbLf &
                                                         strCommand_F & vbLf &
                                                          strCommand_0 & vbLf &
                                                           strCommand_1 & vbLf &
                                                            strCommand_2 & vbLf &
                                                             strCommand_3 & vbLf &
                                                              strCommand_4 & vbLf &
                                                               strCommand_5 & vbLf &
                                                                strActive_Req & vbLf &
                                                                 strSimulate_Req
    
    
            'Alarm Word
            Dim strAlarm = "Alarm: R" & strAlarmAddr
            Dim strAlarm_8 = "Alarm_8: R" & strAlarmAddr & ".0"
            Dim strAlarm_9 = "Alarm_9: R" & strAlarmAddr & ".1"
            Dim strAlarm_A = "Alarm_A: R" & strAlarmAddr & ".2"
            Dim strAlarm_B = "Alarm_B: R" & strAlarmAddr & ".3"
            Dim strAlarm_C = "Alarm_C: R" & strAlarmAddr & ".4"
            Dim strBus_FU = "Bus_FU: R" & strAlarmAddr & ".5"
            Dim strAlarm_E = "Alarm_E: R" & strAlarmAddr & ".6"
            Dim strAlarm_F = "Alarm_F: R" & strAlarmAddr & ".7"
            Dim strAlarm_0 = "Alarm_0: R" & strAlarmAddr & ".8"
            Dim strAlarm_1 = "Alarm_1: R" & strAlarmAddr & ".9"
            Dim strAlarm_2 = "Alarm_2: R" & strAlarmAddr & ".A"
            Dim strAlarm_3 = "Alarm_3: R" & strAlarmAddr & ".B"
            Dim strInst_FU = "Inst_FU: R" & strAlarmAddr & ".C"
            Dim strAlarm_5 = "Alarm_5: R" & strAlarmAddr & ".D"
            Dim strAlarm_6 = "Alarm_6: R" & strAlarmAddr & ".E"
            Dim strAlarm_7 = "Alarm_7: R" & strAlarmAddr & ".F"
    
            Dim strAlarmWordString As String = strAlarm & vbLf &
                                                strAlarm_8 & vbLf &
                                                 strAlarm_9 & vbLf &
                                                  strAlarm_A & vbLf &
                                                   strAlarm_B & vbLf &
                                                    strAlarm_C & vbLf &
                                                     strBus_FU & vbLf &
                                                      strAlarm_E & vbLf &
                                                       strAlarm_F & vbLf &
                                                        strAlarm_0 & vbLf &
                                                         strAlarm_1 & vbLf &
                                                          strAlarm_2 & vbLf &
                                                           strAlarm_3 & vbLf &
                                                            strInst_FU & vbLf &
                                                             strAlarm_5 & vbLf &
                                                              strAlarm_6 & vbLf &
                                                                strAlarm_7
    
    
            'Status Word
            Dim strStatus = "Status: R" & strStatusAddr
            Dim strStatus_18 = "Status_18: R" & strStatusAddr & ".0"
            Dim strStatus_19 = "Status_19: R" & strStatusAddr & ".1"
            Dim strBus_Healthy = "Bus_Healthy: R" & strStatusAddr & ".2"
            Dim strStatus_1B = "Status_1B: R" & strStatusAddr & ".3"
            Dim strStatus_1C = "Status_1C: R" & strStatusAddr & ".4"
            Dim strStatus_1D = "Status_1D: R" & strStatusAddr & ".5"
            Dim strStatus_1E = "Status_1E: R" & strStatusAddr & ".6"
            Dim strStatus_1F = "Status_1F: R" & strStatusAddr & ".7"
            Dim strStatus_10 = "Status_10: R" & strStatusAddr & ".8"
            Dim strStatus_11 = "Status_11: R" & strStatusAddr & ".9"
            Dim strStatus_12 = "Status_12: R" & strStatusAddr & ".A"
            Dim strStatus_13 = "Status_13: R" & strStatusAddr & ".B"
            Dim strStatus_14 = "Status_14: R" & strStatusAddr & ".C"
            Dim strStatus_15 = "Status_15: R" & strStatusAddr & ".D"
            Dim strStatus_16 = "Status_16: R" & strStatusAddr & ".E"
            Dim strStatus_17 = "Status_17: R" & strStatusAddr & ".F"
            Dim strStatus_08 = "Status_08: R" & CStr(CSng(strStatusAddr) + 1) & ".0"
            Dim strStatus_09 = "Status_09: R" & CStr(CSng(strStatusAddr) + 1) & ".1"
            Dim strStatus_0A = "Status_0A: R" & CStr(CSng(strStatusAddr) + 1) & ".2"
            Dim strInst_FU_Activate = "Inst_FU_Activate: R" & CStr(CSng(strStatusAddr) + 1) & ".3"
            Dim strStatus_0C = "Status_0C: R" & CStr(CSng(strStatusAddr) + 1) & ".4"
            Dim strBypass = "Bypass: R" & CStr(CSng(strStatusAddr) + 1) & ".5"
            Dim strSimulate = "Simulate: R" & CStr(CSng(strStatusAddr) + 1) & ".6"
            Dim strStatus_0F = "Status_0F: R" & CStr(CSng(strStatusAddr) + 1) & ".7"
            Dim strLLow_State = "LLow_State: R" & CStr(CSng(strStatusAddr) + 1) & ".8"
            Dim strLow_State = "Low_State: R" & CStr(CSng(strStatusAddr) + 1) & ".9"
            Dim strHigh_State = "High_State: R" & CStr(CSng(strStatusAddr) + 1) & ".A"
            Dim strHHigh_State = "HHigh_State: R" & CStr(CSng(strStatusAddr) + 1) & ".B"
            Dim strUnder_Range_Fault = "Under_Range_Fault: R" & CStr(CSng(strStatusAddr) + 1) & ".C"
            Dim strOver_Range_Fault = "Over_Range_Fault: R" & CStr(CSng(strStatusAddr) + 1) & ".D"
            Dim strInstrument_Error = "Instrument_Error: R" & CStr(CSng(strStatusAddr) + 1) & ".E"
            Dim strStatus_07 = "Status_07: R" & CStr(CSng(strStatusAddr) + 1) & ".F"
    
            Dim strStatusWordString As String = strStatus & vbLf &
                                                 strStatus_18 & vbLf &
                                                  strStatus_19 & vbLf &
                                                   strBus_Healthy & vbLf &
                                                      strStatus_1B & vbLf &
                                                       strStatus_1C & vbLf &
                                                        strStatus_1D & vbLf &
                                                         strStatus_1E & vbLf &
                                                          strStatus_1F & vbLf &
                                                           strStatus_10 & vbLf &
                                                            strStatus_11 & vbLf &
                                                             strStatus_12 & vbLf &
                                                              strStatus_13 & vbLf &
                                                               strStatus_14 & vbLf &
                                                                strStatus_15 & vbLf &
                                                                 strStatus_16 & vbLf &
                                                                  strStatus_17 & vbLf &
                                                                   strStatus_08 & vbLf &
                                                                    strStatus_09 & vbLf &
                                                                     strStatus_0A & vbLf &
                                                                      strInst_FU_Activate & vbLf &
                                                                       strStatus_0C & vbLf &
                                                                        strBypass & vbLf &
                                                                         strSimulate & vbLf &
                                                                          strStatus_0F & vbLf &
                                                                           strLLow_State & vbLf &
                                                                            strLow_State & vbLf &
                                                                             strHigh_State & vbLf &
                                                                              strHHigh_State & vbLf &
                                                                               strUnder_Range_Fault & vbLf &
                                                                                strOver_Range_Fault & vbLf &
                                                                                  strInstrument_Error & vbLf &
                                                                                    strStatus_07
    
    
            Dim strBusInput = "BusInput: R" & strBusInputAddr
            Dim strInterlocks = "Interlocks: R" & strInterlocksAddr
            Dim strFirstUp = "FirstUp: R" & strFirstUpAddr
    
            strDUTValue = strCommandWordString & vbLf & strAlarmWordString & vbLf & strStatusWordString & vbLf & strBusInput & vbLf &
                                                    strInterlocks & vbLf & strFirstUp & vbLf & strAuxilaryWordString & vbLf &
                                                     strAnalog_In & vbLf & strDelay_HL & vbLf & strDelay_HHLL & vbLf & strNo_Errors & vbLf &
                                                        strLLow_Limit & vbLf & strLow_Limit & vbLf & strPV_Value & vbLf & strHHigh_Limit & vbLf &
                                                         strHigh_Limit & vbLf & strHysteresis_Value & vbLf & strReal_Value
    
            Return strDUTValue
    
        End Function
    #End Region
    All advice appreciated.
    Last edited by Slabs1960; Jul 12th, 2017 at 08:57 AM.
    I can fix what stupid does, but, I cannot fix stupid

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Should I use a Class instead of a Function

    You have a function that takes two arguments and returns a string. That's pretty compact, regardless of what is happening in the body of the function. What advantage do you feel a class would provide?

    Much of the length of the code is driven by the way you organized it, which I'd say is pretty reasonable. For example, you have a block of string variables that you create, then you put them all together. You could have avoided creating those string variables, but only at the cost of making a really long and complicated string even longer.

    One thing you probably should look into for this is the StringBuilder class. Anytime you concatenate a string onto a different string, what happens is that a new string is created and both of the originals are copied to the new string, then the originals are abandoned. This is inefficient, but it only matters if you have LOTS of concatenation. I remember people (possibly including me) times how many concatenations were enough to justify switching to a StringBuilder, but I don't remember what the number was. You're over that number, no matter what it was. What the StringBuilder gives you is a resizable string, so you don't pay the cost of the copying every time you concatenate. You call Append or AppendLine, both of which are worth a look, in your case. AppendLine 'might' do what you are doing in lines such as the one where you fill strCommandWordString. It might not do that, either, since you are adding just a line feed, and AppendLine might add CRLF rather than just LF, so it might not work. Even without that, you could just call Append with the variable, then append with the LF. This would cut the number of lines of code down by a fair amount, and you wouldn't have to create all those local variables.
    My usual boring signature: Nothing

  3. #3
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Should I use a Class instead of a Function

    I don't think it's as important to ask, "Should I use a class or a function here?" as it is to realize you did something important: you recognized this is a very complicated chunk of code and you'd like to simplify it.

    I'm going to compliment you up-front: you have properly represented this problem as "the final string is made of several smaller strings that, in turn, consist of even smaller strings." You've carefully made each calculation its own individual variable, and you build them all in a "bottom-up" fashion. This is the way a professional thinks, and it makes it really easy to decompose the problem further and try to yield some simplification.

    "Less complex" won't mean "fewer lines", and rarely does. In this case, if we're going to make a class for doing this, "less complex" takes the form of being able to use new names describing what we're doing as opposed to how it's done. You're building a ton of strings and gluing them together in a specific order, there's no way to make that "simple". But there are ways to make it look a little more methodical.

    It's big enough I don't think I can write an entire class to help out, but here's the kind of thing I mean.

    It doesn't compile as-is, I think towards the bottom variables like 'strAnalog_In' were meant to reference 'strAnalog_InAddr'? I'm going to go on that assumption. What I see in that first big chunk of variables is a repeated calculation:
    Code:
    0 + (2 * intDevicenumber)
    1 + (2 * intDevicenumber)
    ...
    So that's the first 'optimization' I'd make, you want to form a formatted string based on that calculation, this is a good way to subdivide into a function:
    Code:
    Function GetAddress(ByVal offset As Integer, ByVal deviceNumber As Int16) As String
        Dim address As Integer = offset + (2 * deviceNumber)
        Return address.ToString()
    End Function
    That simplifies the lines slightly:
    Code:
    Dim commandAddress As String = GetAddress(0, deviceNumber)
    Dim alarmAddress As String = GetAddress(1, deviceNumber)
    ...
    Let's look at the next "chunk", the code that builds 'strCommandWordString". (By the way, don't you think that variable name's wordy? The 'str' stands for "String", which is also at the end. I'd have just called it 'commandWord' instead of "stringCommandWordString".)

    Each bit is built from formatting a command, the variable 'strCommandAddress', and an optional number. Helper methods for this could make it a little cleaner. Here's the helper methods I'd use:
    Code:
    Private Sub AppendCommandTo(ByVal builder As StringBuilder, ByVal prefix As String, ByVal suffix As String)
        builder.AppendFormat("{0}{1}{2}{3}", prefix, commandAddress, suffix, vbLf)
    End Sub
    With that in place:
    Code:
    Dim commandWordBuilder As New StringBuilder()
    AppendCommandTo(commandWordBuilder, "Command: R", "")
    AppendCommandTo(commandWordBuilder, "Bypass_Req: R", ".0")
    AppendCommandTo(commandWordBuilder, "Command_9: R", ".0")
    ...
    
    Dim commandWord As String = builder.ToString()
    The Alarm and Status words are built in very similar fashions. One thing I want to call out, take a look at this:
    Code:
    Cstr(CSng(strStatusAddr))
    'strStatusAddr' is a String. This code says, "Convert the String to a Single, then convert the Single to a String". Is there a good reason for doing that? It seems silly, and if there's some reason there might be a better way to make it clear.

    You could certainly move all this code into another class, but I think the best first step is making helper methods so your code more properly explains what it is doing rather than how. The final string could be built up more compactly with a loop over an array:
    Code:
    Dim resultComponents() As String = { commandWord, alarmWord, statusWord, busInput, ..., real_value }
    Dim resultBuilder As New StringBuilder()
    For Each component In resultComponents
        resultBuilder.AppendFormat("{0}{1}", component, vbLf)
    Next
    
    Return resultBuilder.ToString()
    This makes it easier to reorder/tweak the string without making errors.

    So I wouldn't say any of this is making the code "less complicated", but it does make it "easier to change".
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  4. #4

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Thanks Sitten Spynne , Shaggy Hiker for the great replies and compliments .

    'strStatusAddr' is a String. This code says, "Convert the String to a Single, then convert the Single to a String". Is there a good reason for doing that? It seems silly, and if there's some reason there might be a better way to make it clear.
    The reason for this that the "Device Number" comes in as a string. So in order to do the calculation I need to convert to a integer. The result has to be a string, it is converted back to a string. Not sure if there is a simpler way to do this.

    Let's look at the next "chunk", the code that builds 'strCommandWordString". (By the way, don't you think that variable name's wordy? The 'str' stands for "String", which is also at the end. I'd have just called it 'commandWord' instead of "stringCommandWordString".)
    I missed that. You are correct and I will fix it.


    What the StringBuilder gives you is a resizable string, so you don't pay the cost of the copying every time you concatenate
    The string structure will never change (the PLC expects it this format). That said, I will definitely look into the "StringBuilder" class. The concatenation at the end of each word bothered me from the beginning.

    I like my code to be simple and easily readable (there will be others maintaining it, later)
    The reason I asked the question is, that I have been reading up on classes and wondered if this is an ideal case to use a class. I do not need to change it. Part of the learning process.
    Last edited by Slabs1960; Jul 12th, 2017 at 12:19 PM.
    I can fix what stupid does, but, I cannot fix stupid

  5. #5
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Should I use a Class instead of a Function

    Oh! I didn't see the "+ 1" in that spot. Easy to miss when so much is going on. But there's a better way to go about it.

    In about a dozen places, you need to get statusAddr as an Integer rather than a String. I'd be real careful about just using Single here, that's a floating-point number so if you really want an Integer you're inviting disaster if you don't convert to Integer. So here's what I'd do.

    'statusAddress' is calculated as a String up top, based on a calculation. You also use 'statusAddress + 1' on about a dozen different occasions. So I'd make a new variable up-top:
    Code:
    Dim statusAddress = GetAddress(1000, deviceNumber)
    Dim statusAddressPlusOne = GetAddress(1001, deviceNumber)
    Then just use that in all the cases where you want an offset.

    There's some other approaches. Maybe you should just leave all of those addresses as Integers. All of the string formatting calls are fine with converting integers to Strings:
    Code:
    Dim statusAddress As Integer = 1000
    Dim builder As New StringBuilder()
    
    builder.AppendFormat("{0}{1}{2}", "Command:", statusAddress + 1, ".1")
    
    Console.WriteLine(builder.ToString)
    ' Command:1001.1
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  6. #6

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Oh! I didn't see the "+ 1" in that spot. Easy to miss when so much is going on. But there's a better way to go about it
    There is always ONE exception to mess up a simple pattern
    I can fix what stupid does, but, I cannot fix stupid

  7. #7
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Should I use a Class instead of a Function

    i would do this completely different. it seems the message header you generate always has the same format. i would have a template for that and search/replace keywords such as ***strCommandAddr*** and ***strAlarmAddr***.
    i think this will make the code much much more readable and maintainable.

  8. #8

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Quote Originally Posted by digitalShaman View Post
    i would do this completely different. it seems the message header you generate always has the same format. i would have a template for that and search/replace keywords such as ***strCommandAddr*** and ***strAlarmAddr***.
    i think this will make the code much much more readable and maintainable.
    The format will always be the same. But I do not understand what you are saying. Please explain.
    I can fix what stupid does, but, I cannot fix stupid

  9. #9
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Should I use a Class instead of a Function

    do you use 2015+? if so you can use interpolated strings:
    Code:
           Dim intDevicenumber As Int16 = CType(strDeviceNumber, Int16)
            Dim strCommandAddr As String = CType(0 + (2 * intDevicenumber), String)
            Dim strAlarmAddr As String = CType(1 + (2 * intDevicenumber), String)
            Dim sHeader As String =
    $"Command: R{strCommandAddr}
    Bypass_Req: R{strCommandAddr}.0
    Command_9: R{strCommandAddr}.1
    Reset_Req: R{strCommandAddr}.2
    Command_B: R{strCommandAddr}.3
    Command_C: R{strCommandAddr}.4
    Command_D: R{strCommandAddr}.5
    Command_E: R{strCommandAddr}.6
    Command_F: R{strCommandAddr}.7
    Command_0: R{strCommandAddr}.8
    Command_1: R{strCommandAddr}.9
    Command_2: R{strCommandAddr}.A
    Command_3: R{strCommandAddr}.B
    Command_4: R{strCommandAddr}.C
    Command_5: R{strCommandAddr}.D
    Active_Req: R{strCommandAddr}.E
    Simulate_Req: R{strCommandAddr}.F
    Alarm: R{strAlarmAddr}
    Alarm_8: R{strAlarmAddr}.0
    Alarm_9: R{strAlarmAddr}.1
    Alarm_A: R{strAlarmAddr}.2
    Alarm_B: R{strAlarmAddr}.3
    Alarm_C: R{strAlarmAddr}.4
    Bus_FU: R{strAlarmAddr}.5
    Alarm_E: R{strAlarmAddr}.6
    Alarm_F: R{strAlarmAddr}.7
    Alarm_0: R{strAlarmAddr}.8
    Alarm_1: R{strAlarmAddr}.9
    Alarm_2: R{strAlarmAddr}.A
    Alarm_3: R{strAlarmAddr}.B
    Inst_FU: R{strAlarmAddr}.C
    Alarm_5: R{strAlarmAddr}.D
    Alarm_6: R{strAlarmAddr}.E
    Alarm_7: R{strAlarmAddr}.F
    Status: R1002
    Status_18: R1002.0
    Status_19: R1002.1
    Bus_Healthy: R1002.2
    Status_1B: R1002.3
    Status_1C: R1002.4
    Status_1D: R1002.5
    Status_1E: R1002.6
    Status_1F: R1002.7
    Status_10: R1002.8
    Status_11: R1002.9
    Status_12: R1002.A
    Status_13: R1002.B
    Status_14: R1002.C
    Status_15: R1002.D
    Status_16: R1002.E
    Status_17: R1002.F
    Status_08: R1003.0
    Status_09: R1003.1
    Status_0A: R1003.2
    Inst_FU_Activate: R1003.3
    Status_0C: R1003.4
    Bypass: R1003.5
    Simulate: R1003.6
    Status_0F: R1003.7
    LLow_State: R1003.8
    Low_State: R1003.9
    High_State: R1003.A
    HHigh_State: R1003.B
    Under_Range_Fault: R1003.C
    Over_Range_Fault: R1003.D
    Instrument_Error: R1003.E
    Status_07: R1003.F
    BusInput: R2002
    Interlocks: R3002
    FirstUp: R4002"
    
    return sHeader & vblf & strAuxilaryWordString & vbLf &
                                                     strAnalog_In & vbLf & strDelay_HL & vbLf & strDelay_HHLL & vbLf & strNo_Errors & vbLf &
                                                        strLLow_Limit & vbLf & strLow_Limit & vbLf & strPV_Value & vbLf & strHHigh_Limit & vbLf &
                                                         strHigh_Limit & vbLf & strHysteresis_Value & vbLf & strReal_Value
    if you cant use interpolated strings then loop over the template and do serach replace "{strCommandAddr}"->strCommandAddr.tostring etc.

    you have to add the other vars to the template yourself, i am just showing how i'd go about it.
    maybe the same is true for the rest of the message? does it really take to send all that stuff everytime?

  10. #10
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Should I use a Class instead of a Function

    and in regards to the class/function question: it is clearly a function. the question is: is it a method of a class? private/public? is there maybe a class PLC? you see?

  11. #11

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Using VS2017. Forgot to add it to the post.

    I think I get the idea. Will give it a try.
    I can fix what stupid does, but, I cannot fix stupid

  12. #12

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    maybe the same is true for the rest of the message? does it really take to send all that stuff everytime?
    This is a device type. Depending on the size of the Process Plant, there could be 50 to 60 of them, identical except for a unique TagName and Device number. To add them to the PLC by manually could take a day or so. Doing it this way, few seconds.
    I can fix what stupid does, but, I cannot fix stupid

  13. #13
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Should I use a Class instead of a Function

    The trouble with that approach is:

    How do you guarantee it's using an LF as the line separator instead of the more standard CRLF?
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  14. #14

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    CRLF does not work. Has to a LF only
    I can fix what stupid does, but, I cannot fix stupid

  15. #15

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Quote Originally Posted by digitalShaman View Post
    and in regards to the class/function question: it is clearly a function. the question is: is it a method of a class? private/public? is there maybe a class PLC? you see?
    This is a good question. I am not an expert, but from my reading the same questions passed through my mind.

    The only way to answer that one is for me to submit a post explaining what my whole project is all about. That will be a long one, but might be worth the while. There is a whole lot of processes involved. The bottom line is that I can automate 80% of the PLC & Scada software development using VB. This saves 3 to 6 weeks of manual engineering time, with the associated finger problems.

    When I get a gap I may just do that.
    I can fix what stupid does, but, I cannot fix stupid

  16. #16
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Should I use a Class instead of a Function

    If it is possible, you might try sending with a CRLF rather than an LF. It will either work or fail. If it works, then that would be a good thing, because CRLF is MUCH more common than just the LF.
    My usual boring signature: Nothing

  17. #17
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Should I use a Class instead of a Function

    Quote Originally Posted by Sitten Spynne View Post
    The trouble with that approach is:

    How do you guarantee it's using an LF as the line separator instead of the more standard CRLF?
    thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...

    if there is no consitency then one could still explicitly add the LFs to the template. or replace CRLFs to LFs afterwards etc. many ways. the Point that i wanted to make is that instead of that concats the code gets much more readable using a template.

    The only way to answer that one is for me to submit a post explaining what my whole project is all about. That will be a long one, but might be worth the while. There is a whole lot of processes involved.
    yes, maybe you should do this. it could help you getting Input how others would design the code.

    This saves 3 to 6 weeks of manual engineering time, with the associated finger problems.
    this sounds archaic

  18. #18

    Thread Starter
    Addicted Member Slabs1960's Avatar
    Join Date
    Mar 2017
    Location
    Oranjemund, Namibia
    Posts
    173

    Re: Should I use a Class instead of a Function

    Quote Originally Posted by digitalShaman View Post
    thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...

    if there is no consitency then one could still explicitly add the LFs to the template. or replace CRLFs to LFs afterwards etc. many ways. the Point that i wanted to make is that instead of that concats the code gets much more readable using a template.


    yes, maybe you should do this. it could help you getting Input how others would design the code.



    this sounds archaic
    This is PLC's (Programmable Logic Controllers by Siemens, Schneider Electric, Mitsubishi & Allen Bradley) we talking about. Some of these are form based. Uugh.
    I can fix what stupid does, but, I cannot fix stupid

  19. #19
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Should I use a Class instead of a Function

    thats a good Point i was also wondering about when i knocked that example together. however it seems that interpolated strings used in that manner do add a single LF for each linebreak, at least this was what i was seeing yesterday testing it with 2015. i hope there is some consitency through Versions, regional Settings, days, moon Phase etc...
    ahh, after project reopen: "The line endings in the following file are inconsistent do you want to normalize?"
    i remember i was running the function, dumping the result into a file, open with text editor and copy pasted into the project. that makes sense. but actually a bad idea as at some point in time someone will normalize the lineendings and break the code without even knowing. a timebomb good that vs warns about this.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width