Populating Input_Select options from REST

I’ve been integrating controls for Octopi in my Hass setup running in Docker. I have just about everything finished except one major piece. I’m trying to gain the ability to select an STL file from Octopi within Hass and send the print command for that file from Hass. Without that feature, you still have to login to Octopi to select the file to print, which to me makes controlling the printer at all within Hass kinda pointless since you would already be logged into Octopi at that point anyway.

According to the Octoprint REST page if I use this:

GET /api/files HTTP/1.1
Host: example.com
X-Api-Key: abcdef...

I can get a JSON file containing the files currently stored in Octopi. However they are all mixed within other data I don’t need:

{
  "files": [
    {
      "date": 1577046092, 
      "display": "Baby_Yoda_v2.2.gcode", 
      "gcodeAnalysis": {
        "dimensions": {
          "depth": 50.736000000000004, 
          "height": 53.0, 
          "width": 49.312
        }, 
        "estimatedPrintTime": 12350.724723496645, 
        "filament": {
          "tool0": {
            "length": 5920.939400004707, 
            "volume": 0.0
          }
        }, 
        "printingArea": {
          "maxX": 124.597, 
          "maxY": 125.812, 
          "maxZ": 53.09, 
          "minX": 75.285, 
          "minY": 75.076, 
          "minZ": 0.09
        }
      }, 
      "hash": "024b5b4370b24d41e79315122681a52718879702", 
      "name": "Baby_Yoda_v2.2.gcode", 
      "origin": "local", 
      "path": "Baby_Yoda_v2.2.gcode", 
      "prints": {
        "failure": 0, 
        "last": {
          "date": 1577061984.755321, 
          "printTime": 15103.536770413979, 
          "success": true
        }, 
        "success": 1
      }, 
      "refs": {
        "download": "http://10.0.0.33/downloads/files/local/Baby_Yoda_v2.2.gcode", 
        "resource": "http://10.0.0.33/api/files/local/Baby_Yoda_v2.2.gcode"
      }, 
      "size": 16991093, 
      "statistics": {
        "averagePrintTime": {
          "_default": 15103.536770413979
        }, 
        "lastPrintTime": {
          "_default": 15103.536770413979
        }
      }, 
      "type": "machinecode", 
      "typePath": [
        "machinecode", 
        "gcode"
      ]
    }, 
    {
      "date": 1578353346, 
      "display": "Metal Rack Bracket.gcode", 
      "gcodeAnalysis": {
        "dimensions": {
          "depth": 60.21600000000001, 
          "height": 10.0, 
          "width": 35.70100000000001
        }, 
        "estimatedPrintTime": 1081.7857074683004, 
        "filament": {
          "tool0": {
            "length": 727.6129000000262, 
            "volume": 0.0
          }
        }, 
        "printingArea": {
          "maxX": 119.352, 
          "maxY": 131.108, 
          "maxZ": 10.18, 
          "minX": 83.651, 
          "minY": 70.892, 
          "minZ": 0.18
        }
      }, 
      "hash": "549bad7aa2d9915ccc35ce3429e2d717bb047ca0", 
      "name": "Metal_Rack_Bracket.gcode", 
      "origin": "local", 
      "path": "Metal_Rack_Bracket.gcode", 
      "prints": {
        "failure": 1, 
        "last": {
          "date": 1579747214.75577, 
          "success": false
        }, 
        "success": 2
<TRUNCATED>

The problem I’m having is how to pull out all the name fields (the files ending in .gcode) and pull that into an input_select. At that point I should be able to create a button that sends a REST command back to the printer to print the file that is currently selected. Its just populating the input_select inside of Hass that I can’t seem to wrap my head around. Not sure how to parse that JSON with just the names.

1 Like

I’m not sure it’s feasible without some external (python) script or other wizardry.
I can get the number of files and each file individually, I can’t use them to populate an array (needed to set an input_select)
Here is what I have in case it helps someone else figure out the last bit
Assuming your REST sensor gives you the above JSON as value and is called sensor.octopi, you can get the number of files with something like (untested):

{% set octopi = states("sensor.octopi")|from_json %}
Number of files: {{ octopi.files | length }}

You could then do a loop to retrieve each file with something like (untested):

{% for i in range(octopi.files | length) %}
  path: {{ octopi.files[i].path }}
{% endfor %}

but like I said I don’t know of a way to save the output in an array like ['file1', 'file2', 'file3'] … which would be needed to set your input_select:

      - service: input_select.set_options
        data:
          entity_id: input_select.file_selector
          options: ["file1", "file2", "file3"]

Maybe save the output of the for loop to a file and then use that file as an input, but it’s starting to get convoluted. I would probably look at a python script if I had to do this myself…

Good luck and hope this gives you some inspiration

Thanks for the great info! I’ve arrived to the same spot you are at, and that is getting the values from the loop and into an array to be populated in the input_select. I’ve been messing with the template editor in HASS. I feel like this part is the most complex aspect.

I haven’t made the sensor yet that pulls the JSON data. I’m working on that currently.

Quite some time ago I was looking at a different lisible that required the exact same solution : building a dynamic input select. And I have up as it didn’t look feasible / it looked like a limitation of jinja2…

I’ve still been working on this, but haven’t made much progress. I’m about to give up myself. Only thing I know to do would be to always name an STL with the same name, put it in the root of Octopi and have a button in Hass that calls a rest command to always print that file. Not ideal.

I was able to do this using the following action in an automation:

service: input_select.set_options
data_template:
  entity_id: input_select.outdoor_playlists
  options: >-
    [{%- for item in states("sensor.fpp3_playlists")|from_json %} "{{ item }}"{%
    if not loop.last %}, {% endif %} {%- endfor %}]

for reference the sensor.fpp3_playlists contains the following text ( which is populated from a REST call):

["Halloween","Halloween_Scary","Poltergeist","Pumpkins","Remote Falcon Play","RemoteFalcon","Siren","Siren_- Come Hither","TuneP10 - Effect","Zombie"]