Author Topic: Writing a new driver  (Read 2651 times)

briano

  • Newbie
  • *
  • Posts: 4
    • View Profile
Writing a new driver
« on: March 27, 2016, 07:38:00 PM »
I've embarked on the task of writing my own driver, and I'm wondering how to implement BeginRead and BeginWrite in the IComComponent interface. Is there supposed to be a standard way of notifying the caller on completion? I don't see an event defined in the interface, just a delegate type.

Also, what do OwnerObjectID and TransactionNumber represent in PlcComEventArgs? Is TransactionNumber the same as sequenceNumber?

Thanks!

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Writing a new driver
« Reply #1 on: March 27, 2016, 07:56:52 PM »
BeginRead and BeginWrite are asynchronous. Once called, they send the request to the PLC, then immediately return to the caller. Once data is returned from the PLC, the DataReceived event is fired with the requested address and the data.

OwnerObjectID is a unique ID number for each driver instance. Since all instances share a common transport layer, the returned data also comes back with the OwnerObjectID, so each driver instance can identify whether it was data that it requested. In the constructor for the driver, it will increment the shared ObjectIDs and use the current value for its OwnerObjectID.

TransactionNumber and SequenceNumber are interchangeable terms. If you refer to Allen Bradley PCCC documentation, it refers to a TNS (Transaction Number). If you refer to CIP/EIP documentation, it will refer to SequenceNumber. Omron documentation will yet call it by another term.

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Writing a new driver
« Reply #2 on: March 27, 2016, 08:14:35 PM »
If this helps, this is the full source code of a driver written for AdvancedHMI:

https://sourceforge.net/projects/modbusrtu/

briano

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Writing a new driver
« Reply #3 on: March 27, 2016, 08:27:48 PM »
Thanks for the quick response!

So, is any class that implements IComComponent supposed to have an event named DataReceived?

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Writing a new driver
« Reply #4 on: March 27, 2016, 08:38:58 PM »
The IComComponent is the interface used by the visual controls. The visual controls link to the driver through subscriptions and do not use the DataRecieved event. The subscribe function uses a specified Callback to send the data to.

The DataReceived event is only needed if a user wishes to use the asynchronous methods within their own code.

briano

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Writing a new driver
« Reply #5 on: March 30, 2016, 02:00:56 PM »
Getting close.

The problem I'm running into now has to do with the event handler thread trying to update the GUI. I added the SynchronizingObject property to the driver similar to the example but it doesn't look like it's being set from anywhere.

This is what I added:

Code: [Select]
public System.ComponentModel.ISynchronizeInvoke SynchronizingObject
{
    get
    {
        if (m_SynchronizingObject == null && AppDomain.CurrentDomain.FriendlyName.IndexOf("DefaultDomain", System.StringComparison.CurrentCultureIgnoreCase) >= 0)
        {
            System.ComponentModel.Design.IDesignerHost host1;
            host1 = this.GetService(typeof(System.ComponentModel.Design.IDesignerHost)) as System.ComponentModel.Design.IDesignerHost;
            if (host1 != null)
            {
                m_SynchronizingObject = host1.RootComponent as System.ComponentModel.ISynchronizeInvoke;
            }
        }
        return m_SynchronizingObject;
    }

    set
    {
        if (value != null)
        m_SynchronizingObject = value;
    }
}

Archie

  • Administrator
  • Hero Member
  • *****
  • Posts: 5322
    • View Profile
    • AdvancedHMI
Re: Writing a new driver
« Reply #6 on: March 30, 2016, 02:39:24 PM »
An improved driver model has been developed that makes the driver more portable across platforms. This model completely separates the UI from the base driver. The SynchronizingObject is considered a function of UI integration, so it is not part of the base driver. Nor does the base driver use the System.ComponentModel.Component as a base.

Once the base driver is developed without using UI thread invocation, it is inherited into another layer to implement the specific use functionality. For instance, since AdvancedHMI uses WinForms, the top layer will implement the functionality for synchronizing to the UI thread in a WinForms application.

The new driver model also uses the more current object of SynchronizationContext instead of SynchronizingObject.

Take a look at EthernetIPforCLXCom.vb in the AdvancedHMIDrivers project to see how all this ties together. You may be able to make a copy of that code and change the inherit to point to your driver.

This new driver model will be used in future versions of AdvancedHMI, so it is a good idea to follow that pattern to ensure your driver will be compatible with future versions.
« Last Edit: March 30, 2016, 02:43:51 PM by Archie »

briano

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Writing a new driver
« Reply #7 on: March 31, 2016, 07:18:10 AM »
Ah, yes I'm familiar with the SynchronizationContext. You could do it similar to "await" where the SynchronizationContext is captured at the time of subscription, and when the event handler is called, it posts to that context.