• ...
  • Yocto
  • production
  • project creation
  • SDK extension
  • SimpleSwitch
  • packages
  • images

Dynamically configure SimpleSwitch™ packages#

You can dynamically configure your SimpleSwitch™ packages through our SimpleSwitch™-launcher by setting

SIMPLESWITCH_CONFIGURE = "1"

inside the recipe using

inherit simpleswitch-package

this will incorporate simpleswitch-configure to wrap your application startup with a dynamically generated command line, extracted from a Json Schema and a persistent configuration file.

Providing default configuration and schema#

You will need to provide two files:

  • a json schema as json file

  • a configuration as a json file, matching the provided schema

both of them need to be installed into the SimpleSwitch™ package.

Current level of support of Json Schema

We currently support a subset of Draft-4 <https://json-schema.org/specification-links#draft-4> and higher versions of the Json Schema standard.

But without the following elements

an example could look like this

{
   "$schema": "http://json-schema.org/draft-04/schema#",
   "properties": {
      "environment": {
         "items": {
         "type": "string"
         },
         "title": "Environment variables",
         "description": "environment variables to set. Notation is <key>=<value>",
         "type": "array"
      },
      "options": {
         "items": {
         "type": "string"
         },
         "title": "Cog options",
         "description": "Additional parameter to pass to cog",
         "type": "array"
      },
      "url": {
         "title": "URL",
         "description": "URL to browse to",
         "type": "string"
      }
   },
   "required": [
      "url"
   ],
   "title": "Cog",
   "description": "Cog browser configuration",
   "type": "object"
}

Dynamic enum#

When using the enum element in an object, e.g.

{
   "$schema": "http://json-schema.org/draft-04/schema#",
   "type": "object"
   "properties": {
      "foo": {
         "type": "string"
         "enum": ["1", "2", "3"]
      }
   }
}

you can let simpleswitch-configure create the enum values from e.g. a list of files. For that you can use fromFolder instead of the enum values.

fromFolder(dir: list[str], pattern: str = '*', wo_extension: bool = False, fullpath: bool = False, exclude: list[str] = [])

as an example, if your directory /apps/foo contains

file1
file2.txt
file3.dat
file2
anotherfile.txt

the parameter would have the following effects

parameter

description

example

result from the example

dir

Directory to scan in

[“/apps/foo]””

["file1", "file2.txt", "file3.dat", "file2", "anotherfile.txt"]

pattern

fnmatch based filter pattern

*.txt

["file2.txt", "anotherfile.txt"]

wo_extension

Return without file extension

true

["file1", "file2", "file3", "file2", "anotherfile"]

fullpath

Return the full path to the file

true

["/apps/foo/file1", "/apps/foo/file2", "/apps/foo/file3", "/apps/foo/file2", "/apps/foo/anotherfile"]

exclude

Files to exclude (after filtering)

[“anotherfile.txt”]

["file1", "file2", "file3", "file2"]

you can combine all parameter to get the result your wrapped application will accept.

As part of the schema this could look like this

{
   "$schema": "http://json-schema.org/draft-04/schema#",
   "type": "object"
   "properties": {
      "foo": {
         "type": "string"
         "enum": "fromFolder('/apps/myapp', pattern='*.json', exclude=['config.json'])"
      }
   }
}

Configuring simpleswitch-configure#

From within your SimpleSwitch™ package recipe you may need to configure, the location of the configuration, using SIMPLESWITCH_CONFIGURE_CONFIG and SIMPLESWITCH_CONFIGURE_SCHEMA

Then you will need to define the command line that will be generated by simpleswitch-configure, using SIMPLESWITCH_CONFIGURE_STARTUP.

SIMPLESWITCH_CONFIGURE_STARTUP is a Python f-string based pattern, that will be filled by simpleswitch-configure using the information found in the current validated configuration.

With an example configuration like

{
   "mylist": ["1", "2", "3"],
   "mybool": true,
   "notApplicable": false,
   "myobject": {
      "moreSettings": "foo"
   }
}

You can use any value being found in the configuration directly and in addition the following helper functions

asList(in_: Iterable, prefix: str = '', suffix: str = '', delimiter: str = ' ')

will generate a result from a list

parameter

description

example

result from the example

in_

A list or set to use

{asList(mylist)}

1 2 3

prefix

A prefix to every item

{asList(mylist, prefix=’–‘)}

--1 --2 --3

suffix

A suffix to every item

{asList(mylist, suffix=’–‘)}

1-- 2-- 3--

delimiter

Character between each element

{asList(mylist, delimiter=’,’)}

1,2,3

you can combine all parameter to get the result your wrapped application will accept.

asFile(in_: str, prefix: str = None, suffix: str = None, style: str = "json")

will generate a temporary file with the content of requested item

parameter

description

example

result from the example

in_

A list or set to use

{asFile(myobject)}

<path tp temporary filename> with the content {"moreSettings": "foo"}

prefix

A prefix to every item

{asFile(myobject, prefix=’–‘)}

--<path tp temporary filename> with the content {"moreSettings": "foo"}

suffix

A suffix to every item

{asFile(myobject, suffix=’–‘)}

<path tp temporary filename>-- with the content {"moreSettings": "foo"}

style

Type of file to create (ini/json/rhasspynlu)

{asFile(myobject, style=”ini”)}

<path tp temporary filename> with the content in ini style format

you can combine all parameter to get the result your wrapped application will accept.

ifelse(in_: object, trueval: str, falseval: str = '')

will choose one based on a condition

parameter

description

example

result from the example

in_

Condition to test

{ifelse(mybool, ‘foo’)}

foo

trueval

value if condition is met

{ifelse(notApplicable, ‘foo’)}

`` ``

falseval

value if condition is not met

{ifelse(notApplicable, ‘foo’, ‘bar’)}

bar

you can combine all parameter to get the result your wrapped application will accept.

You can even write complex expressions like

myapp {asList(mylist, prefix='--')} {ifelse(notApplicable, '/my-standard.config', asFile(myobject))}

which would with above mentioned configuration generate

myapp --1 --2 --3 /my-standard.config

Note

Variables that don’t exist in the configuration, but in the provided SIMPLESWITCH_CONFIGURE_STARTUP setting, will generate empty strings

Note

When defining the generator pattern, please be extra careful about escaping any string, as the entire line needs to be f-string compliant.

Dynamically configure other SimpleSwitch™ packages#

You can also (re-)configure other SimpleSwitch™ packages. For that you will need to place files named

  • <SimpleSwitch™ package>.minimal.json

  • or <SimpleSwitch™ package>.json

into /usr/share/simpleswitch-service-configuration inside the SimpleSwitch™ package’s file system.

simpleswitch-configure will then automatically monitor if the other SimpleSwitch™ package is present, and if the content of the file is part of the other’s current configuration. If not the other SimpleSwitch™ package is reconfigured automatically.

Model context protocol integration#

You can add a MCP server (see Introduction to MCP for more details) to integrate your demo with our LLM (large language model), to have support for interacting with a package by using a chatbot.

For that you will need to add a server application to the SimpleSwitch™ package and pass --mcpserver=<path to executable> to the simpleswitch-configure arguments.

simpleswitch-configure will then automatically start the MCP server and forward the URL of that server to any other SimpleSwitch™ package that defines a field mcpserver in their minimal configuration (see above’s section)