Programmatically Connect to Serial Devices with Player Triggers

I like to use the Player (Serial Only) driver a lot. It’s my preferred way of connecting to devices like Zebra printers, as all your message configuration is done in the App Editor - no need to switch between App, App Editor, and Device Configuration to make code changes!

But a common issue here is that the driver needs to reference a COM port - the PC’s internal reference for the specific USB port plugged into the device. If the device is moved, plugged into a different port on my PC - even if it’s the same type of port - the COM number will be different, and my app will no longer work.

With the newly-added ARRAY_INDEX_OF() function, I’m now able to determine this port programmatically and remove this “it must always be this port” dependency from my app.
(If you’re familiar with Excel, this method will look similar to index-match)


In the App Editor:

The List Ports function displays a list of objects in a Tulip App. Normally, I manually read this list and hard-code a port (here, COM3) into my subsequent serial triggers:

If I know what number row (what index) my printer connection is on, I can pull the correct COM port regardless of what it may have changed to.

I know the manufacturer “FTDI” is going to be unique enough to reliably find this device at this PC, so I’ll use that as my search term. However, to search I need to create a single-width list of that column “manufacturer”…

Store expression MAP_TO_TEXT_LIST(@Variable.ports, 'manufacturer') in variable “All Manufacturers List”

“All Manufacturers List” now has the value ['FTDI', 'wch.cn']

Then, I search through this list for the item in question:
Store expression ARRAY_INDEX_OF(@Variable.All Manufacturers List, 'FTDI') in variable “Target Port Index”

“Target Port Index” now has the value 0, indicating the first row in my table.
All that’s left is to pull the COM info from the row I just found:

Get from Index in Array, with:

  • Array >> “ports”
  • Index >> Variable >> “Target Port Index”

Store in Variable >> “COM Port Row”

“COM Port Row” is now an object with values:

COM Port Row: { "path": "COM3", "manufacturer": "FTDI", "serialnumber":"A9XE70R4", ... }

I can now reference COM Port Row.path in any future triggers (like a Connect or Send function)! I recommend putting this flow to run “At App Start”, so every time your user starts the app Tulip will search through all available COM ports and select the one relevant to your device.

Hope this helps!

3 Likes

I was applying this approach to connect multiple potentially-connected devices on App Start but this is frustrated by the trigger sequence stopping upon the first failed connection (i.e. device not connected). The only work around I can think of is to have a bunch of “startup steps”, one for each device, that attempt to connect each device in turn (and produce a message/error accordingly).

Thought of another option - if I make the CONNECT conditional, that should resolve it…

UPDATE: this works!

image

1 Like

@jmlowden hey, nice! I like the many-triggers method you have here, too, because it lets you be verbose about which connections succeed and fail (and have a single source-of-truth for a device’s reference information, rather than needing lookup tables or something). let me know if anything else comes up!

1 Like

Next step for me will be to try to do these connections, looping from a list of devices populated from a Tulip Table, so I only try to connect devices that are “Active Record? = yes” in the table (i.e. if calibration due date for device is past, as part of the loop set Active = no, skip connection, and move to the next.

most likely the problem is that the new usb port you chose does not have its drivers installed
cheers