- SVSHI - Secure and Verified Smart Home Infrastructure
The SVSHI (Secure and Verified Smart Home Infrastructure) (pronounced like "sushi") project is a platform/runtime/toolchain for developing and running formally verified smart infrastructures, such as smart buildings, smart cities, etc.
It provides a GUI to interact easily with the platform.
It also provides a CLI, svshi
, for shell interaction.
With SVSHI, a user can develop and run Python applications interacting with KNX systems that are formally verified at both compile and run-time against a set of provided invariants.
To help you familiarize with SVSHI concepts and write your first apps, we provide a "discover service". Your start using the service by uploading your .knxproj
file. It then extracts devices and detects all the communication objects (can be seen as "sub devices" or "abtract devices") that your physical devices offer and that are compatible with SVSHI.
You can generate new apps for SVSHI that use these devices, write the code locally and update them again on the service.
Finally, you can install these apps on SVSHI, see the result of the compilation and verification processes and, if they succeeded, you can start a simulation on our KNX simulator and see the behaviour of your app(s) live.
Once you're ready for the complete SVSHI experience, you can download the app(s) you developed and run them on your own physical installation.
To run the discover service, please run these 2 scripts in that order:
./scripts/build_discover_service.sh
./scripts/run_discover_service.sh
Please note that the build process can take 10-15min, even more depending on your machine.
Once you executed the 2nd script, open your favorite web browser and go to http://localhost:3000
.
We strongly recommend to use SVSHI on Docker with the GUI, see Docker (can be used on Windows or Unix machine).
To work, SVSHI needs Python 3.9 (or newer)(download here), pip
(pip
will be automatically installed by scripts on Windows, on Linux simply use sudo apt install python3-pip
and on MacOS use python3 -m ensurepip
) and Java 11 (or newer)(download here). Optionally, sbt 1.5.5 (or newer) is needed to build from sources.
To check if the installation was successful, run svshi version
in your terminal.
SVSHI comes with a GUI in the form of a web application. For this usage, we strongly recommend to use the provided Docker image.
Here the SVSHI system and the frontend server run in the same Docker image. To use it:
- Run
cd ./scripts && ./build_docker.sh
(Windows:.ps1
) to build the image - Run
cd ./scripts && ./run_docker.sh
to run the docker container - Open a browser and navigate to
http://localhost:3000
(or replacelocalhost
by the IP of the machine running the Docker)
Do not forget to use volumes (see https://docs.docker.com/storage/volumes/) if you want your container files to be non-volatile. The scripts that we provide that run the container already create a volume and use it for the container. Feel free to modify those scripts if you are an advanced user of Docker.
You need to have npm
installed on your system!
To use the GUI:
- run
svshi gui
in a terminal to start SVSHI - run the script
start_ui.sh
in another terminal - connect to http://localhost:3000 in your favorite browser
When you want to stop, kill both processes running in terminals.
If you are running SVSHI on a smart building infrastructure, DO NOT kill
svshi gui
, it would stop running on your building installation! You can however stop thestart-ui.sh
process.
To install SVSHI on Linux or macOS:
- Download the latest version
.zip
file from the Releases page - Unzip it, move the folder to the desired installation site, then run
cd ./scripts && ./install.sh
inside it. - Add
$HOME/local/bin
(where the CLI executable is stored) to the path by addingexport PATH=$HOME/local/bin:$PATH
to your.bash_profile
,.zsh_profile
, etc. - Add the variable
SVSHI_HOME
to your environment by addingexport SVSHI_HOME=path/to/the/svshi/folder
(a path example is~/svshi-v1.1.0
) to your.bash_profile
,.zsh_profile
, etc.
To update SVSHI, you just need to do the first two steps. However, do not forget to reinstall the applications (stored in installedApps
) by moving all the installedApps
content in the new version's generated
folder and compiling.
To install SVSHI on Windows:
- Download the latest version
.zip
file from the Releases page - Unzip the archive, move the unzipped folder to the desired installation site. The moved folder must contain (among other things) a
src
folder and some scripts. - Open a Powershell instance a
CD
into the unzipped directory. - Setup
python3
by executing the script.\setup-python3.ps1
. This sets up apython3
alias if it does not exist.The command
py
,python
orpython3
must be available in your Powershell environment for this script to work! - Reboot your computer.
- Execute
.\install-pip.ps1
to install pip on your computer - Run the
.\install.ps1
script inside the unzipped folder to install the program.
IMPORTANT! use Powershell to execute the scripts!
To update SVSHI, you just need to do steps 1, 2, 3 and 7. However, do not forget to reinstall the applications (stored in installedApps
) by moving all the installedApps
content in the new version's generated
folder and compiling.
To build from sources on Linux or macOS:
- Clone the repository
- Run
cd ./scripts && ./build.sh
- Add
$HOME/local/bin
(where the CLI executable is stored) to the path by addingexport PATH=$HOME/local/bin:$PATH
to your.bash_profile
,.zsh_profile
, etc. - Add the variable
SVSHI_HOME
to your environment by addingexport SVSHI_HOME=path/to/your/cloned/repo
to your.bash_profile
,.zsh_profile
, etc.
To update SVSHI, you just need to pull the latest changes and perform step 2. However, do not forget to reinstall the applications (stored in installedApps
) by moving all the installedApps
content in the new version's generated
folder and compiling.
To build from sources on Windows:
- Clone the repository
- Open a Powershell instance and
CD
into the unzipped directory. - Setup
python3
by executing the script.\setup-python3.ps1
. This sets up apython3
alias if it does not exist.The command
py
,python
orpython3
must be available in your Powershell environment for this script to work! - Reboot your computer.
- Execute
.\install-pip.ps1
to install pip on your computer - Run the
.\install.ps1 -build $true
script inside the cloned folder to install the program.
IMPORTANT! use Powershell to execute the scripts!
To update SVSHI, you just need to pull the latest changes and perform steps 2 and 6. However, do not forget to reinstall the applications (stored in installedApps
) by moving all the installedApps
content in the new version's generated
folder and compiling.
We also provide a Docker image with all requirements and SVSHI installed. To use it:
- Run
cd ./scripts && ./build_docker.sh
to build the image - Run
cd ./scripts && ./run_docker.sh
to run the docker container. It opens ash
instance in the container with the current directory mapped to/pwd
in the container - You can find the repo copied in
/home/maki/svshi
svshi
command is accessible
You need to have npm
installed on your system!
To use the GUI:
- run
svshi gui
in a terminal to start SVSHI - run the script
start_ui.sh
in another terminal - connect to http://localhost:3000 in your favorite browser
When you want to stop, kill both processes running in terminals.
If you are running SVSHI on a smart building infrastructure, DO NOT kill
svshi gui
, it would stop running on your building installation! You can however stop thestart-ui.sh
process.
- Binary sensors (deviceType = "binarySensor")
- Temperature sensors (deviceType = "temperatureSensor")
- Humidity sensors (deviceType = "humiditySensor")
- CO2 sensors (deviceType = "co2Sensor")
- Switches (deviceType = "switch")
- Dimmer Actuator (deviceType = "dimmerActuator")
- Note that this dimmer supports single-value dimming (KNX DPT-5-1)
- Dimmer Sensor (deviceType = "dimmerSensor")
-
- Note that this dimmer supports single-value dimming (KNX DPT-5-1)
-
To develop an app for SVSHI:
- Create the devices prototypical structure file containing the list of the devices the app should use, as explained in the app prototypical structure section.
- Run the app generator, as explained in the app generator section, to get the app skeleton. It will be created under the
generated/
folder. - Write your app.
- Run
svshi
to generate the bindings withsvshi generateBindings -f ets.knxproj
, where the argument is the absolute path to the ETS project file.Note that SVSHI supports a .json file as input instead of the ets.knxproj file but this should be use only when using the simulator!
- Map the right physical ids given in
generated/physical_structure.json
to the right device ingenerated/apps_bindings.json
. This is needed to provide the devices in the Python code with the group addresses to use. The first file represents the physical structure from the ETS project file, where each communication object has an id. The second one represents the apps structure with the devices and for each of them, the links they need. - Run
svshi
again to compile and verify the app withsvshi compile -f ets.knxproj
.Note that SVSHI supports a .json file as input instead of the ets.knxproj file but this should be use only when using the simulator!
To write an app, you mainly have to modify the main.py
file, optionally adding dependencies into the requirements.txt
file provided in the generated project. To understand how the project is generated, please refer to the app generation section.
All the available device instances are already imported in main.py
. They mirror what has been defined in the device prototypical structure file.
The application can use external files. They must live in the files
folder at the root of the application folder. Calling open
directly is forbidden. One must use the functions provided by svshi_api
to access files. Files are managed by the SVSHI runtime and thus all interactions must go through svshi_api
functions. Please refer to the SVSHI built-in functions section for details about these functions.
There are two important functions in main.py
, invariant()
and iteration()
. In the first one the user should define all the conditions (or invariants) that the entire KNX system must satisfy throughout execution of all applications, while in the second she should write the app code.
An important thing to be aware of is that iteration()
cannot use external libraries directly. Instead, these calls have to be defined first inside periodic or on_trigger functions, which are functions whose name starts with periodic
, respectively on_trigger
and whose return type is explicitly stated. Then, these functions can be used in iteration()
.
In addition, note that invariant()
must return a boolean value, so any kind of boolean expression containing the read properties of the devices and constants is fine. However, here operations with side effects, external libraries calls, periodic
and on_trigger
functions calls are not allowed.
Periodic and on_trigger functions are used to empower performance and formal verification, while slightly reducing utility. They are meant to encapsulate calls to external libraries, as such calls might be slow and have higher chances to crash. They are run asynchronously, so that even if they need time to execute, they will not slow down the apps. Their content is not verified by SVSHI and they are allowed to crash, which will not impact the running apps. This is why, when you retrieve the result you should treat it as unsafe input and expect any value of the correct type, or None
(if the function has not been executed, yet).
Note that some modules are forbidden to use even in periodic and on_trigger functions. For now, the time
module is forbidden, please use the time provided by the SVSHI_API, see SVSHI built-in functions.
To execute and retrieve values of such functions, use the provided api available through the svshi_api
object: svshi_api.trigger_if_not_running
and svshi_api.get_latest_value
(more details below).
Periodic functions should have a name starting with periodic
and a period in seconds defined in the docstring like this: period: 3
(meaning a period of 3 seconds). They are not allowed to have any argument as input. Such functions are automatically executed by svshi periodically, according to the given period. A period of X seconds means that there will be X seconds between each executions' start, unless the function takes more than X seconds to execute (in that case, next execution starts immediately after the function terminates). If the provided period is 0
, the function is executed as often as possible, but not more often than every 0.5 second. Here is an example:
def periodic_function() -> int:
"""
period: 10
"""
return external_library_get_int()
On_trigger functions have a name starting with on_trigger
. They may take some arguments as input, but are not allowed to have default arguments, *args or **kwargs.
svshi_api.trigger_if_not_running(fn)(args) is used to trigger the execution of an on_trigger
function. See the example below on how it should be used.
def on_trigger_function(x: int, y: bool) -> int:
return external_library_get_int(x, y)
# Somewhere in the iteration function:
svshi_api.trigger_if_not_running(on_trigger_function)(3, True)
svshi_api.get_latest_value(fn) is used to retrieve the latest value returned by a periodic of on_trigger function. Remember that you should assume it to be any value of the correct type, or None
if the function was never executed yet. The verification will fail if any of the returned values leads to an invalid state, which is why you should sanitize the received value.
Here is an example of retrieving a value:
def on_trigger_function(x: int, y: bool) -> int:
return external_library_get_int(x, y)
# Somewhere in the iteration function:
x = svshi_api.get_latest_value(on_trigger_function)
# Since on_trigger_functions returns an int, x might be any integer value, or None
# Suppose you expect a value between -5 and 30.
if x is None or x < -5 or x > 30:
# Some default and safe behaviour.
else:
# Regular behaviour, using x.
Furthermore, applications have access to a set of variables (the app state) they can use to keep track of state between calls. Indeed, the iteration()
function is called in an event-based manner (either the KNX devices' state changes or a periodic app's timer is finished). All calls to iteration()
are independent and thus SVSHI offers a way to store some state that will live in between calls. There is a local state instance per app.
To do so, in main.py
the app_state
instance is imported along with the devices. This is a dataclass and it contains 4 fields of each of the following types: int
, float
, bool
. The fields are called respectively INT_X
, FLOAT_X
, BOOL_X
where X equals 0, 1, 2 or 3.
These values can be used in iteration()
and invariant()
. One should be careful while using it in invariant()
or in a condition that will affect the KNX installation's state (the physical state): the formal verification would fail if ANY possible value of the app_state
leads to an invalid state after running iteration()
even if this case should not occur because of previous calls to iteration()
that would have set the values.
A svshi_api
instance is imported in every app, like the app_state
.
This instance offers several functions used to track the system's time in applications:
get_hour_of_the_day
returns an integer between 0 and 23.get_minute_in_hour
returns an integer between 0 and 59.get_day_of_week
returns an integer between 1 and 7, where 1 corresponds to Monday.get_day_of_month
returns an integer between 1 and 31, corresponding to the day of the month.get_month_in_year
returns an integer between 1 and 12, where 1 corresponds to January.get_year
return the current year. Example: For Wed Apr 13 15:57:17 2022 UTCget_hour_of_the_day
returns15
,get_minute_in_hour
returns57
,get_day_of_week
returns3
,get_day_of_month
returns13
,get_month_in_year
returns4
andget_year
returns2022
. This allows to put time constraints into the invariant and to write and verify time sensitive applications . Therefore, it can be used for the code ofiteration
, ininvariant
and in pre- and post- conditions.
As seen before, the svshi_api
instance also offers a way to trigger and retrieve values of periodic and on_trigger functions (via trigger_if_not_running
and get_latest_value
).
The svshi_api
instance additionally offers functions to interact with external files:
get_file_text_mode(file_name, mode)
: open the file with the given name in the corresponding mode as a text file and return theIO[str]
instance (same as returned byopen
) orNone
if an error occured. The mode can bea
,w
,ar
orwr
get_file_binary_mode(file_name, mode)
: open the file with the given name in the corresponding mode as a binary file and return theIO[bytes]
instance (same as returned byopen
) orNone
if an error occured. The mode can bea
,w
,ar
orwr
get_file_path(file_name)
: returns the path to the file with the given filename as managed by SVSHI. This can be used to pass as arguments to some libraries. However, you must use use theget_file_...
functions to open the file directly!
To ease the verification process of time sensitive functions, a check_time_property
function is offered:
check_time_property
has three arguments : frequency
,duration
and finally the condition.
frequency
andduration
time are given insvshi_api
, already imported on themain.py
.frequency
indicates how often the property must be valid. Havingsvshi_api.Day(2)
for frequency means that the property must be true every two days.duration
states for how long the property holds. For example, ifduration
issvshi_api.Minute(10)
, the property must be always valid for 10 minutes, continuously.
Classes in svshi_api
are used to represent various time durations; Possible representations are Year
,Month
,Week
,Day
,Hour
and Minute
.
Each of these instances take one value at construction, the amount of time. Example: svshi_api.Day(5)
represent 5 days.
condition
is the proposition that needs to be valid for some time at the given frequency. WARNING: Do not use any previously declared variables or the verification will fail. For example, if you want that theswitch_one
is on every hour for ten minutes, you can write:svshi_api.check_time_property(frequency=Hour(1),duration=Minute(10),condition=switch_one.is_on()
NB: This function can only be used in theinvariant
and cannot be used initeration
.
In main.py
:
from instances import app_state, BINARY_SENSOR, SWITCH
def invariant() -> bool:
# The switch should be on when the binary sensor is on or when INT_0 == 42, off otherwise
return ((BINARY_SENSOR.is_on() or app_state.INT_0 == 42) and SWITCH.is_on()) or (not BINARY_SENSOR.is_on() and not SWITCH.is_on())
def iteration():
if BINARY_SENSOR.is_on() or app_state.INT_0 == 42:
SWITCH.on()
else:
SWITCH.off()
To run all the installed apps (with runtime verification enabled):
- In ETS, import the file
assignments/assignment.csv
to create the group addresses, then assign to each communication object the right group address as presented inassignments/assignment.txt
. The name of the group address should help understanding which device it is meant to. - In ETS, do a basic configuration of the devices to make them have the correct basic behaviour (the amount of configuration depends on the particular device)
- Execute
svshi run -a address:port
, where address is the KNX IP gateway address and port is the KNX IP gateway port.
SVSHI logs which apps have been called during execution and which telegrams have been received. You can find the logs in logs/
.
If you want to update the code of an app that is already installed, SVSHI offers a simplified process. To be updated, an app must have the same prototypical structure as its previous version and be installed.
To update the app, you then:
- Put the new version of the app in the
generated
folderThere must be NO other app in the folder
- Run
svshi updateApp -n app_name
whereapp_name
is the app you want to update
Using this process, you do not need to generate or modify the bindings and you do not need to pass an ETS project.
If the new version does not pass the verification stage, the update is aborted and the old set of apps is restored as before the operation.
This JSON file is given by the programmer/developer that wants to develop an application. It represents the prototypical devices that the app needs with their types. It also specifies whether the app is privileged or not ("permissionLevel": "privileged" | "notPrivileged"
). A privileged app overrides the behavior of the non-privileged ones at runtime.
Moreover, the timer
attribute can be used to run the application even though the physical state has not changed. The app thus becomes a periodic app.
- If
timer == 0
the application runs only when the physical state of the devices it uses changes - If
timer > 0
the application runs when the physical state changes AND everytimer
seconds.
Optionally, devices can have a "preBindingPhysId"
that represents the physicalId to which it is bound (see Bindings) if it is already known. This id is then transfered in the bindings file automatically by the compiler. This is mainly used by the SVSHI Web-service.
Once the app is generated, it is moved in the generated apps' folder.
Here is an example:
{
"permissionLevel": "notPrivileged",
"timer": 60,
"devices": [
{
"name": "name_of_the_instances",
"deviceType": "type_of_the_devices"
},
{
"name": "name_of_the_instance_2",
"deviceType": "type_of_the_device",
"preBindingPhysId": 42
}
]
}
The name
is used as the instance name in the Python app that is generated. It should then be unique in a given app, and should follow the Python variables naming conventions: no whitespaces nor numbers.
The deviceType
should be supported by SVSHI.
The app generator takes as input the devices JSON file and the name of the app.
Before executing it, you need to create the file containing the list of the devices the app should use, as explained above.
To execute the generator, run svshi generateApp -d devices.json -n app_name
, where the first argument is the absolute path to the prototypical structure file and the second one (app_name
in the example) is the name of the app to be used. The name has to follow the same rules as for Python modules: short, all-lowercase names. Underscores can be used if it improves readability.
You can run svshi --help
to display the following:
Secure and Verified Smart Home Infrastructure
task <command> The task to run. Can be passed as is. Possible options are 'run', 'compile', 'generateBindings', 'generateApp', 'removeApp', 'listApps', 'version', 'gui' and
'deviceMappings. This argument is not case sensitive.
-f --ets-file <str> The ETS project file to use for the tasks 'compile' and 'generateBindings'
-d --devices-json <str> The devices prototypical structure JSON file to use for the task 'generateApp'
-n --app-name <str> The app name to use for the tasks 'generateApp' and 'removeApp'
-a --address <str> The KNX address to use for the task 'run'. The correct format is 'address:port' (ex: 192.168.1.1:5555)
--no-colors The flag to disable output coloring
--all The flag to remove all apps for the task 'removeApp'
Available commands are:
svshi run -a 1.1.1.1:5555
to run all the apps with runtime verificationsvshi compile -f ets.knxproj
to compile all the appssvshi generateBindings -f ets.knxproj
to generate the bindings for all the appssvshi generateApp -d devices.json -n app_name
to generate a new Python appsvshi removeApp -n app_name
to remove an installed appsvshi updateApp -n app_name
to update the code of an app that is already installedsvshi listApps
to list all the installed appssvshi version
to display the CLI versionsvshi gui
to start svshi as a server for the GUIsvshi deviceMappings -f ets.knxproj
to generate a json file containing a list of the prototypical devices offered by your physical devices
Shorter aliases are also available:
svshi r
forsvshi run
svshi c
forsvshi compile
svshi gb
forsvshi generateBindings
svshi ga
forsvshi generateApp
svshi ra
forsvshi removeApp
svshi ua
forsvshi updateApp
svshi la
forsvshi listApps
svshi v
forsvshi version
To facilitate development and demo, we developed a KNX simulator that can be used with or without SVSHI.
To use it with SVSHI, to avoid having to create an ETS project, it is possible to input a .json
file when running compile
and generatedBindings
. This JSON file that represents the physical system can be easily generated using our GUI.
The compiler combines all applications already installed (in app_library
) with new applications (in generated
). It generates the bindings between physical and prototypical devices communication objects, assigns group addresses to used physical communication objects and produces useful files for the runtime.
When compiling applications, if the verification passed all checks, applications from generated
are moved into app_library
to become installed applications.
The compiler generates the bindings file to let the developer map physical device communication objects (from the ETS project) to prototypical devices from applications.
Bindings for the installed applications are stored and when svshi generateBindings -f ets.knxproj
is called, the new bindings reuse current bindings if the physical structure did not change since last application installation. Therefore, only bindings for new applications are empty and must be filled. If the physical structure changed, the bindings file is a fresh one and all bindings must be entered again.
When compiling, the apps are also verified to make sure each one of them satisfies the invariants of each app. If not, the procedure fails with helpful error messages. Therefore, the static verification not only catches apps violating the invariants, but it also ensures compatibility between installed apps.
Whenever an app wants to update the KNX system, SVSHI verifies whether the update could break the apps' invariants. If it is the case, the apps are prevented from running, otherwise the updates are propagated to KNX.
At compile time, all applications are combined to create a function representing the system's behaviour. This function combines all applications' iteration()
functions and the order is thus set at compile time. Applications that are privileged
overrides behaviour of nonPrivileged
ones if they are conflicting.
SVSHI's runtime is reactive and event-based. The system listen for changes to the group addresses of the devices it uses, and is run on a state change (an event). The state transition can be triggered externally by the KNX system or by its own behaviour, in which case the system proceeds to notify the listener again. Notable exception are apps that run every X seconds based on a timer, which not only react to state changes but are also executed periodically.
For a given set of applications, the system behaviour function is run every time the state of the devices changes and every Y seconds where Y is the minimum of all timers of all applications which are greater than 0.
Running applications concretely means that the system behaviour function is executed on the current physical state of the system and with the current app states.
This execution model has been chosen for its ease of use: users do not need to write while
loops or deal with synchronization explicitly.
The copy of the state kept by SVSHI is updated each time a telegram is sent by a device.
The SVSHI runtime also sends KNX "read" request every 60 seconds to all devices connected to SVSHI. So, for devices that support the read request, their state is updated at least every 60 seconds.
This is particularly indispensable for devices that cannot send their state on their own and rely solely on read requests.
To provide a GUI in the form of a web application, SVSHI offers a JSON API through HTTP. To start the server, run svshi gui
. It starts a server that serves requests at http://localhost:4242
.
## Device Mappings We provide a way to discover the functionality offered by your physical devices. Given your knxproj file (ETS project file), Svshi produces a json structure containing a list of protoypical devices supported by svshi for each of your physical devices.
Example of such a file:
{
"physicalStructureJson": {...},
"deviceMappings": [
{
"physicalAddress": "1.1.1",
"supportedDeviceMappingNodes": [
{
"name": "Channel - CH-0 - IP settings",
"supportedDeviceMappings": [
]
}
]
},
{
"physicalAddress": "1.1.7",
"supportedDeviceMappingNodes": [
{
"name": "Default",
"supportedDeviceMappings": [
{
"name": "Input A - Eingang A - Disable",
"supportedDeviceName": "switch",
"physicalCommObjectId": 85743129
},
{
"name": "Input A - Eingang A - Telegr. switch - Telegr. counter value 2 bytes",
"supportedDeviceName": "switch",
"physicalCommObjectId": 270662119
},
{
"name": "Input A - Eingang A - Telegr. switch - Telegr. counter value 2 bytes",
"supportedDeviceName": "binarySensor",
"physicalCommObjectId": 270662119
},
{
"name": "Input B - Eingang B - Disable",
"supportedDeviceName": "switch",
"physicalCommObjectId": -1909925948
},
{
"name": "Output B - Ausgang B - Input B - Telegr. switch - Control value (PWM)",
"supportedDeviceName": "switch",
"physicalCommObjectId": 209048516
},
{
"name": "Output B - Ausgang B - Input B - Telegr. switch - Control value (PWM)",
"supportedDeviceName": "binarySensor",
"physicalCommObjectId": 209048516
}
]
}
]
}
]
}
Except otherwise specified, requests reply with a JSON body with the following structure:
{
"status": true,
"output":
[
"first line of the output text",
"second line of the output text"
]
}
where the status
represents whether the request succeeded and output
contains the output specific to each request.
Here are the available endpoints:
-
GET
/version
Corresponds to
svshi version
of the CLI.Returns the current version of
svshi
in the first line ofoutput
. -
GET
/listApps
Corresponds to
svshi listApps
of the CLI.Replies with one app name per element in
output
-
GET
/availableProtoDevices
Does not correspond to any CLI function.
Replies with one device type per element in
output
. These are the Supported devices. -
GET
/availableDpts
Does not correspond to any CLI function.
Replies with one dpt per element in
output
. The format is "DPT-X" where X is the int of an available dpt. -
POST
/generateApp/:appName
Corresponds to the
svshi generateApp
of the CLI.The name of the new app is passed in the endpoint path. The body of the request must contain the prototypical structure as a JSON (same structure as created manually for the CLI).
-
POST
/compile
Corresponds to the
svshi compile
of the CLI.Runs the
compile
operation ofsvshi
, replying with thestatus
representing whether the compilation was successful or not and theoutput
contains the messages returned bysvshi
.The body must be a
.zip
archive containing the.knxproj
file used to compile. -
POST
/updateApp/:appName
Corresponds to the
svshi updateApp -n appName
of the CLI.Runs the
updateApp -n appName
operation ofsvshi
, replying with thestatus
representing whether the update was successful or not and theoutput
contains the messages returned bysvshi
.The body must be a
.zip
archive containing the.knxproj
file or the.json
file used to compile. -
POST
/generateBindings
Corresponds to the
svshi generateBindings
of the CLI.Runs the
generateBindings
operation ofsvshi
, replying with thestatus
representing whether the generation was successful or not and theoutput
contains the messages returned bysvshi
.The body must be a
.zip
archive containing the.knxproj
file or the.json
file used to generate the bindings. -
POST
/removeApp/:appName
Corresponds to the
svshi removeApp -n appName
of the CLI.Runs the
removeApp -n appName
operation ofsvshi
, replying with thestatus
representing whether the removal was successful or not and theoutput
contains the messages returned bysvshi
. -
POST
/removeAllApps
Corresponds to the
svshi removeApp --all
of the CLI.Runs the
removeApp --all
operation ofsvshi
, replying with thestatus
representing whether the removal was successful or not and theoutput
contains the messages returned bysvshi
. -
POST
/run/:ipPort
Corresponds to the
svshi run -a ip:port
of the CLI.Launches
svshi
run replying with thestatus = true
and theoutput
containing a fixed message that indicates that the server started.It stores all the outputs of
svshi
running in a file, to be retrieved by/runStatus
. -
GET
/runStatus
Replies with the standard body JSON with
status
representing whethersvshi
is running or not, and emptyoutput
. -
GET
/logs/run
If the log file exists (i.e., SVSHI was run or is running), it replies with the standard body JSON with status=true
and output
containing the output lines of svshi
running, truncated if the log file goes beyond a given size (e.g., 20MB).
- GET
/logs/receivedTelegrams
If the log file exists (i.e., SVSHI was run or is running), it replies with the standard body JSON with status=true
and output
containing the received telegrams log file of the latest execution, truncated if the log file goes beyond a given size (e.g., 20MB).
- GET
/logs/execution
If the log file exists (i.e., SVSHI was run or is running), it replies with the standard body JSON with status=true
and output
containing the complete execution log file of the latest execution, truncated if the log file goes beyond a given size (e.g., 20MB).
- GET
/logs/physicalState
If the physical state log file exists (i.e., SVSHI runtime part wrote it), it replies with a JSON Body containing the physical state (i.e., mapping from Group Addresses to their current value in the system). Reply with a 404 if the file does not exist.
-
POST
/stopRun
Stops the instance of
svshi
running if it was indeed running, does nothing otherwise. Replies with the standard body JSON withstatus=true
andoutput
containing a standard message. -
GET
/newApps
Replies with the standard body JSON with
status=true
andoutput
containing the names of the apps currently in thegenerated
folder (i.e., to be installed if callingcompile
). -
GET
/bindings
Replies with the bindings and physical structure currently in the
generated
folder.This endpoint replies with a different body. It is a JSON body containing the physical structure and the generated bindings in the following form:
{ "physicalStructure": {...}, "bindings": {...} }
If no bindings or physical structure json are available in generated folder, error message is sent with a 404 error code.
-
POST
/generated
Allows to add/overwrite files in the
generated
folder. The body must be a.zip
archive containing files and folders that must go intogenerated
. If a file already exists ingenerated
, it is overwritten. If a folder already exists ingenerated
it is merged (i.e., files with same names are overwritten, files that exist only in one of the two are kept).Replies with the standard body JSON with
status
representing whether the copy worked andoutput
containing errors or the names of folders and files that were added in case of success. -
GET
/generated
Replies with the
generated
folder in a.zip
archive as body. -
GET
/generated/:filename
Replies with the requested
filename
folder or file in a.zip
archive as body.If the file or directory does not exist, it replies with an empty
.zip
. -
POST
/deleteAllGenerated
Deletes the content of the
generated
folder.Replies with the standard body JSON with
status
representing whether the removal worked andoutput
containing errors or a standard message in case of success. -
POST
/deleteGenerated/:filename
Deletes the file or directory with the name
filename
in thegenerated
folder.Replies with the standard body JSON with
status
representing whether the removal worked andoutput
containing errors or a standard message in case of success.If the file or directory does not exist, it replies with a success message.
-
GET
/installedApp/:appName
Replies with the requested app folder in a
.zip
archive as body if the requested app name corresponds to an installed app, 404 error otherwise. -
GET
/allInstalledApps
Replies with the requested installedApps folder in a
.zip
archive as body if at least one app is installed, 404 error otherwise. The folder contains all installed apps and the bindings and physical structure. It can be uploaded to generated and be compiled as is. -
GET
/assignments
Replies with a
.zip
archive as body containing theassignments
folder if assignments are created, 404 error if no assignments are created. -
GET
/assignments/gaToPhysId
Replies with a json body
assignments/gaToPhysId.json
file if assignments are created, 404 error if no assignments are created. -
POST
/deviceMappings
Corresponds to the
svshi deviceMappings
of the CLI.Runs the
deviceMappings
operation ofsvshi
, replying with the json containing the mappings for the devices and the physical structure.The body must be a
.zip
archive containing the.knxproj
file or the.json
file used to get the mappings. -
POST
/physicalStructure/parse
Parse the file passed as an archive
zip
, either a.json
or a.knxproj
file. Replies with the physical structure json in the body. -
GET
/appLibrary/bindings
Replies with a json containing the bindings for the currently installed apps. Replies with a 404 if no bindings in the appLibrary (i.e., no apps are installed).
The POST endpoints functions cannot be ran in parallel. These endpoints then acquire a "lock" and reply with a 423 error code if the lock is already aquired by another endpoint currently running.
You do not necessarily need to build a KNX infrastructure to test your app. You can use KNX Virtual to run SVSHI. This a Windows-only program that is available on the KNX Association's website1. Once you downloaded and installed it, you can use it exactly as a physical installation with SVSHI. Use the startup settings of KNX Virtual (address and port) when executing svshi run
. Default values are 127.0.0.1:3671
.
Please be careful and use the right devices inside ETS when configuring the project and refer to the KNX Help for KNX Virtual related issues2.
See the contributing guide for detailed instructions on how to get started with the project.
See the white paper and the reports for an in-depth understanding about why SVSHI exists, what it does and how it does it.
SVSHI is licensed under the MIT license.
Logo: Copyright @norafisler