Pluggable discovery specification
Discovery tools are a special kind of tool used to find supported boards, a platform developer can create their own following the specification below. These tools must be in the form of executables that can be launched as a subprocess using a
platform.txtPluggable discovery API via stdin/stdout
All the commands listed in this specification must be implemented in the discovery.
After startup, the tool will just stay idle waiting for commands. The available commands are:
HELLOSTARTSTOPQUITLISTSTART_SYNCAfter each command the client always expects a response from the discovery. The discovery must not introduce any delay and must respond to all commands as fast as possible.
HELLO command
HELLOHELLO <PROTOCOL_VERSION> "<USER_AGENT>"
 is the maximum protocol version supported by the client/IDE (currently- <PROTOCOL_VERSION>
 )- 1
 is the name and version of the client. It must not contain double-quotes (- <USER_AGENT>
 ).- "
some examples:
- HELLO 1 "Arduino IDE 1.8.13"
- HELLO 1 "arduino-cli 1.2.3"
the response to the command is:
1{2  "eventType": "hello",3  "protocolVersion": 1,4  "message": "OK"5}The
protocolVersion- if the client/IDE supports the same or a more recent version of the protocol than the discovery, then the client/IDE should go into a compatibility mode and use the protocol level supported by the discovery.
- if the discovery supports a more recent version of the protocol than the client/IDE: the discovery should downgrade
itself into compatibility mode and report a 
 that is less than or equal to the one supported by the client/IDE.protocolVersion
- if the discovery cannot go into compatibility mode, it must report the protocol version supported (even if greater than the version supported by the client/IDE) and the client/IDE may decide to terminate the discovery or produce an error/warning.
START command
The
STARTLIST1{2  "eventType": "start",3  "message": "OK"4}If the discovery could not start, for any reason, it must report the error with:
1{2  "eventType": "start",3  "error": true,4  "message": "Permission error"5}The
errortruemessageSTOP command
The
STOP1{2  "eventType": "stop",3  "message": "OK"4}If an error occurs:
1{2  "eventType": "stop",3  "error": true,4  "message": "Resource busy"5}The
errortruemessageQUIT command
The
QUITQUIT1{2  "eventType": "quit",3  "message": "OK"4}after this output the discovery exits. This command is supposed to always succeed.
LIST command
The
LIST1{2  "eventType": "list",3  "ports": [4    {5      "address":       <-- THE ADDRESS OF THE PORT6      "label":         <-- HOW THE PORT IS DISPLAYED ON THE GUI7      "protocol":      <-- THE PROTOCOL USED BY THE BOARD8      "protocolLabel": <-- HOW THE PROTOCOL IS DISPLAYED ON THE GUI9      "hardwareId":    <-- A STRING THAT UNIQUELY IDENTIFIES A BOARD INSTANCE10      "properties": {11                       <-- A LIST OF PROPERTIES OF THE PORT12      }13    },14    {15      ...              <-- OTHER PORTS...16    }17  ]18}The
portsEach port has:
- an 
 (for example- address
 for serial ports or- /dev/ttyACM0
 for network ports)- 192.168.10.100
- a 
 that is the human readable form of the- label
 (it may be for example- address
 or- ttyACM0
 )- SSH on 192.168.10.100
 is the protocol identifier (such as- protocol
 or- serial
 or- dfu
 )- ssh
 is the- protocolLabel
 in human readable form (for example- protocol
 or- Serial port
 or- DFU USB
 )- Network (ssh)
 (optional) a string that uniquely identifies a specific board instance (even among other boards of the same model). Different ports with the same- hardwareId
 must belong to the same board instance. The identifier should be sufficiently long to uniquely identify the board instance and reduce the probability of collisions. Good examples of- hardwareId
 values are: Ethernet MAC Address, USB Serial Number, CPU-ID number, etc.- hardwareId- This value should not be used to identify the board model (see the board identification section for more information about identification of the board model). 
 is a list of key/value pairs that represent information relative to the specific port.- properties
To make the above more clear let's show an example output from the
serial-discovery1{2  "eventType": "list",3  "ports": [4    {5      "address": "/dev/ttyACM0",6      "label": "ttyACM0",7      "protocol": "serial",8      "protocolLabel": "Serial Port (USB)",9      "hardwareId": "EBEABFD6514D32364E202020FF10181E",10      "properties": {11        "pid": "0x804e",12        "vid": "0x2341",13        "serialNumber": "EBEABFD6514D32364E202020FF10181E",14        "name": "ttyACM0"15      }16    }17  ]18}In this case the serial port metadata comes from a USB serial converter. Inside the
propertiesThe
hardwareIdserialNumberThe
LISTSome discoveries may require some time to discover a new port (for example network protocols like MDNS, Bluetooth, etc. require some seconds to receive the broadcasts from all available clients) in that case it is fine to answer with an empty or incomplete list.
If an error occurs and the discovery can't complete the enumeration, it must report the error with:
1{2  "eventType": "list",3  "error": true,4  "message": "Resource busy"5}The
errortruemessageSTART_SYNC command
The
START_SYNCaddremove1{2  "eventType": "start_sync",3  "message": "OK"4}After this message the discovery will send
addremove1{2  "eventType": "start_sync",3  "error": true,4  "message": "Resource busy"5}The
errortruemessageOnce in "event" mode, the discovery is allowed to send
addremoveThe
add1{2  "eventType": "add",3  "port": {4    "address": "/dev/ttyACM0",5    "label": "ttyACM0",6    "hardwareId": "EBEABFD6514D32364E202020FF10181E",7    "properties": {8      "pid": "0x804e",9      "vid": "0x2341",10      "serialNumber": "EBEABFD6514D32364E202020FF10181E",11      "name": "ttyACM0"12    },13    "protocol": "serial",14    "protocolLabel": "Serial Port (USB)"15  }16}It basically provides the same information as the
listSTART_SYNCThe
remove1{2  "eventType": "remove",3  "port": {4    "address": "/dev/ttyACM0",5    "protocol": "serial"6  }7}The content is straightforward, in this case only the
addressprotocolIf the information about a port needs to be updated the discovery may send a new
addremoveInvalid commands
If the client sends an invalid or malformed command, the discovery should answer with:
1{2  "eventType": "command_error",3  "error": true,4  "message": "Unknown command XXXX"5}State machine
A well behaved pluggable discovery tool must reflect the following state machine.

The arrows represent the commands outlined in the above sections, calling a command successfully assumes the state changes.
A pluggable discovery state is Alive when the process has been started but no command has been executed. Dead means the process has been stopped and no further commands can be received.
Board identification
The
properties- each board listed in the platform file 
 may declare a set ofboards.txt
 propertiesupload_port.*
- if each 
 property has a match in theupload_port.*
 set coming from the discovery then the board is a "candidate" board attached to that port.properties
Some port
propertiespropertiesLet's see an example to clarify things a bit, let's suppose that we have the following
properties1"port": {2    "address": "/dev/ttyACM0",3    "properties": {4      "pid": "0x804e",5      "vid": "0x2341",6      "serialNumber": "EBEABFD6514D32364E202020FF10181E",7      "name": "ttyACM0"8    },9    ...in this case we can use
vidpidserialNumberboards.txt1# Arduino Zero (Programming Port)2# ---------------------------------------3arduino_zero_edbg.name=Arduino Zero (Programming Port)4arduino_zero_edbg.upload_port.vid=0x03eb5arduino_zero_edbg.upload_port.pid=0x21576[...CUT...]7# Arduino Zero (Native USB Port)8# --------------------------------------9arduino_zero_native.name=Arduino Zero (Native USB Port)10arduino_zero_native.upload_port.0.vid=0x234111arduino_zero_native.upload_port.0.pid=0x804d12arduino_zero_native.upload_port.1.vid=0x234113arduino_zero_native.upload_port.1.pid=0x004d14arduino_zero_native.upload_port.2.vid=0x234115arduino_zero_native.upload_port.2.pid=0x824d16arduino_zero_native.upload_port.3.vid=0x234117arduino_zero_native.upload_port.3.pid=0x024d18[...CUT...]19# Arduino MKR100020# -----------------------21mkr1000.name=Arduino MKR100022mkr1000.upload_port.0.vid=0x2341       <------- MATCHING IDs23mkr1000.upload_port.0.pid=0x804e       <------- MATCHING IDs24mkr1000.upload_port.1.vid=0x234125mkr1000.upload_port.1.pid=0x004e26mkr1000.upload_port.2.vid=0x234127mkr1000.upload_port.2.pid=0x824e28mkr1000.upload_port.3.vid=0x234129mkr1000.upload_port.3.pid=0x024e30[...CUT...]As we can see the only board that has the two properties matching is the
mkr1000Note that
vidpidboards.txtupload_port.*We can also specify multiple identification properties for the same board using the
.N1myboard.name=My Wonderful Arduino Compatible Board2myboard.upload_port.pears=203myboard.upload_port.apples=30will match on
pears=20, apples=301myboard.name=My Wonderful Arduino Compatible Board2myboard.upload_port.0.pears=203myboard.upload_port.0.apples=304myboard.upload_port.1.pears=305myboard.upload_port.1.apples=40will match on both
pears=20, apples=30pears=30, apples=40pears=20, apples=40An important note about vid
 and pid
vidpidThe board identification properties should be used only if they allows to match the board model beyond any doubt. Sometimes a board do not expose a unique vid/pid combination, this is the case for example if a USB-2-serial converter chip is used (like the omnipresent FT232 or CH340): those chips exposes their specific vid/pid that will be the same for all the other boards using the same chip. In such cases the board identification properties should NOT be used.
Identification of board options
Custom board options can also be identified.
Identification property values are associated with a custom board option by the board definition in
. Two formats are available.boards.txt
If only a single set of identification properties are associated with the option:
1BOARD_ID.menu.MENU_ID.OPTION_ID.upload_port.PORT_PROPERTY_KEY=PORT_PROPERTY_VALUEIf one or more sets of identification properties are associated with the option, an index number is used for each set:
1BOARD_ID.menu.MENU_ID.OPTION_ID.upload_port.SET_INDEX.PORT_PROPERTY_KEY=PORT_PROPERTY_VALUEIf multiple identification properties are associated within a set, all must match for the option to be identified.
Let's see an example to clarify it, in the following
boards.txt1myboard.upload_port.pid=0x00102myboard.upload_port.vid=0x23413myboard.menu.cpu.atmega1280=ATmega12804myboard.menu.cpu.atmega1280.upload_port.c=atmega1280          <--- identification property for cpu=atmega12805myboard.menu.cpu.atmega1280.build_cpu=atmega12806myboard.menu.cpu.atmega2560=ATmega25607myboard.menu.cpu.atmega2560.upload_port.c=atmega2560          <--- identification property for cpu=atmega25608myboard.menu.cpu.atmega2560.build_cpu=atmega25609myboard.menu.mem.1k=1KB10myboard.menu.mem.1k.upload_port.mem=1                         <--- identification property for mem=1k11myboard.menu.mem.1k.build_mem=102412myboard.menu.mem.2k=2KB13myboard.menu.mem.2k.upload_port.1.mem=2                       <------ identification property for mem=2k (case 1)14myboard.menu.mem.2k.upload_port.2.ab=ef                       <---\15myboard.menu.mem.2k.upload_port.2.cd=gh                       <---+-- identification property for mem=2k (case 2)16myboard.menu.mem.2k.build_mem=2048we have a board called
myboardcpumemA port with the following identification properties:
1vid=0x00102pid=0x23413c=atmega2560will be identified as FQBN
mypackage:avr:myboard:cpu=atmega2560c=atmega2560A port with the following identification properties:
1vid=0x00102pid=0x23413c=atmega25604mem=2will be identified as FQBN
mypackage:avr:myboard:cpu=atmega2560,mem=2kA port with the following identification properties:
1vid=0x00102pid=0x23413c=atmega25604ab=ef5cd=ghwill be identified as FQBN
mypackage:avr:myboard:cpu=atmega2560,mem=2kmem=2k