How to add user specified items to OPC data group - matlab

I am creating a MATLAB application which connects to an OPC Server and reads the Tag properties. The MATLAB documentation is telling me that I can add a group, add tag items, and then read the value:
grp = addgroup(da, 'ExRead');
itm = additem(grp, 'Tag.Argument');
The problem is that I don't know the tag argument, in my app the user is selecting an available tag in a popupmenu and the value is written to a string, but when I call:
val = get(handles.popupmenu1, 'Value'); // Ask for Value selected item
string_val = get(handles.popupmenu1, 'String'); // Ask for string
stringName = string_val{val}; // Ask for string corresponding to the specified value
set(handles.text1, 'String', stringName); // Display the selected tag
item1 = additem(Group1, stringName); // Add the selected string to a global group "Group1"
read1 = read(Group1, item1); // Read the value
set(handles.text11, 'String', read1); // Display the value
But when I run the code MATLAB generates errors. I guess the problem is item1 = additem(Group1, stringName); In all the MATLAB documentation examples I see something like item1 = additem(Group1, 'adres.adres.1'); This should explain why I am unable to add any data to the Group1.
But how can I add an item to a taggroup which must be specified/selected by a user?

Group1 appears to be a variable here, that is undefined. Perhaps you meant to type 'Group1', with quotes? That would add item to a group called Group1.

If I get it right, you don't know which tag names you should use.
The correct ItemID (Tag name) is typically found by browsing the server address space.
Before you implement browsing in your application (if possible with MATLAB), you can use test clients, such as Prosys OPC Client to browse the address space and find the proper ItemID(s) to use.

Related

AVPlayerItem's selectedMediaOption(in:) disagrees with available selection options following seek(to:) call

I'm having a strange issue with AVFoundation in a completion block of loadValuesAsynchronously(forKeys:) on an AVAsset with the key "availableMediaCharacteristicsWithMediaSelectionOptions", I'm inspecting the values of the available media selection options in the group for the .legible characteristic, as well as the currently selected media option in that group (via selectedMediaOption(in: group). When I print these out, I get the following output (the array is the available selection options, followed by the current selection):
(
"<AVMediaSelectionKeyValueOption: 0x60c002078380, language = en-IE, mediaType = 'sbtl', title = English+(Ireland)>",
"<AVMediaSelectionKeyValueOption: 0x60c002078440, language = ab, mediaType = 'sbtl', tagged media characteristics = {public.accessibility.transcribes-spoken-dialog, public.accessibility.describes-music-and-sound}, title = Abkhazian>"
)
<AVMediaSelectionKeyValueOption: 0x60c00207b640, language = en-IE, mediaType = 'sbtl', title = English+(Ireland)>
As you can see, the selected option has the same info as the en-IE option in the array, but it is actually a different AVMediaSelectionOption instance since the address differs. This is occurring immediately following a state change on the AVPlayerItem object, in case that affects anything. Does the selected option get updated later? Has anyone ever seem something like this?
So it looks like the answer is that the identity of the AVMediaSelectionGroup (as well as the AVMediaSelectionOptions that it contains) changes with every call to .mediaSelectionGroup(forMediaCharacteristic:). This means that even though the group will contain all the same information, it will not be the same instance as the one from the previous call.

Create a mask in Simulink with edit field as enumeration

I want to create a mask on a subsystem, like the mask of the Enumerated Constant (shown below). As you see in the blue circle, the Value can be edited using a drop down list of possibilities. The Enumerated Constant
If creating a mask it is indeed possible to make a Popup instead of an Edit but the problem with this is that the list of possible selections needs to be manually created inside the mask. What I want is that this Edit value only shows the possible selections of a certain enumeration that I want to specify only ones. The Enumerated Constant mask does this with an Edit type but even then it works.
Of course I tried to reverse engineer this from this block but I can not find how Matlab does this.
I am not sure if my initial question was quite clear if I read it now. The enumerals should be taken from an enumerated type from a Data Dictionary. So based on the answers of Julian and DrBuck I could answer my own question.
I first get the enumerated type from the data dictionary.
% set name of DD and type
DDName = 'types.sldd';
EventType = 'Dem_EventIdType';
% Get DD entry
myDictionaryObj = Simulink.data.dictionary.open(DDName);
dDataSectObj = getSection(myDictionaryObj,'Design Data');
entryObj = getEntry(dDataSectObj,EventType,'DataSource',DDName);
entryValue = getValue(entryObj);
Then I get the enumerals and add the event type to it. This will be used to fill the pop-up options.
% Get enumerals
NoOfEvents = length(entryValue.Enumerals);
for i = 1:NoOfEvents
EventIDs{i,1} = [EventType '.' entryValue.Enumerals(i).Name];
end
After this I used the above proposed code to manipulate the created pop-up menu with the enumerals from the Data Dictionary.
maskObj= Simulink.Mask.get(gcb);
par_name = 'Value_eventID'; % name
par_idx = find(strcmp({maskObj.Parameters.Name},par_name)); % index of parameter
maskObj.Parameters(par_idx).TypeOptions = EventIDs; % enum options
I do this not in the 'Initialization Commands' but in the callback function of the 'Refresh events' button. When the block is added from the library it only contains the INVALID_EVENT. After a refresh it does a fresh look-up and adds the current enumerals to the list.
My end result:
I couldn't quite figure out how to do this but hopefully this answer should get you on the right track.
Create two popups on the mask, eg 'popup1' and 'popup2'. Hardcode your type options to popup1, and leave popup2 blank and disabled (because it's dependent on what you select with popup1). You can then use a callback on popup1 to populate popup2 when the first one is clicked. Your callback would look something like this:
% Grab the value selected from popup1
value = get_param(gcb, 'popup_1');
% Do some sort of check/switch statement to set your options
if value == 1
% Enable popup2
set_param(gcb, 'MaskEnables', {'on', 'on'});
% Set the type options for popup2
set_param(gcb, 'MaskStyleString', 'popup(1|2|3|4|5),popup(my|new|options)');
end if
Have a look at this and this in the Matlab/Simulink documentation. get_param and set_param are useful if a bit unintuitive. It looks like in later versions of Simulink you can use maskObj = Simulink.Mask.create(gcb); methods to do this sort of stuff, which might be easier.
as DrBuck sugessted, you should use maskObj = Simulink.Mask.create(gcb) to create a mask for the currently selected block (gcb) or select an already existing mask by maskObj=Simulink.Mask.get(gcb). Then, add parameters to it:
par_name = 'foo'; % name
par_prompt = 'This is my enum constant'; %prompt
maskObj.addParameter('Prompt',par_prompt,'Name',par_name); % add parameter
The field you are looking for is called TypeOptions, but first you must find the correct parameter number by e.g.
par_idx = find(strcmp({maskObj.Parameters.Name},par_name)); % index of parameter
Set the mask parameter to 'popup' and create your enum values:
maskObj.Parameters(par_idx).Type = 'popup'; % type
maskObj.Parameters(par_idx).TypeOptions = {'Option1','Option2'}; % enum options
There you are ;)
HTH Julian

Passing arguments to Access Forms created with 'New'

I have a form called 'detail' which shows a detailed view of a selected record. The record is selected from a different form called 'search'. Because I want to be able to open multiple instances of 'detail', each showing details of a different record, I used the following code:
Public detailCollection As New Collection
Function openDetail(patID As Integer, pName As String)
'Purpose: Open an independent instance of form
Dim frm As Form
Debug.Print "ID: " & patID
'Open a new instance, show it, and set a caption.
Set frm = New Form_detail
frm.Visible = True
frm.Caption = pName
detailCollection.Add Item:=frm, Key:=CStr(frm.Hwnd)
Set frm = Nothing
End Function
PatID is the Primary Key of the record I wish to show in this new instance of 'detail.' The debug print line prints out the correct PatID, so i have it available. How do I pass it to this new instance of the form?
I tried to set the OpenArgs of the new form, but I get an error stating that OpenArgs is read only. After researching, OpenArgs can only be set by DoCmd (which won't work, because then I don't get independent instances of the form). I can find no documentation on the allowable parameters when creating a Form object. Apparently, Microsoft doesn't consider a Constructor to be a Method, at least according to the docs. How should I handle this? (plz don't tell me to set it to an invisible text box or something) Thanks guys, you guys are the best on the net at answering these questions for me. I love you all!
Source Code for the multi-instance form taken from: http://allenbrowne.com/ser-35.html
Inside your Form_detail, create a custom property.
Private mItemId As Long
Property Let ItemID(value as Long)
mItemId = value
' some code to re query Me
End Property
Property Get ItemId() As Long
ItemId = mItemId
End Property
Then, in the code that creates the form, you can do this.
Set frm = New Form_detail
frm.ItemId = patId
frm.Visible = True
frm.Caption = pName
This will allow you to pass an ID to the new form instance, and ensure it gets requeried before making it visible. No need to load all of the results every time if you're always opening the form by Newing it. You let the property load the data instead of the traditional Form_Load event.
This works because Access Form modules are nothing more than glorified classes. Hope this helps.
You could try applying a filter:
frm.Filter = "[ID] = " & patID
frm.FilterOn = True
The Record Source of the Detail form will need to be set to the table to which the ID belongs.
UPDATE
As you requested, here is the code to set the RecordSource:
frm.RecordSource = "select * from TableName where [ID] = " & patID
This is probably cleaner than using a filter given that a user can remove the filter (depending on the type of form).

The name of the custom list for "Detected in Cycle" field in QC

I am tring to extract the possible values available in QC defects section for "Detected in Cycle" field.
I tried doing it for "Defects status", i was able to extract the values Resolved, Open, Assigned....
The code which i tried for extracting status values is as below:
Set cust = QCConnection.customization
Set custlists = cust.Lists
Set custlist = cutslists.List
Set custlist = custlists.List("Bug Status") 'it is listing complete bug status values not specific 'to the project
Set listrootnode = custlist.RootNode
Set listchildren = listrootnode.Children
For Each listname In listchildren
MsgBox (listname.Name) 'Assigned, deferred, cancel...... all are displayed
Next
But here i need to replace Bug_status with something related to Detected in cycle field. So i need help in finding out this name of custom list....
i was able to get list of cycles avaiable in QC project. Here is the code:
Set cycles = UserForm9.QCConnection.CycleFactory ' here CycleFactory, a method in QC API will help ' you get complete list
So Bug status is a customization list.
And Cycles is not customized list but could be extracted by CycleFacotry method.

Access 2010 Trying to Enter a unique record through Form

I'm trying to input an error check for my form. I have the user entering the name and I would like a prompt to inform them if they are attempting to use a Name already in the records.
Example: the Person table has 3 records with FNames being: Jeff, Kyle, Darren.
If on the add person form in the Fname Box Kyle is entered, the after update event will notify the user that this name has been claimed and null the field. Where as if Greg was enter no notifications will occur.
I just don't know how to compare a text field value to values in a filtered query list, and Google searches have other loosely related links in the way.
Thank you for help!
If all fnames must be unique, add a unique index to the table. This will prevent duplicates being entered. The form error property will allow you to provide a custom error.
You can also check if the name exists in the Before Update event of the control.
In this example, the control and field are both called AText. Generally, you should rename controls so they are not the same as fields.
Private Sub AText_BeforeUpdate(Cancel As Integer)
Dim IsOk As Boolean
''One of the very few places where the .Text property is used
sLookUp = Me.AText.Text
IsOk = IsNull(DLookup("Atext", "Table1", "Atext='" & sLookUp & "'"))
If Not IsOk Then
MsgBox "Found!"
Cancel = True
End If
End Sub