AdvancedHMI Software
General Category => Application Showcase => Topic started by: Phrog30 on February 04, 2019, 10:05:54 AM
-
I put together a little sample app that has some of the latest controls. This app is compiled and ready to go. Run the included modbus sim and have at it.
Edit, had to update a file, latest link
https://drive.google.com/file/d/1cKDpXR5fCnxmGkT6vuMejVZuXbUPXSTQ/view?usp=sharing (https://drive.google.com/file/d/1cKDpXR5fCnxmGkT6vuMejVZuXbUPXSTQ/view?usp=sharing)
James
-
James, I have had a look at this application hoping to get some guidance for security control.
I have noticed that the BasicButton in the first AdvancedHMI Components section has a property field for security.
I would like to have this available on other controls such as AnalogValueDisplay, MomentaryButton, SelctorSwitch but can't seem to figure out the "How To" to make this possible.If you would point me in the right direction it would be very much appreciated.
Thanks,
Gene
-
My controls already have security, so you have that option. But...
I have a class called Globals. In this class is this code:
Public Enum SecurityType
None = 0
Operators = 10
Maintenance = 20
Supervisor = 30
Engineer = 40
Admin = 50
End Enum
This is where I can globally change the security levels, but generally these 5 are all anyone would need.
Then, in the controls, I have a property...
'******************************
'* Property - Security
'******************************
Private m_Security As myEnums.SecurityType
''' <summary>
''' Choose security for this button
''' </summary>
''' <remarks></remarks>
<System.ComponentModel.Description("Choose security for this button")>
Public Property Security As myEnums.SecurityType
Get
Return m_Security
End Get
Set(ByVal value As myEnums.SecurityType)
m_Security = value
End Set
End Property
Then, for a button, on a button press event, for example, add something like this...
Dim securityText = [Enum].ToObject(GetType(myEnums.SecurityType), m_Security).ToString()
If Globals.LoginLevel >= m_Security Then
Else
Dim x As New Security_Notice
x.Level = securityText
x.ShowDialog()
Return
End If
Globals.LoginLevel is from my login stuff, if you make your own you will need to massage this part. Also, I use my own message popup, if you use your own you will need to edit that part as well.
Go through, read the comments, take a stab at it, then come back if you have questions. The way I did things isn't necessarily the right way, just the way I did it.
James
-
To add....
Instead of a popup you could bind the security stuff to the enabled property. Then there isn't really any code to write, aside from binding to the enable property.
-
Using enabled may simply it for you, in my class Globals, is this shared property. This is tied to my security stuff.
Public Shared LoginName As String
Public Shared UserName As String
Private Shared s_LoginLevel As Integer
Public Shared Property LoginLevel As Integer
Get
Return s_LoginLevel
End Get
Set(value As Integer)
If s_LoginLevel <> value Then
s_LoginLevel = value
OnLoginLevelChanged(System.EventArgs.Empty)
End If
End Set
End Property
I then have an event, in the same class...
Public Shared Event LoginLevelChanged As EventHandler
Private Shared Sub OnLoginLevelChanged(ByVal e As EventArgs)
RaiseEvent LoginLevelChanged(Nothing, e)
End Sub
Then could add a handler OnHandleCreated, I also look at security then to see about what to do.
Protected Overrides Sub OnHandleCreated(e As EventArgs)
MyBase.OnHandleCreated(e)
AddHandler AdvancedHMI.Globals.LoginLevelChanged, AddressOf LoginLevelChanged
Dim securityText = [Enum].ToObject(GetType(myEnums.SecurityType), m_Security).ToString()
If Globals.LoginLevel >= m_Security Then
Me.Enabled = True
Else
Me.Enabled = False
End If
Then watch the event and look at the security level...
Private Sub LoginLevelChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim securityText = [Enum].ToObject(GetType(myEnums.SecurityType), m_Security).ToString()
If Globals.LoginLevel >= m_Security Then
Me.Enabled = True
Else
Me.Enabled = False
End If
End Sub
-
Thanks James!! That helped me a lot. I appreciate your help with this matter.
I think I understand what you are doing now.
I will continue on and see if I can implement this.
-
James, I have been trying to get the alarms to use the description in the PLC.
I am using a Compaclogix L24. I configured the application ini file (Alarm_Use_PLC_Desc=1)
and set the alarmtriggers to use my plc. The alarm popup window showing that an alarm occured
will show but appears to still be populated from the ini file and does not show in the active alarms list page.
I also noticed that the header bar remains red and is blank. It's obvious that there must be more steps to configure
this to work with a PLC. I have tested with the included Modbus Simulator and it works fine.
Thanks, Gene
-
Oh, I removed the functionality. You will have to add another datasubcriber for plc strings. What is your string array address in the plc? I'll put something together and send to you.
-
Here again I am not sure that I am doing this right but I am using Alarm_Descriptions.
-
Ok, to clarify, there is a datasubscriber that looks at an array of integers. They are used for your triggers. The name of the datasubcriber for the app I sent is AlarmTriggers. Currently, the only option for descriptions is the ini file. You have to manually enter/type those. I still had the options for the PLC descriptions, they just don't do anything. However, it's easy enough to add. You will need an array of strings in the PLC to look at. So, your array is Alarm_Descriptions? What length, are they full length strings (82)? This matters, if they aren't then we have to run them through some code first or they won't look right. Personally, unless I'm doing string building in the PLC, I would just use the ini file. I used PLC descriptions, for example, when I would have one motor alarm trigger, but many reasons and I built the strings in the PLC and sent to the HMI. This saved on triggers.
I'll put together something quick and send. It may be a little later today.
-
OK, Sounds like staying with the ini file maybe the better way. So no bother in adding the plc description functionality back. The ini file will be fine, once created should be good for all of my projects anyway. I appreciate your help.
Gene
-
Ok. I won't bother then.
One thing to note, after you change the trigger addresses, assuming you are using DINTs, you will need to change the bit length from 16 to 32. It's currently at 16 for the modbus test. You have to do this in code, let me know if you need help finding it.
Or, you can use INTs and there isn't anything to change.
-
I lied, here is an updated app that will read descriptions from your PLC.
https://drive.google.com/file/d/1XQm0JiKfaghv4Ktjf22MzNqfmVjJaVcV/view?usp=sharing (https://drive.google.com/file/d/1XQm0JiKfaghv4Ktjf22MzNqfmVjJaVcV/view?usp=sharing)
I only tested for CLX/CpLX using full strings, 82 characters. I created two PLC arrays, the triggers are DINT[10], "AlarmTriggers", the descriptions are STRING[200], "AlarmDescriptions". Note that if the strings are blank it will use whatever is in the flat file. You can change the bit length and description lengths in the global class, see picture 1. It's a little clunky, but I'm using a datasubscriber for the descriptions, but you only enter the base tag in it. It will then dynamically add items based on length you set in globals and add brackets [ ] to it, so it has to be an array of strings, you can't use structures/UDTs the way it currently is. If you need structures, it will need changed a bit. Picture 2 shows the setup of datasubscriber PLC address name. Picture 3 shows PLC tags.
Even if you don't need this app you can play around with it, it may come in handy. I allow the descriptions to update even while the trigger is active. This differs from most HMIs, where the embedded server only updates on transition. This is nice if you build strings in the PLC and they update even after the triggers first occurs.
-
Thanks James I will check it out.
Gene