# Custom Driver development

**URL:** <https://forum.inductiveautomation.com/t/custom-driver-development/22767>\
**Category:** Module Development\
**Tags:** ignition79\
**Created:** [February 21, 2019, 4:09pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767 "2019-02-21T16:09:39Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 21, 2019, 4:09pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/1 "2019-02-21T16:09:39Z")

</div>

Hello,

I’m trying to develop a custom driver for a PLC .  
I already wrote a java library implementing the comunication protocol for read and write data from the PLC.  
I started from the AstractTagDriver module found in the SDK and I was studying the Modbus module trying to understand the flow… new node declarations, read and write requests and subscriptions.  
Maybe i’m missing some points but I still can’t see a node exposed (and can’t write or read it) after the buildNode function is called.  
I extended the AbstarctDriver class:

```auto
	@Override
	public void buildNode(String address, NodeId nodeId) throws AddressNotFoundException {
		// TODO Auto-generated method stub
		
		BrowseNode node = nodeMap.get(address);
		if (node == null) {
			node = new DataVariableNode(
					address,
					address,
					new DataValue(StatusCode.GOOD),
					DataType.Int16);
			nodeMap.put(address, node);
		}
		
		EnumSet<AccessLevel> accessLevel = EnumSet.of(AccessLevel.CurrentWrite);

	
			Node uaNode = (Node) builderFactory.newVariableNodeBuilder()
				.setNodeId(nodeId)
				.setBrowseName(new QualifiedName(1, node.getDisplayName()))
				.setDisplayName(new LocalizedText(node.getDisplayName()))
				.setDataType(DataType.Int16.getNodeId())
				.setTypeDefinition(NodeIds.VariableNode_DataType.getNodeId())
				.setAccessLevel(accessLevel)
				.setUserAccessLevel(accessLevel)
				.buildAndAdd(nodeManager);

		uaNodes.add(uaNode);
	}

```

So I Can’t even see any of createReadRequest or createWriteRequest called.

How can I move on?

Thanks,  
Federico.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2019, 4:22pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/2 "2019-02-21T16:22:40Z")

</div>

`buildNode` is called by the server when necessary, usually in response to a read, write, or browse coming to a node belonging to your driver.

I would ignore those examples and just focus on implementing the `Driver` interface from scratch. Start with `browse` and `buildNode` functions.

---

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 22, 2019, 7:36am UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/3 "2019-02-22T07:36:01Z")

</div>

Thank you Kevin, I will give a try with Driver Interface. Maybe I will need some help later…

---

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 22, 2019, 4:23pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/4 "2019-02-22T16:23:23Z")

</div>

Hi, Kevin,  
So, after some attemps I was able to add a node to the namespace and add the reference to other nodes. Now nodes are browsable. If I use quick Client I can see the nodes I created.  
But when I try to read or write I recive an error from the provider:  
Result code: [Bad\_NotConnected] The variable should receive its value from another variable.

What am I missing now?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 22, 2019, 4:48pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/5 "2019-02-22T16:48:25Z")

</div>

I don’t know, the responsibility for answering browse, read, and write calls is entirely up to your driver implementation.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 22, 2019, 4:52pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/6 "2019-02-22T16:52:42Z")

</div>

Next you need to implement the readItems() and writeItems() methods of the Driver Interface. The readItems() method needs to call .setValue() on each item with your value wrapped in a DataValue(), or a bad status code wrapped in a DataValue(). The writeItems() method needs to call .setWriteStatus() after each item write, supplying the appropriate StatusCode.

After that, you’ll want to implement the DriverSubscriptionModel.ModelChangeListener so tags that point at your OPC items will work correctly.

---

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 22, 2019, 5:15pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/7 "2019-02-22T17:15:45Z")

</div>

Thank u ptumel,

Thank you for the exhasutive explanation.  
I was losing the right way because I was still implementing the AbstarctDriver class and I could not see any of createReadRequest() or createWriteRequest() called. I was missing some parts of the driver implementation  
Now, starting from the Driver interface I can see the readItems() and writeItems() functions called and the flow is more clear.  
Maybe not so easy to implement the DriverSubscriptionModel but the flow is clear now.

Thank you,  
Federico

---

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 25, 2019, 3:16pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/8 "2019-02-25T15:16:51Z")

</div>

Thanks also to your suggestions I implemented readItems() and writeItems() methods and now I’m able to write and read from my device.  
I’m trying to understand how the subsciprion beetwen tags and items works.

I implemented the DriverSubscriptionModel.ModelChangeListener interface in my driver Class and then I added the driver as listener to DriverContext.DriverSubscriptionModel.

Now I can see itemsAdded() itemsRemoved() functions called when there are subscription requests.

Which is the nex step?  
How to manage new Items subscriptions?  
And then, have I to run a task to update items at their own specific scan class?  
How should I do it?

Thanks,  
Federico.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 25, 2019, 6:22pm UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/9 "2019-02-25T18:22:48Z")

</div>

> [@f.pinciaroli](#):
>
> How to manage new Items subscriptions?

Maintain one or more lists within your driver for subscribed items, and ensure that you update them at the requested pace.

> [@f.pinciaroli](#):
>
> And then, have I to run a task to update items at their own specific scan class?

Not so much the scan class but the requested interval from the scan class. I recommend using an executor to schedule repeating runnables at each unique interval among your subscriptions. I would maintain the lists of subscriptions by interval right in the runnable.

---

<div class="post-metadata">

**Author:** ![f.pinciaroli](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/f.pinciaroli/32/6101_2.png) [@f.pinciaroli](https://forum.inductiveautomation.com/u/f.pinciaroli)\
**Post date:** [February 26, 2019, 10:25am UTC](https://forum.inductiveautomation.com/t/custom-driver-development/22767/10 "2019-02-26T10:25:53Z")

</div>

Thank you!  
Great suggestions,I made it and it seems to work…  
Now I have to improve the code and make it more robust, but readm write, browse and subscriptions works.

Thank you again,  
Federico
