# Troi Serial Plug-in 9.0 for FileMaker Pro 2025 USER GUIDE August 2025 You can visit the Troi web site at: www.troi.com Troi Serial Plug-in is copyright 1998-2025 of Troi Automatisering. All rights reserved. # Table of Contents Installing plug-ins If you have problems What can this plug-in do? Software requirements Getting started Using external functions Where to add the external functions? Using script steps Simple example You can use globals or variables Steps for working with Troi Serial Plug-in Specifying the port settings Specifying the handshaking options Receiving data via script triggering Dispatch Scripting using script name Dispatch Scripting for a specific port Script triggering on a match string Controlling input from the serial port Function and script step reference ## Installing plug-ins A plug-in for FileMaker Pro can be installed directly from a container field. Installation is therefore very easy: just open the "All Serial Examples.fmp12" example file and the startup script will install the plug-in for you. See also the EasyInstallTroiPlugins.fmp12 example file which contains the actual plug-in and install script. TIP You can check which plug-ins you have loaded by going to the plug-in preferences: choose Preferences from the Edit menu, and then choose Plug-ins. You can now open the file "All Serial Examples.fmp12" to see how to use the plug-in's functions. There is also a function and script step reference available. ## If you have problems This user guide tries to give you all the information necessary to use this plug-in. So if you have a problem please read this user guide first. You can also visit our support web page: www.troi.com/support This page contains FAQ's (Frequently Asked Questions), help on registration and much more. If that doesn't help you can get free support by email. Send your questions to support@troi.com with a full explanation of the problem. Also give as much relevant information (version of the plug-in, which platform, version of the operating system, version of FileMaker Pro) as possible. Note that due to spam we have to filter incoming email. It might happen that non-spam email is filtered out too. If you have sent an email and you don't get an answer, try to send another email, slightly differently formulated and include the word "FileMaker" in the body text. If you find any mistakes in this manual or have a suggestion please let us know. We appreciate your feedback! TIP You can get more information on returned error codes from the OSErrrs database on our web site. This free FileMaker database lists all error codes for Windows and macOS! ## What can this plug-in do? Troi Serial Plug-in adds serial functions to FileMaker Pro. With this plug-in you can read and write to any serial port that is available on your computer. ## Support for USB to Serial adapters Troi Serial Plug-in supports most USB to Serial adapters, but native USB ports are not supported. USB is a bus protocol that can be used from various purposes and devices, like keyboards, hard disks, CD-ROM drives, adaptors, cameras. All these devices need specific drivers. A serial port can be implemented as virtual port on top of a USB port. The plug-in now has a Serial_GetUSBInfo function, which returns information about the USB port hardware, like the USB vendor ID, vendor name, USB Product name USB Serial number and location ID. The location ID indicates the (physical) location in the USB device tree. For example `0x14200000` can indicate `controller 1 -> USB hub 4 -> port 2`. You can use the location ID to identify a USB serial device by determining which physical port it is plugged into. Finally note that we have currently no plans to create a native USB plug-in. ## Software requirements ### System requirements for macOS macOS 12 (Monterey) macOS 13 (Ventura) macOS 14 (Sonoma) macOS 15 (Sequoia) ### System requirements for Windows Windows 10 including these updates: November 2019 Update May 2020 Update October 2020 Update May 2021 Update November 2021 Update 2022 Update Windows 11 including these updates: 22H2 (September 20, 2022 Update) 23H2 (October 31, 2023 Update) 24H2 (October 1, 2024 Update) ### FileMaker Pro requirements FileMaker Pro Advanced 18 FileMaker Pro 19 FileMaker Pro 20 (FileMaker Pro 2023) FileMaker Pro 21 (FileMaker Pro 2024) FileMaker Pro 22 (FileMaker Pro 2025) ### FileMaker Server requirements FileMaker Server 18 FileMaker Server 19 FileMaker Server 20 (FileMaker Server 2023) FileMaker Server 21 (FileMaker Server 2024) FileMaker Server 22 (FileMaker Server 2025) You can use FileMaker Server to serve databases that use functions of Troi Serial Plug-in (client-side): you need to have the plug-in installed at the clients that use these functions. Troi Serial Plug-in can also be used by FileMaker Server as a server-side plug-in or as a plug-in used by the web publishing engine. More information can be found in the download or on our web site. ## Getting started ### Using external functions Troi Serial Plug-in adds new functions to the standard functions that are available in FileMaker Pro. The functions added by a plug-in are called external functions. You can see those extra functions for all plug-ins at the top right of the Specify Calculation box: You use special syntax with external functions: FunctionName ( parameter1 ; parameter 2 ) where FunctionName is the name of an external function. A function can have zero or more parameters. Each parameter is separated by a semi-colon. Plug-ins don't work directly after installation. To access a plug-in's function, you need to add the calls to the function in a calculation, for example in a text calculation in Define Fields or in a script in Script Workspace (formaly called ScriptMaker). ### Where to add the external functions? Most of the external functions for this plug-in are intended to be used in a Set Field or Set Variable script step using a calculation. For most functions of this plug-in it makes no sense to add them to a define field calculation, as the functions will have side effects. Only the Serial_AsciiValueToText and Serial_TextToAsciiValue functions have no side effects and can be used in a define field calculation. ### Using script steps Starting with FileMaker 16 plug-ins can also add script steps. You can select these script steps in the script steps pane in Script Workspace, or you can begin typing the script step name, then choose the script step from the list that appears. The script steps significantly expand the possible actions you can perform with FileMaker Pro. screenshot of Troi File Plug-in script step NOTE only steps that perform an action have been added as a script step. Functions that just return information (like for example Serial_GetPortNames) are only available as an external function. ### Simple example We start with a simple example to get you started. Create a new database, with a global text field called gPortNames. Create a new script called "Get Serial Port Names". Delete all steps and then add the following script step:
      Set Field [ gPortNames ; Serial_GetPortNames ( "-Unused" ) ]
This shows the call to the Serial_GetPortNames function. This function has only one parameter, switches, which is currently not used, so "-Unused" is given as value. Performing this script will return all the serial ports that can be found on this computer, separated by returns. On Windows the result will be something like this: COM1¶ COM2¶ COM3¶ COM4¶ NOTE Function names, like Serial_GetPortNames, are not case sensitive. Please take a close look at the included example files, as they provide a great starting point. From there you can move on, using the functions of the plug-in as building blocks. Together they give you great new tools to access serial ports. ### You can use globals or variables With the release of FileMaker Pro 8 and later it is possible to use variables in calculations. Our example files in the download now both use global fields and variables to pass parameters and store the results of a plug-in function. We continue to move the scripts to use variables wherever possible. Note that not all examples are using variables yet. All plug-in functions work with variables just fine. For example if you have this script steps
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ; "port1" ) ]
With variables you can alternative use:
      Set Variable [ $ErrorCode ; Serial_Open ( "-Unused" ; "port1" ) ]
The main advantage of variables is that you don't need to define global fields that clutter your database definitions. The variables can stay local to the script. ## Steps for working with Troi Serial Plug-in Below you find an overview of the main steps needed to communicate with a serial port: 1 - Find available ports Use the function "Serial_GetPortNames" to get the names of all serial ports that are available on the computer and let the end user choose a port. 2 - Open the selected port Use the function "Serial_Open" to open a port. Optionally use the function "Serial_SetDispatchScript" to specify which script is triggered when data comes in from the serial port. 3 - Communicate with the serial port Use the functions "Serial_Send" and "Serial_Receive" to send and receive data to and from a serial port. You can use other functions, like "Serial_DataWasReceived", to help you get the data into a FileMaker database. 4 - Close the serial port At the end of the communication you need to close the serial port. ## Specifying the port settings Default port settings A serial port can be configured in a lot of ways. These settings can be set by specifying the settings parameter of Serial_Open. If you don't specify any settings the port is initialized to the following settings: a speed of 9600 baud, no parity, 8 data bits, 1 stop bit, no handshaking. If you want to use this setting, open the port like this:
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ; "COM2" ) ]
Specifying other port settings It is recommended that you set the port settings explicitly. Give the settings by concatenating the desired settings keywords. You specify them like this:
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ;
                  "COM2" ; "baud=9600 parity=none data=8 stop=10 flowControl=XOnXOff" ) ]
You can set the speed, the parity, the number of data and stopbits, and the handshaking to use. Note that the order of the keywords and case are ignored. All keywords are optional and should be separated by a space or a return. Specifying the port speed The port speed indicates how quickly the data is transported over the serial line. Allowed values for the port speed are:

      baud=150   baud=1800   baud=7200   baud=28800   baud=115200
      baud=300   baud=2400   baud=9600   baud=38400   baud=230400
      baud=600   baud=3600   baud=14400   baud=57600
      baud=1200   baud=4800   baud=19200
NOTE Not all speeds may be supported on all serial ports. Check the documentation of the computer and the equipment you want to connect. You need to specify the same speed that the other equipment is using. Higher port speeds can result in loss of data if the serial cable can't cope with this speed. If this happens try a lower speed. Specifying the bit format options Data over a serial port is sent in small packets of 4 to 10 bits. These packets consist of 4-8 data bits, followed by a parity bit and stopbits. Data bits You can specify the number of the data bits by adding one of the data size keywords to the switch parameter. The most used value is 8 data bits. Allowed values for the number of data bits are:

      data=4   data=5   data=6   data=7   data=8
Parity bits You can specify the parity bit by adding one of the following keywords to the switch parameter:
      parity=none
      parity=odd
      parity=even
Stop bits You can specify the number of stopbits by adding one of the following keywords to the switch parameter:
      stop=10
      stop=15
      stop=20
Here stop=10 means 1 stop bit, stop=15 means 1.5 stopbit and stop=20 means 2 stopbits. ## Specifying the handshaking options Handshaking is a way to ensure that the transfer of data can be stopped temporarily. This is also called (data) flow control. A serial port can use hardware handshaking and software handshaking. For hardware handshaking to work the serial cable must have wires to support it. Using the Serial_Open function this plug-in allows a basic way to set the handshaking and also an advanced way, which gives more options, but most users probably don't need. Basic handshaking options Basic handshaking has 3 keywords:

      flowControl=DTRDSR   flowControl=RTSCTS   flowControl=XOnXOff
You can specify one or more of these flow control keywords. You should specify at least one of these keywords. Try flowControl=DTRDSR as this is mostly supported. flowControl=DTRDSR and flowControl=RTSCTS are hardware handshaking options, for which you need proper cabling. flowControl=XOnXOff is a software based handshake option. `flowControl=DTRDSR` means that the signal DTR is used for input flow control and DSR for output flow control. `flowControl=RTSCTS` means that the signal RTS is used for input flow control and CTS for output flow control. `flowControl=XOnXOff` uses a XOff character (control-S) and a XOn character (control-Q) to stop input and output flow. IMPORTANT Do not use `FlowControl=XOnXOff` if you want to transfer binary data, like pictures. This protocol uses two ASCII characters that might also be in the binary data. `FlowControl=XOnXOff` works fine with normal text. Example 1
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ;
                "COM2" ; "baud=9600 parity=none data=8 stop=10 flowControl=DTRDSR" ) ]
This will set the port to use DTR/DSR hardware handshaking. Example 2
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ; "COM2" ;
               "baud=9600 parity=none data=8 stop=10 flowControl=DTRDSR flowControl=RTSCTS
                flowControl=XOnXOff" ) ]
This will set the port to use all 3 types of handshaking in parallel. Advanced handshaking options Advanced handshaking options allows you more control over the serial port settings. It enables you to set the handshaking of the output and input separately. With advanced handshaking you can use the following keywords:
keyword | meaning
inputControl=XOnXOff | use XOnXOff for input handshaking
outputControl=XOnXOff | use XOnXOff for output handshaking
inputControl=RTS | use RTS for input handshaking
outputControl=CTS | use CTS for output handshaking
inputControl=DTR | use DTR for input handshaking
outputControl=DSR | use DSR for output handshaking
DTR=enabled | set DTR signal permanent to high
DTR=disabled | set DTR signal permanent to low
RTS=enabled | set RTS signal permanent to high
RTS=disabled | set RTS signal permanent to low
Below you find how the basic handshaking keywords relate to the advanced handshaking keywords:
basic keyword | = | the same as 2 advanced keywords
flowControl=XOnXOff | = | inputControl=XOnXOff outputControl=XOnXOff
flowControl=RTSCTS | = | inputControl=RTS outputControl=CTS
flowControl=DTRDSR | = | inputControl=DTR outputControl=DSR
The other advanced keywords don't have an equivalent. NOTE You can mix the basic handshaking keywords with the advanced handshaking keywords, as long as this is sensible. Example 1 If you want to use DTR handshaking for input flow control and CTS for output flow control use the following settings to open COM1:
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ; "COM1" ;
            "baud=9600 parity=none data=8 stop=10 outputControl=CTS inputControl=DTR" ) ]
Example 2 If you want to enable the DTR signal and use XOnXOff input flow control use the following settings to open COM1:
      Set Field [ gErrorCode ; Serial_Open ( "-Unused" ; "COM1" ;
                "baud=9600 parity=none data=8 stop=10 DTR=enabled inputControl=XOnXOff" ) ]
Example 3
      Set Variable [ $ErrorCode ; Serial_Open ( "-Unused" ; "COM2" ;
                "baud=9600 data=7 parity=odd stop=20 flowControl=XOnXOff " &
                "outputControl=CTS inputControl=DTR" ) ]
This shows that XOnXOff is used for input and output flow control and also DTR handshaking for input flow control and CTS for output flow control. ## Receiving data via script triggering The Plug-in API for FileMaker Pro 7 and later has an official way to trigger scripts (or dispatch scripts). It is possible on all platforms to trigger scripts by filename and script name. Version 5.5 and later of the Serial Plug-in implements this triggering. Other ways of triggering are no longer needed. Functions to implement Dispatch Scripting The following external functions help in achieving the receiving of data via the Dispatch Script.
Serial_SetDispatchScript | tell the plug-in which (Dispatch) script to trigger when data is received
Serial_DataWasReceived | returns the name of the port when data was received on an open port
The following function is no longer needed, and is no longer present in Troi Serial Plug-in 5.5 and later:
Serial_RestoreSituation
TIP See the example file Terminal.fmp12 for a working example. ### Dispatch Scripting using script name This method will trigger a script when data is received on one of the open ports. Usually you set the dispatch script once after you have opened the serial port(s). Example "Set Dispatch Script with name" Below you find a sample Set Dispatch Script:
      Set Field [ gErrorCode ; Serial_SetDispatchScript ( "-Unused" ; "" ;
                      Get ( FileName ) ; "Process Data Received" ) ]
      If [ Left ( gErrorCode ; 2 ) = "$$" ]
            Beep
            Show Message [ An error occurred while setting the dispatch script ]
            Halt Script
      End If
This tells the plug-in to trigger the script Process Data Received whenever incoming data from (one of) the serial port(s) is available. In the script Process Data Received you can retrieve the incoming data, and store it, and do any other processing. ### Dispatch Scripting for a specific port This plug-in can also trigger different scripts for different open ports. This is done with the Serial_Open function. This is how this can be done: Example Dispatch Script for specific port Below you find a sample Dispatch Script:
      Set Variable [ $ErrorCode ; Serial_Open ( "-Unused" ;
                      gPortName1 ; "baud=19200 parity=none" ; Get ( FileName ) ;
                      "Process Data Received for 1st Port" ) ]
      If [ Left ( $ErrorCode ; 2 ) = "$$" ]
            Beep
            Show Message [ "An error occurred while opening the port." ]
            Halt Script
      End If
This script will open the port gPortName1 and will trigger script "Process Data Received for 1st Port" when data comes in on this port. If both triggering with Serial_Open and also with Serial_SetDispatchScript has been specified the trigger script specified with Serial_Open takes precedence. Example Process Data Received script Below you find a sample "Process Data Received" script, which gets the data from the plug-in into the field mesReceived.
      Enter Browse Mode []
      Set Field [ gTempResultReceived ; Serial_Receive ("-Unused" ;  gPortName ) ]
      Set Field [ mesReceived ; mesReceived & gTempResultReceived ]
Example "Set Dispatch Script" script Below you find a sample "Set Dispatch Script" script:
      Set Field [ gErrorCode ;  Serial_SetDispatchScript ( "-Unused" ;
                                        Get ( FileName ) ; "MyTriggerScript" ) ]
      If [ Left ( gErrorCode ; 2 ) = "$$" ]
            Beep
            Show Message [ An error occurred while setting the dispatch script ]
            Halt Script
      End If
Example Start Receiving script Below you find a sample "Start Receiving" script:
      Perform Script [ Sub-scripts ; "Open Serial Port" ]
      Perform Script [ Sub-scripts ; "Set Dispatch Script" ]
When you want to begin receiving perform the "Start receiving script". ## Script triggering on a match string The Serial plug-in can look for a special match string that has to arrive at the input buffer before it triggers a script. When you specify the dispatch script, you can add the waitstring parameter. The script step below will open a port with a dispatch script Process Data Received, which is only triggered after the string OK is received in the input buffer.
      Set Field [ gErrorCode ; Serial_SetDispatchScript ( "-Unused" ;
                      Get (FileName ) ;
                      "Process Data Received" ;
                      "OK" ) ]
The script step below will set a dispatch script Process Data Received , which is only triggered after a CR (carriage return) character, followed by a LF (linefeed) character is received. These are the ASCII characters 0x0D and 0x0A respectively (see the ASCII Table in the ASCII.fmp12 file in the download). Using the Serial_AsciiValueToText function we set the waitstring like this:
      Set Field [ gErrorCode ; Serial_SetDispatchScript ( "-Unused" ;
                      Get ( FileName ) ;
                      "Process Data Received" ;
                      Serial_AsciiValueToText ( "-Unused" ; "OxOD Ox0A" ) ]
There is no longer a length limitation on the waitstring. ### Getting the last match string It is also possible to get the last string of text that matches the match string. You specify this in the Serial_Receive function. You need to have this script step:
      Set Field [ gResult ; Serial_Receive ( "-GetLastMatch" ; "COM1" ; ]
Example We assume, like the example above, to be waiting for match `"<CR><LF>"` and this data comes in:
      12345<CR><LF>
      434343<CR><LF>
      5678<CR><LF>
      12
If we now run the Serial_Receive script step this data is received in the gResult field:
      5678<CR><LF>
All earlier data is discarded. ## Controlling input from the serial port The function "Serial_Control" controls the serial port. With this function you can suspend or resume the incoming data. This command is very useful for devices that send out continuous data, like an electronic weighing scale. NOTE The buffer will be emptied when the port is suspended. So when you give the resume command only the data received after this command will be received. NOTE You can continue to send data to the serial port. Example 1
      Set Field [ gResult ; Serial_Control ( "-Suspend" ; "Modem port" ) ]
This will suspend the incoming stream of data from the Modem port.
      Set Field [ gResult ; Serial_Control ( "-Resume" ; "Modem port" ) ]
This will resume the previously suspended incoming stream of data from the Modem port. Example 2 Say you have an electronic weighing scale that sends data to the serial port continuously. The data is in this form:
      1200 kg net CR LF
      1199 kg net CR LF
      1200 kg net CR LF
      1200 kg net CR LF
      etc.
You are only interested in this data when you are actually weighing something. So the best way to handle this is to open the serial port and then suspend this port. When you want to measure something you send a resume command, and gather a full line of data, then suspend the port again. You need to define these fields:
gPortName | global text field, to hold the port name
gErrorCode | global text field, to hold the error code in
weight | number field, to store the weight
When starting up the database you issue these commands in a startup script:
      Set Field [ gPortName ; "COM2" ]
      Set Field[ gErrorCode ; Serial_Open ( "-Unused" ; gPortName ; "baud=19200" ) ]
      If [ gErrorCode = 0 ]
            Set Field [ gErrorCode ; Serial_Control ( "-Suspend" ; gPortName ) ]
      End If
This will open the port and then wait till further notice. When the user of the database presses a button you start this Measure Now script:
      Set Field [ gTempResultReceived ; "" ]
      Set Field [ gTempBuffer ; "" ]
      Set Field [ gNumber ; 10 ]
      # ...Resume the incoming data...
      Set Field [ gErrorCode ; Serial_Control ( "-Resume" ; gPortName ) ]
      If [ gErrorCode = 0 ]
      	Loop
            Set Field [ gTempResultReceived ; Serial_Receive ( "-Unused" ;  gPortName ) ]
            Set Field [ gTempBuffer ; gTempBuffer & gTempResultReceived ]
            Exit Loop If [PatternCount ( gTempBuffer ; "¶" ) >= 2 or gErrorCode <> 0 ]
            Pause/Resume Script [ 0:00:01 ]
            Set Field [ gNumber ; gNumber - 1 ]
            If [ gNumber = 0 ]
                    Set Field [ gErrorCode ; -1 ]
            End If
      	End Loop
        Set Field [ gNumber ; Serial_Control ( "-Suspend" ; gPortName ) ]
      End If
      Perform Script [ Sub-scripts ; Store Measure Results ]
The Measure Now script resets the buffers, then resumes the incoming data. Inside the loop the data is received until there are 2 returns in the buffer, which means a complete line was received. The script then suspends the port again and then the script Store Measure Results is called to store the results in a record. To prevent this looping forever when no data is received we also use a counter, gNumber. It starts at 10 and is lowered every time through the loop. After 10x the script gives up and an error code of -1 is set, to get out of the loop. Here is the Store Measure Results script:
      If [ gErrorCode = 0 and PatternCount ( gTempBuffer ; "¶" ) >= 2 ]
      	New Record/Request
        #...Cut off at the end of the line...
        Set Field [ gTempBuffer ; Left ( gTempBuffer ;
        	Position ( gTempBuffer ; "¶" ; Length ( gTempBuffer ) ; -1 ) - 1 ) ]
        #...Copy one line from the end...
        Set Field [ Weight ; Middle ( gTempBuffer ;
            Position ( gTempBuffer ; "¶" ; Length ( gTempBuffer ) ; -1 ) + 1 ;
            Length ( gTempBuffer ) ) ]
      Else
      	Beep
        Show Message [ An error occurred! ]
      End If
      Go to Field []
This script will create a new record and find the last line in the buffer, and store it in the field Weight. ## Function and script step reference For a description of all External Functions and External Script Steps added by Troi Serial Plug-in please see the separate Reference.fmp12 file. For each function and script step you will find: the correct syntax the parameters/options to be used the returned result special considerations an example usage The same information is also available as online help on Troi's web site. You can easily consult the online help directly from FileMaker, by clicking the Help button (the small question mark button) next to the function description in the functions pane or the script step description in the script steps pane.