Yep, there’s a project_file command that will let you start a print remotely using a path on the SD card, and configure all the additional settings (including AMS mapping, which itself is quite complex).
{
"print": {
"ams_mapping": [ <array of id's, explained below > ],
"bed_leveling": true/false,
"bed_type": "hot_plate"/"eng_plate"/"textured_plate"/"cool_plate",
"command": "project_file",
"file": "" (not needed),
"flow_cali": true/false,
"layer_inspect": true/false,
"param": "Metadata/plate_1.gcode", (replace "1" with whichever plate id you want to print from 3mf. They are always in the format of "Metadata/plate_#.gcode". Open 3mf in 7zip to view)
"profile_id": "" (not needed, big number as str),
"project_id": "" (not needed, big number as str),
"sequence_id": "2222" (just any number as a str),
"subtask_id": "" (not needed, big number as str),
"subtask_name": "Some Name" (Name of print, for convenience, make same as 3mf filename without path, optional leave extensions in, as this is what it usually is unless manually overridden),
"task_id": "" (not needed, big number as str),
"timelapse": true/false,
"url": "file:///sdcard/YOURFILE.3mf" (more explained below),
"use_ams": true/false,
"vibration_cali": true/false
}
}
‘url’ logic
It can be like “file:///sdcard/filename.gcode.3mf” too, browse the printer’s sd card via FTPS to see exactly.
Could also be “ftp:///file.3mf” or “ftp:///file.gcode.3mf”, these will self-resolve internally too if at root, but may need /sdcard or /cache infront depending on true location.
You’ll need to play around. AFAIK A1 series is only one that specifies an sdcard in the path. X1 and P1 usually treat it as root, and a /cache folder.
Fun fact, this will also take 3mf’s from HTTP addresses too, including locally hosted ones if you’re into that.
AMS Mapping logic
AMS mapping logic is tricky to get right. If you do not use an ams, you can leave it out of the request and set use_ams to false. If you have an ams, you will likely want to set the AMS mapping. Note, that if you have use_ams to false, an ams_mapping would essentially end up being [0], but if true, it’s different still.
So backstory is, when you slice the 3mf file, it embeds all filament profiles you had “loaded” in the project in the slicer, even if it’s not used for the plate you are printing or any plates. As long as it’s added with the + button to the project, it’s embedded.
The values in the array are the tray id’s from AMS units. So if you have 1 AMS unit, it’s id’s 0,1,2,3 for tray 1,2,3,4. Since you have A1 series, atm it only can have 1 AMS, so you don’t need to worry for more. But if they expand it or you tinker with P1/X1 series, then it’ll continue increasing (so AMS 2 tray 1 is id 4, tray 2 is id 5 etc).
When making the AMS mapping, it uses the same order as filaments you had ordered in the slicer at time of slicing, and assigns a tray id to that slot.
So if you had 3 filaments loaded into the slicer when you made your 3mf, but only used 2 for a plate you’re printing, and let’s say the first one mapped to slot 3, second mapped to slot 4, and third to slot 1, then your AMS mapping would be: [2, -1, 0].
The -1 means that the second filament profile you had in the slicer is unused, but ones after it were, so it tells the printer to skip over it. If you used 4 profiles in the slicer, and used all 4, it would have 4 elements, but the order depends on which AMS tray you mapped to which profile in the slicer, which is not usually in sync.
So yeah, you need pretty good knowledge of what the filament mappings were in a 3mf to assign them properly, and even more knowledge of what’s actually in your AMS unit. The length of the array for a specific 3mf will always be for however many filaments were embedded when slicing, and will share the same order. Though keep in mind the tray id’s incrementing and the position in the array are not at all linked, if they ever are it’s purely by coincidence.
If you want to build some fancy logic on this, you can figure out the embedded profiles’ ordering and information (type, colour, amt used, profile name etc etc) by extracting and unzipping the 3mf file, and parsing the gcode file (and some other files in there too can help).