Get Started

To get started with the SvanLINK application, follow these steps:

Linux

  1. Download the zip file containing the application.
  2. Unpack the zip file:
  3. unzip svanlink_os_osType.zip
  4. Navigate to the unpacked directory:
  5. cd svanlink
  6. Make the binaries executable:
  7. chmod +x svanlink
    chmod +x restart
    
  8. Run the application:
  9. sudo ./svanlink

Windows

Run the installation file and follow the instructions.

The API requests by default are sent to local address on TCP port 8000.

In browser under the local address on port 80 (default http port) should be available UI of the app. For example: http://localhost

Mac OS

Run the installation file and follow the instructions.

The API requests by default are sent to local address on TCP port 8000.

In browser under the local address on port 3000 (default http port) should be available UI of the app. For example: http://localhost:3000

Authentication

Overview

SvanLINK API uses token-based authentication to secure access to all endpoints. Authentication is required for all API requests except for the initial login request.

Authentication Flow

  1. Login: Send a login request with your password to obtain an authentication token.
  2. Token Usage: Include the token in all subsequent API requests using the token parameter.
  3. Logout: Use the logout request to invalidate the token when you're done.

Token Lifecycle

Security Considerations

Error Handling

When authentication fails, the API will return an error response:

{
  "Request": "endpointName",
  "Status": "error",
  "StatusMessage": "Invalid token"
}

WebSocket Authentication

For WebSocket connections, authentication can be performed in two ways:

  1. Login Request: Send a login request as the first message after establishing the WebSocket connection.
  2. Token Only: Send just the token string (without wrapping it in a request object) if you already have a valid token.

Example Authentication Flow

// 1. Login to obtain token
{
  "Request": "login",
  "Params": {
    "password": "your_password"
  }
}

// 2. Use token in subsequent requests
{
  "Request": "getStatus",
  "token": "your_token_here"
}

// 3. Logout when done
{
  "Request": "logout",
  "token": "your_token_here"
 }

General Error Handling

Overview

All SvanLINK API endpoints follow a consistent error response format. Understanding these error patterns will help you handle errors gracefully in your applications.

Standard Error Response Format

When an error occurs, the API returns a JSON response with the following structure:

{
  "Request": "endpointName",
  "Status": "error",
  "StatusMessage": "Description of the error"
}

Error Response Fields

Common Error Types

General Error Example

For unhandled or unexpected errors, the API returns a generic error message:

{
  "Request": "endpointName",
  "Status": "error",
  "StatusMessage": "An unhandled error occurred during execution. Please try again!"
}

Error Handling Best Practices

HTTP Status Codes

In addition to the JSON error response, the API may also return appropriate HTTP status codes:

WebSocket Configuration

Description:

This configuration is used to set up WebSocket communication. The configuration specifies the intervals at which different types of data are sent automatically. The settings are saved, and on reconnection, SvanLINK will continue to send results according to the configured intervals. The maximum number of simultaneous connections is 20 clients.

The configuration must be sent via WebSocket connection. Default port is 8001

From version 1.1.0 was introduced such a concept as channels. Channel represents under a name a request (or set of requests) which will be preconfigured and sent automatically according to configured intervals. This allows to listen to different sets of requests by different clients.

Authentication:

When the WebSocket connection is opened, the first step is to authenticate. This can be done by sending a login request or by sending only the token (as a string) which was generated previously.

Request Format:

Request Body:

To configure the broadcast of data the SvanLINK will accept a list of "Requests". Each item in the list contains a desired type of request (the requests are described below in the documentation) and an interval (ms) at which the data must be sent.

{
  "Channel": "main",  //Optional, default is "main"
  "Requests": [
    {
      "Request": "getResults",
      "Interval": 1000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
      "startSync": 1       // Optional: align first emission to next multiple of N seconds (default: 1).
    },
    {
      "Request": "getSpectrumResults",
      "Interval": 5000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
      "startSync": 60      // Optional: start on the next whole minute boundary.
    }
  ]
}

Success Response:

The response indicates that the configuration has been successfully applied, and data will be sent automatically according to the configured intervals.

Response Format:

{
  "Channel": "main",
  "Status": "ok",
  "Response": {
    "message": "Configuration applied successfully"
  }
}

Channel Management Workflow:

  1. Use getChannelList to see all available channels
  2. Use subscribeChannel to subscribe to a channel
  3. Use deleteChannel to remove unwanted channels
  4. Recreate channels by sending WebSocket configuration messages

Securing the connection (optional)

Description:

To secure the connection between the client and the SvanLINK application, you can configure SSL certificates. This will enable encrypted communication, ensuring that data transmitted between the client and the server is secure.

Configuration Steps:

  1. Obtain SSL certificates:
    • You need two files: cert.pem (the certificate) and key.pem (the private key).
  2. Place the certificate and key files in the certificates folder within the SvanLINK application directory:
    mv path/to/cert.pem certificates/
    mv path/to/key.pem certificates/
    
  3. On startup, SvanLINK will automatically detect the presence of these files and switch on encryption for communication.

Verification:

Once the certificates are in place, restart the SvanLINK application. You should see a log message indicating that the WebSocket server is starting with SSL:

"Starting UI with SSL" or
"Starting TCP server with SSL" or
"Starting WebSocket server with SSL"

If the certificates are not found, the WebSocket server will start without SSL:

"Starting UI without SSL" or
"Starting TCP server without SSL" or
"Starting WebSocket server without SSL"

MQTT Configuration

Description:

MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for IoT (Internet of Things) applications. SvanLINK supports MQTT to enable automatic publishing of measurement data, device status, and other information to an MQTT broker, allowing integration with external systems, dashboards, and data processing platforms.

How MQTT Works in SvanLINK:

SvanLINK acts as an MQTT client that connects to an MQTT broker. Once configured, SvanLINK can automatically publish data to the broker at specified intervals. The system uses a topic-based configuration similar to WebSocket channels, where each topic represents a set of requests that are published periodically.

Key Concepts:

Configuration Workflow:

  1. Configure MQTT Broker: Use setMqttConfig to set up the broker connection (host, port, username, password, SSL certificate if needed).
  2. Verify Configuration: Use getMqttConfig to retrieve and verify the current broker settings.
  3. Create Topics: Use addMqttTopic to configure which data requests should be published and at what intervals.
  4. Manage Topics: Use getMqttTopicList to view all configured topics, and deleteMqttTopic to remove unwanted topics.

Available MQTT API Requests:

The following API endpoints are available for configuring and managing MQTT functionality:

Supported Request Types:

The following request types can be configured for automatic MQTT publishing:

Message Format:

When data is published to the MQTT broker, each message includes:

Security Considerations:

Notes:

Code Examples


// JavaScript
async function makeRequest() {
  try {
    // Create the payload
    const payload = {
      Request: "getResults",
      Params: {
        results: ["LAeq", "LCeq"],
        devices: ["123456", "654235"],
        average: "true"
      },
      token: "userToken"
    };

    // Send the POST request
    const response = await fetch('http://localhost:8000/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

    // Check if response is OK
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    // Parse and print the JSON response
    const data = await response.json();
    console.log(JSON.stringify(data, null, 2));
  } catch (error) {
    console.error('Error:', error.message);
  }
}

// Execute the request
makeRequest();
  

# Python
import requests
import json

def make_request():
  try:
    # Create the payload
    payload = {
      "Request": "getResults",
      "Params": {
        "results": ["LAeq", "LCeq"],
        "devices": ["123456", "654235"],
        "average": "true"
      },
      "token": "userToken"
    }

    # Send the POST request
    url = "http://localhost:8000/"
    response = requests.post(url, json=payload)

    # Check if response is OK
    response.raise_for_status()

    # Parse and print the JSON response
    print(json.dumps(response.json(), indent=2))
  except requests.exceptions.RequestException as e:
    print(f"Error: {e}")

# Execute the request
make_request()
  

# cURL
curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/json" \
  -d '{
    "Request": "getResults",
    "Params": {
      "results": ["LAeq", "LCeq"],
      "devices": ["123456", "654235"],
      "average": "true"
    },
    "token": "userToken"
  }'
  

//Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;

public class HttpPostExample {
  public static void main(String[] args) {
    try {
      // Create the JSON payload
      JsonObject payload = new JsonObject();
      payload.addProperty("Request", "getResults");

      JsonObject params = new JsonObject();
      JsonArray results = new JsonArray();
      results.add("LAeq");
      results.add("LCeq");
      params.add("results", results);

      JsonArray devices = new JsonArray();
      devices.add("123456");
      devices.add("654235");
      params.add("devices", devices);

      params.addProperty("average", "true");
      payload.add("Params", params);
      payload.addProperty("token", "userToken");

      // Convert payload to string
      Gson gson = new Gson();
      String jsonPayload = gson.toJson(payload);

      // Create HTTP client
      HttpClient client = HttpClient.newHttpClient();

      // Build the HTTP request
      HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("http://localhost:8000/"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
        .build();

      // Send the request and get the response
      HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

      // Parse and print the JSON response
      JsonObject responseJson = gson.fromJson(response.body(), JsonObject.class);
      System.out.println(gson.toJson(responseJson));

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
  

// Go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

func main() {
	// Define the payload structure
	type Params struct {
		Results  []string `json:"results"`
		Devices  []int    `json:"devices"`
		Average  string   `json:"average"`
	}

	type Payload struct {
		Request string  `json:"Request"`
		Params  Params  `json:"Params"`
		Token   string  `json:"token"`
	}

	// Create the payload
	payload := Payload{
		Request: "getResults",
		Params: Params{
			Results:  []string{"LAeq", "LCeq"},
			Devices:  []string{"123456", "654235"},
			Average:  "true",
		},
		Token: "userToken",
	}

	// Marshal the payload to JSON
	jsonData, err := json.Marshal(payload)
	if err != nil {
		fmt.Println("Error marshaling JSON:", err)
		return
	}

	// Create the HTTP request
	url := "http://localhost:8000/"
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		fmt.Println("Error creating request:", err)
		return
	}
	req.Header.Set("Content-Type", "application/json")

	// Send the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error sending request:", err)
		return
	}
	defer resp.Body.Close()

	// Read and parse the response
	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		fmt.Println("Error decoding response:", err)
		return
	}

	// Pretty print the JSON response
	resultJSON, err := json.MarshalIndent(result, "", "  ")
	if err != nil {
		fmt.Println("Error formatting response:", err)
		return
	}
	fmt.Println(string(resultJSON))
}
  

API Documentation - SvanLINK v{{ version }}

login

Description:

This configuration is used to set up WebSocket communication. The configuration specifies the intervals at which different types of data are sent automatically. The settings are saved, and on reconnection, SvanLINK will continue to send results according to the configured intervals. The maximum number of simultaneous connections is 20 clients.

The configuration must be sent via WebSocket connection. Default port is 8001

From version 1.1.0 was introduced such a concept as channels. Channel represents under a name a request (or set of requests) which will be preconfigured and sent automatically according to configured intervals. This allows to listen to different sets of requests by different clients.

Authentication:

When the WebSocket connection is opened, the first step is to authenticate. This can be done by sending a login request or by sending only the token (as a string) which was generated previously.

Request Format:

Request Body:

To configure the broadcast of data the SvanLINK will accept a list of "Requests". Each item in the list contains a desired type of request (the requests are described below in the documentation) and an interval (ms) at which the data must be sent.

{
  "Channel": "main",  //Optional, default is "main"
  "Requests": [
    {
      "Request": "getResults",
      "Interval": 1000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
      "startSync": 1       // Optional: align first emission to next multiple of N seconds (default: 1).
    },
    {
      "Request": "getSpectrumResults",
      "Interval": 5000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
      "startSync": 60      // Optional: start on the next whole minute boundary.
    }
  ]
}

Success Response:

The response indicates that the configuration has been successfully applied, and data will be sent automatically according to the configured intervals.

Response Format:

{
  "Channel": "main",
  "Status": "ok",
  "Response": {
    "message": "Configuration applied successfully"
  }
}

Channel Management Workflow:

  1. Use getChannelList to see all available channels
  2. Use subscribeChannel to subscribe to a channel
  3. Use deleteChannel to remove unwanted channels
  4. Recreate channels by sending WebSocket configuration messages

Securing the connection (optional)

Description:

To secure the connection between the client and the SvanLINK application, you can configure SSL certificates. This will enable encrypted communication, ensuring that data transmitted between the client and the server is secure.

Configuration Steps:

  1. Obtain SSL certificates:
    • You need two files: cert.pem (the certificate) and key.pem (the private key).
  2. Place the certificate and key files in the certificates folder within the SvanLINK application directory:
    mv path/to/cert.pem certificates/
    mv path/to/key.pem certificates/
    
  3. On startup, SvanLINK will automatically detect the presence of these files and switch on encryption for communication.

Verification:

Once the certificates are in place, restart the SvanLINK application. You should see a log message indicating that the WebSocket server is starting with SSL:

"Starting UI with SSL" or
"Starting TCP server with SSL" or
"Starting WebSocket server with SSL"

If the certificates are not found, the WebSocket server will start without SSL:

"Starting UI without SSL" or
"Starting TCP server without SSL" or
"Starting WebSocket server without SSL"

MQTT Configuration

Description:

MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for IoT (Internet of Things) applications. SvanLINK supports MQTT to enable automatic publishing of measurement data, device status, and other information to an MQTT broker, allowing integration with external systems, dashboards, and data processing platforms.

How MQTT Works in SvanLINK:

SvanLINK acts as an MQTT client that connects to an MQTT broker. Once configured, SvanLINK can automatically publish data to the broker at specified intervals. The system uses a topic-based configuration similar to WebSocket channels, where each topic represents a set of requests that are published periodically.

Key Concepts:

Configuration Workflow:

  1. Configure MQTT Broker: Use setMqttConfig to set up the broker connection (host, port, username, password, SSL certificate if needed).
  2. Verify Configuration: Use getMqttConfig to retrieve and verify the current broker settings.
  3. Create Topics: Use addMqttTopic to configure which data requests should be published and at what intervals.
  4. Manage Topics: Use getMqttTopicList to view all configured topics, and deleteMqttTopic to remove unwanted topics.

Available MQTT API Requests:

The following API endpoints are available for configuring and managing MQTT functionality:

Supported Request Types:

The following request types can be configured for automatic MQTT publishing:

Message Format:

When data is published to the MQTT broker, each message includes:

Security Considerations:

Notes:

login

Description:

The login API is used to authenticate a user by providing a password. If the password is correct, the user is granted access to the system and receives a token.

Request Format:

Request Body:

{
  "Request": "login",
  "Params": {
    "password": "Svantek312"
  }
}

Success Response:

If the password is correct, the response will indicate a successful login and provide a token.

Response Format:

{
  "Request": "login",
  "Status": "ok",
  "Response": {
    "token": "userToken",
    "message": "Login successful"
  }
}

Error Response:

If the password is incorrect, the response will indicate an error.

Response Format:

{
  "Request": "login",
  "Status": "error",
  "StatusMessage": "Wrong password"
}

Note. It is highly recommended to change it to keep your data and settings safe. Use setNewPassword request to do this.

logout

Description:

The logout API is used to log out a user by invalidating the provided token. This will end the user's session.

Request Format:

Request Body:

{
  "Request": "logout",
  "token": "userToken"
}

Success Response:

If the token is valid, the response will indicate a successful logout.

Response Format:

{
  "Request": "logout",
  "Status": "ok",
  "Response": {
    "message": "Logout successful"
  }
}

Error Response:

If the token is invalid, the response will indicate an error.

Response Format:

{
  "Request": "logout",
  "Status": "error",
  "StatusMessage": "Invalid token"
}

setNewPassword

Description:

The setNewPassword API allows an authenticated user to change their password. The user must provide their current password and enter the new password twice for confirmation. The new password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter.

Request Format:

Request Body:

{
  "Request": "setNewPassword",
  "Params": {
    "oldPassword": "currentPassword",      // The current password.
    "newPassword": "newPassword",       // The new password.
    "newPassword2": "newPassword"       // Repeat of the new password for confirmation.
  },
  "token": "userToken"
}

Success Response:

If the password is changed successfully, the response will indicate success.

Response Format:

{
  "Request": "setNewPassword",
  "Status": "ok",
  "Response": {
    "message": "Password changed successfully"
  }
}

Error Responses:

If the request fails, an error response is returned.

Incorrect Password:

{
  "Request": "setNewPassword",
  "Status": "error",
  "StatusMessage": "Incorrect password"
}

Note. To reset the password to default it is needed to remove the password file with the same name.

On Linux systems it is located in the SvanLINK's folder.

On Windows it is located in C:\Users\YourUserName\AppData\Local\Svantek\SvanLINK\

licenseStatus

Description:

The licenseStatus API retrieves the current license status of the device. The response includes the status of the license, the license end date, the device ID, and a message regarding the license status.

Request Format:

Request Body:

{
  "Request": "licenseStatus",
  "token": "userToken"
}

Success Response:

The response contains the current license status of the device.

Response Format:

{
  "Request": "licenseStatus",
  "Status": "ok",
  "Response": {
    "licenseStatus": "active",
    "deviceId": "XXXXXXXXXXXXXXXX",
    "licenseMessage": "The license is active"
  }
}

setLicense

Description:

The setLicense API activates a new license key for the device. You can provide the license key encoded in a Base64 string, and the API will activate it for the device.

Important note. There are 2 types of licenses: hardware and device. "Hardware licence" attaches the app to the current hardware configuration (PC, laptop, server, Raspberry Pi etc) on which the app is running. The "device license" is attached to Svantek device.

Request Format:

Request Body:

{
  "Request": "setLicense",
  "Params": {
    "key": "License key file encoded in Base64" // License key encoded in Base64
  },
  "token": "userToken"
}

Success Response:

The response indicates whether the license key was successfully activated for the device.

Response Format:

{
  "Request": "setLicense",
  "Status": "ok",
  "Response": {
    "licenseStatus": "active",
    "deviceId": "1424422045401",
    "licenseMessage": "The license was activated successfully"
  }
}

getStatus

Description:

The getStatus API retrieves the status of specified devices. You can request specific device serial numbers, and the API will return the corresponding status data in the response.

Request Format:

Request Body:

{
  "Request": "getStatus",
  "Params": {
    "devices": ["113200", "223200"] // Optional: List of device serial numbers.
  },
  "token": "userToken"
}

Success Response:

The response contains the status data for each requested device.

Response Format:

{
  "Request": "getStatus",
  "Status": "ok",
  "Response": [
    {
      "serial": "113200",
      "type": "SV 303",
      "deviceName": "Demo_1",
      "firmware": "1.03.9",
      "battery": 90,
      "memorySize": 8.2,
      "memoryFree": 30,
      "measurementStatus": "start",
      "measurementType": "1/3 Octave",
      "intPeriod": 30,
      "svannet": false,
      "status": "ok"
    },
    {
      "serial": "223200",
      "type": "SV 303",
      "deviceName": "Demo_2",
      "firmware": "1.03.7",
      "battery": 33,
      "memorySize": 32.0,
      "memoryFree": 54,
      "measurementStatus": "stop",
      "measurementType": "1/1 Octave",
      "intPeriod": 0,
      "svannet": false,
      "status": "ok"
    }
  ]
}

Response Fields:

Device Object:

Notes:

getResults

Description:

The getResults API retrieves measurement results for specified devices. You can request specific result types and device serial numbers, and the API will return the corresponding data in the response.

Request Format:

Request Body:

{
  "Request": "getResults",
  "Params": {
    "results": ["LAeq", "LCeq"],      // Optional: List of result types to fetch.
    "devices": ["123456", "654235"],      // Optional: List of device serial numbers.
    "average": "true",                // Required: Whether to return averaged results.
    "vibrationsDB": false             // Optional: Whether to show vibrations in dB instead of mm/s or m/s².
  },
  "token": "userToken"
}

Success Response:

The response contains the requested measurement data for each device.

Response Format:

{
  "Request": "getResults",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "type": "SV 303",
      "status": "ok",
      "measurement": "start",
      "measurementMode": "sound",
      "results": [
        {
          "name": "LAeq",
          "value": 100.0,
          "unit": "dB"
        },
        {
          "name": "LCeq",
          "value": 112.1,
          "unit": "dB"
        }
      ]
    },
    {
      "serial": "654235",
      "type": "SV 303",
      "status": "ok",
      "measurement": "start",
      "measurementMode": "sound",
      "results": [
        {
          "name": "LAeq",
          "value": 98.2,
          "unit": "dB"
        },
        {
          "name": "LCeq",
          "value": 88.8,
          "unit": "dB"
        }
      ]
    }
  ]
}

Response Fields:

Device Object:

Error Responses:

Missing Parameters:

{
  "Request": "getResults",
  "Status": "error",
  "Error": "Missing required parameters"
}

Invalid Parameter Format:

{
  "Request": "getResults",
  "Status": "error",
  "Error": "Invalid parameter format"
}

Notes:

getSpectrumResults

Description:

The getSpectrumResults API retrieves spectrum results for specified devices. You can request specific spectrum types and device serial numbers, and the API will return the corresponding data in the response.

Request Format:

Request Body:

{
  "Request": "getSpectrumResults",
  "Params": {
    "devices": ["123456", "654235"],             // Optional: List of device serial numbers.
    "vibrationsDB": false                    // Optional: Whether to show vibrations in dB instead of mm/s or m/s².
  },
  "token": "userToken"
}

Success Response:

The response contains the requested spectrum data for each device.

Response Format:

{
  "Request": "getSpectrumResults",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "type": "SV 303",
      "status": "ok",
      "measurement": "start",
      "resultLabel": "LZeq",
      "resultType": "1/1 Octave",
      "measurementMode": "sound",
      "results": [
        {name: "31.5", value: 59.55, unit: "dB"}
        {name: "63", value: 47.22, unit: "dB"}
        {name: "125", value: 41.01, unit: "dB"}
        {name: "250", value: 41.21, unit: "dB"}
        {name: "500", value: 38.36, unit: "dB"}
        {name: "1.0k", value: 38.69, unit: "dB"}
        {name: "2.0k", value: 40.36, unit: "dB"}
        {name: "4.0k", value: 35.02, unit: "dB"}
        {name: "8.0k", value: 30.13, unit: "dB"} 
        {name: "16k", value: 32.06, unit: "dB"} 
        {name: "A", value: 44.92, unit: "dB"}
        {name: "C", value: 61.96, unit: "dB"}
        {name: "Z", value: 72.56, unit: "dB"}
      ]
    },
    {
      "serial": "654235",
      "type": "SV 303",
      "status": "ok",
      "measurement": "start",
      "resultLabel": "LZeq",
      "resultType": "1/1 Octave",
      "measurementMode": "sound",
      "results": [
        {name: "31.5", value: 60.11, unit: "dB"}
        {name: "63", value: 44.22, unit: "dB"}
        {name: "125", value: 32.01, unit: "dB"}
        {name: "250", value: 41.23, unit: "dB"}
        {name: "500", value: 38.54, unit: "dB"}
        {name: "1.0k", value: 38.69, unit: "dB"}
        {name: "2.0k", value: 40.36, unit: "dB"}
        {name: "4.0k", value: 35.34, unit: "dB"}
        {name: "8.0k", value: 35.13, unit: "dB"} 
        {name: "16k", value: 32.23, unit: "dB"} 
        {name: "A", value: 44.92, unit: "dB"}
        {name: "C", value: 61.96, unit: "dB"}
        {name: "Z", value: 66.56, unit: "dB"}
      ]
    }
  ]
}

Response Fields:

Device Object:

Error Responses:

Missing Parameters:

{
  "Request": "getSpectrumResults",
  "Status": "error",
  "Error": "Missing required parameters"
}

Invalid Parameter Format:

{
  "Request": "getSpectrumResults",
  "Status": "error",
  "Error": "Invalid parameter format"
}

Notes:

getResultsHistory

Description:

The getResultsHistory API retrieves historical measurement results (time history) for specified devices. Unlike getResults which returns the current snapshot, this API returns time-series data for each result type over a configurable period.

Request Format:

Request Body:

{
  "Request": "getResultsHistory",
  "Params": {
    "period": 3600,
    "average": false,
    "results": ["Lp", "Leq", "Lmax"],
    "devices": ["123456", "654235"],
    "vibrationsDB": false
  },
  "token": "userToken"
}

Success Response:

The response contains time-series data for each device. Each result type has a values array with one value per second (oldest first).

Response Format:

{
  "Request": "getResultsHistory",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "type": "SV 104",
      "status": "ok",
      "timestamp": 1739368245000,
      "results": [
        {
          "name": "Lp",
          "values": [65.2, 64.8, 65.1, 67.6, 66.0],
          "unit": "dB"
        },
        {
          "name": "Leq",
          "values": [65.0, 64.9, 65.1, 67.7, 65.5],
          "unit": "dB"
        }
      ]
    }
  ]
}

Response Fields:

Device Object:

Notes:

getSpectrumHistory

Description:

The getSpectrumHistory API retrieves historical spectrum results (time history) for specified devices. Unlike getSpectrumResults which returns the current snapshot, this API returns time-series data for each frequency band over a configurable period.

Request Format:

Request Body:

{
  "Request": "getSpectrumHistory",
  "Params": {
    "period": 3600,
    "devices": ["123456", "654235"],
    "results": ["8.0", "10.0", "[X] 8.0"],
    "vibrationsDB": false
  },
  "token": "userToken"
}

Success Response:

The response contains time-series spectrum data for each device. Each frequency band has a values array with one value per second.

Response Format (sound spectrum):

{
  "Request": "getSpectrumHistory",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "type": "SV 104",
      "status": "ok",
      "timestamp": 1739368245000,
      "results": [
        {
          "name": "8.0",
          "values": [45.2, 44.8, 45.1, 45.4, 46.0],
          "unit": "dB"
        },
        {
          "name": "10.0",
          "values": [42.1, 41.9, 42.3, 45.5, 43.0],
          "unit": "dB"
        }
      ]
    }
  ]
}

Response Format (vibration spectrum):

When the device is a vibration meter (e.g. SV 803/804/979) and the caller does not filter by axis, each sample of values is a 3-element array [X, Y, Z]. Any element may be null.

{
  "Request": "getSpectrumHistory",
  "Status": "ok",
  "Response": [
    {
      "serial": "92093",
      "type": "SV 979",
      "status": "ok",
      "timestamp": 1739368245000,
      "results": [
        {
          "name": "8.0",
          "values": [
            [0.123, 0.115, 0.098],
            [0.118, 0.121, 0.101],
            null,
            [0.124, 0.119, 0.103]
          ],
          "unit": "mm/s"
        }
      ]
    }
  ]
}

If the caller filters by axis ("results": ["[X] 8.0"]), the corresponding entry becomes a scalar series:

{
  "name": "[X] 8.0",
  "values": [0.123, 0.118, null, 0.124],
  "unit": "mm/s"
}

Response Fields:

Device Object:

Notes:

startMeasurement

Description:

The startMeasurement API starts measurements for specified devices. You can request specific measurement types and device serial numbers, and the API will start the corresponding measurements.

Request Format:

Request Body:

{
  "Request": "startMeasurement",
  "Params": {
    "devices": ["123456", "654235"]           // Optional: List of device serial numbers.
  },
  "token": "userToken"
}

Success Response:

The response confirms that the requested measurements have been started for each device.

Response Format:

{
  "Request": "startMeasurement",
  "Status": "ok"
}

Response Fields:

Notes:

stopMeasurement

Description:

The stopMeasurement API stops measurements for specified devices. You can request specific measurement types and device serial numbers, and the API will stop the corresponding measurements.

Request Format:

Request Body:

{
  "Request": "stopMeasurement",
  "Params": {
    "devices": ["123456", "654235"]           // Optional: List of device serial numbers.
  },
  "token": "userToken"
}

Success Response:

The response confirms that the requested measurements have been stopped for each device.

Response Format:

{
  "Request": "stopMeasurement",
  "Status": "ok",
}

Response Fields:

Notes:

getConfig

Description:

Returns the full current SvanLINK configuration, including all application and UI settings.

Request Format:

Request Body:

{
  "Request": "getConfig",
  "token": "userToken"
}

Success Response:

Response Format:

{
  "Request": "getConfig",
  "Status": "ok",
  "Response": {
    "app": {
      "tcpPort": 8000,
      "echo": true,
      "wsEnabled": true,
      "wsPort": 8001,
      "svannet": true,
      "activeUI": true,
      "disabledExternalLogin": false,
      "deviceTcpServer": true,
      "deviceTcpPort": 8888,
      "autoDownload": {
        "enabled": false,
        "path": "/path/to/afd",
        "deleteAfterDownload": false,
        "filters": {
          "fileTypes": [],
          "devices": [],
          "startDate": ""
        },
        "storageClearing": {
          "storage": { "value": 10, "unit": "gb", "enabled": false },
          "date":    { "value": 365, "unit": "days", "enabled": false }
        }
      },
      "mqtt": {
        "enabled": true,
        "host": "",
        "port": 1883,
        "username": "",
        "ssl": false
      }
    },
    "ui": {
      "liveView": {
        "resultTypes": "LAF;LAeq;LCpeak"
      },
      "thresholdView": {
        "thresholdOrange": 45,
        "thresholdRed": 75,
        "k": 0,
        "resultType": "LAF"
      },
      "currentTab": "thresholdViewTab",
      "darkMode": false
    }
  }
}

Response Fields:

app fields:

ui fields:

setConfig

Description:

Updates the SvanLINK configuration. Only the fields you include are changed; omitted fields keep their current values. Both app and ui must be present in the same request.

Send "Params": { "default": true } to reset all settings to factory defaults.

Request Format:

Request Body:

{
  "Request": "setConfig",
  "Params": {
    "app": {
      "tcpPort": 8000,
      "echo": true,
      "wsEnabled": true,
      "wsPort": 8001,
      "svannet": true,
      "activeUI": true,
      "disabledExternalLogin": false,
      "deviceTcpServer": true,
      "deviceTcpPort": 8888,
      "autoDownload": {
        "enabled": false,
        "path": "/path/to/afd",
        "deleteAfterDownload": false,
        "filters": {
          "fileTypes": [],
          "devices": [],
          "startDate": ""
        },
        "storageClearing": {
          "storage": { "value": 10, "unit": "gb", "enabled": false },
          "date":    { "value": 365, "unit": "days", "enabled": false }
        }
      },
      "mqtt": {
        "enabled": true,
        "host": "127.0.0.1",
        "port": 1883,
        "username": "admin",
        "ssl": true,
        "caCert": "base64_encoded_cert",
        "certFile": "base64_encoded_cert",
        "keyFile": "base64_encoded_key"
      }
    },
    "ui": {
      "liveView": {
        "resultTypes": "LAF;LAeq;LCpeak"
      },
      "thresholdView": {
        "thresholdOrange": 45,
        "thresholdRed": 75,
        "k": 0,
        "resultType": "LAF"
      },
      "currentTab": "thresholdViewTab",
      "darkMode": false
    }
  },
  "token": "userToken"
}

app fields:

ui fields:

Success Response:

{
  "Request": "setConfig",
  "Status": "ok"
}

getSetup

Description:

The getSetup API retrieves the setup configuration for a specified device. You can request the setup configuration for a specific device serial number, and the API will return the corresponding setup data in the response.

Request Format:

Request Body:

{
  "Request": "getSetup",
  "Params": {
    "device": "85609" // Device serial number
  },
  "token": "userToken"
}

Success Response:

The response contains the setup configuration data for the requested device.

Response Format:

{
  "Request": "getSetup",
  "Status": "ok",
  "Response": {
    "setupfile": "file encoded in Base64 string format"
  }
}

setSetup

Description:

The setSetup API uploads a setup configuration to a specified device. You can provide the setup configuration file encoded in a Base64 string, and the API will upload it to the specified device.

Request Format:

Request Body:

{
  "Request": "setSetup",
  "Params": {
    "device": "85609", // Device serial number
    "overwrite": true, // Whether to overwrite the existing setup
    "file": "file encoded in Base64 string" // Setup configuration file encoded in Base64
  },
  "token": "userToken"
}

Success Response:

The response indicates whether the setup configuration was successfully uploaded to the device.

Response Format:

{
  "Request": "setSetup",
  "Status": "ok"
}

copySetup

Description:

The copySetup API copies a setup configuration from a source device to one or more target devices. You can specify the source device, target devices, and whether to overwrite the existing setup on the target devices.

Request Format:

Request Body:

{
  "Request": "copySetup",
  "Params": {
    "sourceDevice": "85609", // Source device serial number
    "targetDevices": ["112233", "453789"], // List of target device serial numbers
    "overwrite": true // Whether to overwrite the existing setup on the target devices
  },
  "token": "userToken"
}

Success Response:

The response indicates whether the setup configuration was successfully copied to the target devices.

Response Format:

{
  "Request": "copySetup",
  "Status": "ok"
}

sendRawCommand

Description:

The sendRawCommand API allows you to send # commands directly to the connected device. These commands must follow the format and syntax specified in the device's user manual. The API sends the command to the device and returns the response.

Request Format:

Request Body:

{
  "Request": "sendRawCommand",
  "Params": {
    "devices": ["123456", "654235"],      // Optional: List of device serial numbers.
    "command": "#1,U?,N?;"            // The raw command to send to the device
  },
  "token": "userToken"
}

Success Response:

The response contains the result of the command execution on the device.

Response Format:

{
  "Request": "sendRawCommand",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "response": "#1,U303,N123456;"
    },
    {
      "serial": "654235",
      "response": "#1,U303,N654235;"
    }
  ]
}

Notes:

getFileList

Description:

The getFileList API retrieves a list of files stored on devices. All parameters in Params are optional and act as filters. If a parameter is omitted, no filtering is applied for that field.

Request Format:

Request Body:

{
  "Request": "getFileList",
  "Params": {
    "devices": ["3502"],                    // Optional: List of device serial numbers to filter.
    "mode": "flat",                       // Optional: "flat" for a flat list, "tree" for hierarchical (default: "flat").
    "types": ["TXT", "SVL"],              // Optional: List of file types/extensions to filter.
    "startDate": "2025-05-13 10:30:00",   // Optional: Start date/time (YYYY-MM-DD HH:mm:ss) to filter files created after this date.
    "endDate": "2025-5-13 11:00:00"       // Optional: End date/time (YYYY-MM-DD HH:mm:ss) to filter files created before this date.
  },
  "token": "userToken"
}

Success Response:

The response contains a list of files for each device matching the filters, including file name, size, creation date, and type.

Response Format:

{
  "Request": "getFileList",
  "Status": "ok",
  "Response": [
    {
      "serial": "123456",
      "type": "SV 303",
      "files": [
        {
          "name": "/S1.SVL",
          "size": 1203,
          "dateCreated": "2025-05-13 10:50:40",
          "type": "TXT"
        },
        {
          "name": "/W1.WAV",
          "size": 270336,
          "dateCreated": "2025-05-13 10:52:28",
          "type": "SVL"
        }
      ]
    }
  ],
}

Response Fields:

Notes:

downloadCurrentFile

Description:

The downloadCurrentFile request downloads a single file from a connected device. The HTTP response is a binary stream (not JSON): file bytes with download headers. Depending on mode, you either fetch a file by path on the device or stream the current measurement file (SVL or WAV).

Request Format:

Request Body:

{
  "Request": "downloadCurrentFile",
  "Params": {
    "device": "123456",
    "mode": "byPath",
    "value": "/S1.SVL",
    "offset": 0,
    "force": false
  },
  "token": "userToken"
}

Response:

The response body is the file as a binary stream. Clients must read the raw bytes and save or pipe them to a file.

Notes:

downloadFile (deprecated)

The request name downloadFile is a deprecated alias for downloadCurrentFile. It accepts the same Params and behaves identically. Do not use downloadFile in new code. It will be removed in a future SvanLINK version; migrate to downloadCurrentFile. The sections below reproduce the original downloadFile documentation (request name and examples use downloadFile).

Description

The downloadFile API allows you to download a specific file from a device. The response is a stream of bytes representing the file content.

Request Format

Request Body

{
  "Request": "downloadFile",
  "Params": {
    "device": "123456",                  // Required: Device serial number.
    "mode": "byPath|current",          // Required: Mode for file download.
    "value": "/S1.SVL|SVL"     // Required: Depending on mode, either file path or file type.
  },
  "token": "userToken"
}

Response

The response is a stream of bytes representing the requested file. The content type and headers are set for file download.

Notes

downloadFiles

Description:

The downloadFiles API downloads multiple files from a device in a single request. The response is a binary ZIP archive containing all requested files. If a file has already been synced to SvanLINK via Auto File Download (AFD), it is served from the local AFD cache instead of re-downloading from the device.

Request Format:

Request Body:

{
  "Request": "downloadFiles",
  "Params": {
    "device": "123456",                // Required: Device serial number.
    "files": [
      "/path/file001.svl",
      "/path/file002.wav"
    ],                                 // Required: List of file paths to download.
    "omit": false,                     // Optional: Skip availability checks entirely (default: false).
    "force": false             // Optional: Force live download from device, bypass AFD cache (default: false).
  },
  "token": "userToken"
}

Response:

The response is a binary ZIP archive (Content-Type: application/zip) containing the requested files. This is not a JSON response — handle it as a binary file stream.

Notes:

deleteFiles

Description:

The deleteFiles API deletes one or more files directly from a connected device. The path parameter accepts a single file path string or a list of paths for bulk deletion. Files are deleted sequentially — if any deletion fails, processing stops at that file and an error is returned.

Request Format:

Request Body:

{
  "Request": "deleteFiles",
  "Params": {
    "device": "113200",                    // Required: Device serial number.
    "path": ["/L4.SVL", "/R41.WAV"]       // Required: File path string or list of paths to delete.
  },
  "token": "userToken"
}

Success Response:

{
  "Request": "deleteFiles",
  "Status": "ok",
  "Response": {
    "message": "Files deleted successfully"
  }
}

Error Responses:

Deletion failed (e.g. measurement running):

{
  "Request": "deleteFiles",
  "Status": "error",
  "StatusMessage": "error deleting file /L4.SVL, is measurement stopped?"
}

Missing device parameter:

{
  "Request": "deleteFiles",
  "Status": "error",
  "StatusMessage": "The \"device\" parameter is missing"
}

Missing path parameter:

{
  "Request": "deleteFiles",
  "Status": "error",
  "StatusMessage": "The \"path\" parameter is missing"
}

Notes:

eraseDisk

Description:

The eraseDisk API erases the entire working directory on a connected measurement device — removing all files currently stored there in a single operation. Unlike deleteFiles, which deletes individual named files, eraseDisk wipes the device's working storage wholesale.

The device must have its measurement stopped before the disk can be erased. The operation is sent as a hardware-level command to the device firmware and may take several seconds to complete on large media; during that time the device may not respond to other commands.

Request Format:

Request Body:

{
  "Request": "eraseDisk",
  "Params": {
    "device": "113200"                     // Required: Device serial number.
  },
  "token": "userToken"
}

Success Response:

{
  "Request": "eraseDisk",
  "Status": "ok",
  "Response": {
    "message": "Working directory erased"
  }
}

Long-running operation (warning, not error):

When the device firmware accepts the erase request but does not report immediate completion, the response is returned with a warning rather than a hard success. The operation is still running; the device may be unresponsive until it finishes.

{
  "Request": "eraseDisk",
  "Status": "ok",
  "Warnings": ["Erasing disk may take a while, device might be unresponsive"]
}

Error Responses:

Erase failed (e.g. measurement running):

{
  "Request": "eraseDisk",
  "Status": "error",
  "StatusMessage": "error erasing working directory, is measurement stopped?"
}

Missing device parameter:

{
  "Request": "eraseDisk",
  "Status": "error",
  "StatusMessage": "The \"device\" parameter is missing"
}

Notes:

getFileListFromSvanlink

Description:

The getFileListFromSvanlink API retrieves a list of files that have been downloaded to SvanLINK from devices. This endpoint queries the Auto File Download (AFD) database and returns files that have been synced to SvanLINK, including their download status, paths, and metadata. All parameters in Params are optional and act as filters.

Request Format:

Request Body:

{
  "Request": "getFileListFromSvanlink",
  "Params": {
    "devices": ["3502"],                    // Optional: List of device serial numbers to filter.
    "types": ["SVL", "WAV"]               // Optional: List of file types/extensions to filter.
  },
  "token": "userToken"
}

Success Response:

The response contains a list of files for each device that have been downloaded to SvanLINK, including file path, size, creation date, download date, SvanLINK storage path, and download status.

Response Format:

{
  "Request": "getFileListFromSvanlink",
  "Status": "ok",
  "Response": [
    {
      "serial": "3502",
      "type": "SV 971A",
      "afdSyncDate": "2026-01-12 17:34:35",
      "files": [
        {
          "path": "/R41.WAV",
          "size": 61536506,
          "dateCreated": "2025-05-15 15:25:18",
          "dateDownloaded": "2026-01-12 17:34:35",
          "afdPath": "/path/to/afd/3502/R41_2025-05-15_15-25-18.WAV",
          "status": "downloaded"
        },
        {
          "path": "/L4129.SVL",
          "size": 69550,
          "dateCreated": "2025-05-15 15:25:18",
          "downloadedSize": 1605632,
          "afdPath": "/path/to/afd/3502/L4129_2025-05-15_15-25-18.SVL",
          "status": "downloading"
        }
      ]
    }
  ]
}

Response Fields:

Notes:

syncToSvanlink

Description:

The syncToSvanlink API initiates downloading one or more files from a connected device to SvanLINK. This request triggers the Auto File Download (AFD) system to download the specified files and store them in the configured SvanLINK storage location. Multiple files can be submitted in a single request. Each file is processed independently — skipped files produce warnings but do not prevent other files from being queued.

Request Format:

Request Body:

{
  "Request": "syncToSvanlink",
  "Params": {
    "device": "3502",                        // Required: Device serial number.
    "value": ["/R41.WAV", "/L4129.SVL"],     // Required: File path (string) or list of file paths.
    "force": false                           // Optional: If true, skip the already-downloaded check (default: false).
  },
  "token": "userToken"
}

Success Response:

Returns "ok" once all requested files have been evaluated and download threads started for eligible files. If some files were skipped (already downloaded or currently in progress), their paths are listed in Warnings.

Response — all files queued:

{
  "Request": "syncToSvanlink",
  "Status": "ok"
}

Response — some files skipped (warnings):

{
  "Request": "syncToSvanlink",
  "Status": "ok",
  "Warnings": [
    "file already downloaded: /R41.WAV",
    "File is beeing downloaded: /L4129.SVL"
  ]
}

Response Fields:

Error Responses:

Missing device parameter:

{
  "Request": "syncToSvanlink",
  "Status": "error",
  "StatusMessage": "The \"device\" parameter is missing"
}

Missing or empty value parameter:

{
  "Request": "syncToSvanlink",
  "Status": "error",
  "StatusMessage": "The \"value\" parameter must be a non-empty list of file paths"
}

Notes:

deleteFilesFromSvanlink

Description:

The deleteFilesFromSvanlink API deletes one or more files from SvanLINK's Auto File Download (AFD) storage. Each file is removed from both SvanLINK's file system and the AFD database. Multiple files can be submitted in a single request. Files not found produce warnings (not errors) when deleting in bulk, so other files in the list still proceed.

Request Format:

Request Body:

{
  "Request": "deleteFilesFromSvanlink",
  "Params": {
    "device": "3502",
    "value": [                                                   // Required: afdPath string or list of afdPaths.
      "/path/to/afd/3502/R41_2025-05-15_15-25-18.WAV",
      "/path/to/afd/3502/L4129_2025-05-15_15-25-18.SVL"
    ]
  },
  "token": "userToken"
}

Success Response:

All files deleted:

{
  "Request": "deleteFilesFromSvanlink",
  "Status": "ok"
}

Some files not found (bulk only):

{
  "Request": "deleteFilesFromSvanlink",
  "Status": "ok",
  "Warnings": [
    "Files not found: /path/to/afd/3502/missing.WAV"
  ]
}

Error Responses:

Single file not found:

{
  "Request": "deleteFilesFromSvanlink",
  "Status": "error",
  "StatusMessage": "File not found"
}

Missing device parameter:

{
  "Request": "deleteFilesFromSvanlink",
  "Status": "error",
  "StatusMessage": "The \"device\" parameter is missing"
}

Missing value parameter:

{
  "Request": "deleteFilesFromSvanlink",
  "Status": "error",
  "StatusMessage": "The \"value\" parameter is missing"
}

Notes:

setAfdConfig

Description:

The setAfdConfig API allows you to configure the Auto File Download (AFD) system settings. This includes enabling/disabling automatic downloads, setting storage paths, file type filters, date filters, and storage clearing policies. All parameters are optional - only the parameters you provide will be updated.

Request Format:

Request Body:

{
  "Request": "setAfdConfig",
  "Params": {
    "enabled": true,                                    // Optional: Enable/disable Auto File Download.
    "path": "/path/to/downloads",                       // Optional: Storage location path on SvanLINK.
    "deleteAfterDownload": false,                       // Optional: Delete file from device after successful download.
    "filters": {                                        // Optional: File filtering configuration.
      "fileTypes": ["SVL", "WAV", "CSV"],               // Optional: List of file types to download.
      "startDate": "2025-01-01 00:00:00"                // Optional: Only download files created after this date (YYYY-MM-DD HH:mm:ss).
    },
    "enableStorageClearing": true,                      // Optional: Enable/disable storage-based clearing (size limit).
    "enableDateClearing": false,                        // Optional: Enable/disable date-based clearing (age limit).
    "storageLimit": 100,                                // Optional: Storage size limit value. Requires enableStorageClearing.
    "storageLimitUnit": "GB",                           // Optional: Storage size limit unit ("MB", "GB", "TB"). Requires storageLimit.
    "storageTimeLimit": 30,                             // Optional: Storage time limit value. Requires enableDateClearing.
    "storageTimeUnit": "days"                           // Optional: Storage time limit unit ("days", "weeks", "months"). Requires storageTimeLimit.
  },
  "token": "userToken"
}

Success Response:

The response indicates that the configuration has been updated successfully.

Response Format:

{
  "Request": "setAfdConfig",
  "Status": "ok",
  "Response": {
    "message": "Configuration updated successfully"
  }
}

Response Fields:

Notes:

getVersion

Description:

The getVersion API retrieves the current version of the SvanLINK application. This is useful for checking which version of the software is running on SvanLINK.

Request Format:

Request Body:

{
  "Request": "getVersion",
  "token": "userToken"
}

Response:

The response contains the current version of the SvanLINK application.

Response Format:

{
  "Request": "getVersion",
  "Status": "ok",
  "Response": {
    "version": "{{ version }}"
  }
}

checkUpdate

Description:

The checkUpdate API checks if a new version of the SvanLINK application is available. It returns information about the latest version, its release date, and changelog.

Request Format:

Request Body:

{
  "Request": "checkUpdate",
  "token": "userToken"
}

Success Response:

The response indicates whether an update is available and provides details about the latest version.

Response Format:

{
  "Request": "checkUpdate",
  "Status": "ok",
  "Response": {
    "available": true,
    "critical": false,
    "version": "1.0.0",
    "date": "2025-05-01",
    "changelog": "- Added new features\n- Fixed bugs\n- Improved performance"
  }
}

Error Response:

{
  "Request": "checkUpdate",
  "Status": "error",
  "StatusMessage": "Unable to check for updates"
}

Notes:

downloadUpdate

Description:

The downloadUpdate API downloads the latest available update for the SvanLINK application. It initiates the download process or returns the current status if already in progress or completed.

Request Format:

Request Body:

{
  "Request": "downloadUpdate",
  "token": "userToken"
}

Success Response:

The response indicates the status of the update download process.

Response Format:

{
  "Request": "downloadUpdate",
  "Status": "ok",
  "Response": {
    "status": "downloading|downloaded"
  }
}

Error Response:

{
  "Request": "downloadUpdate",
  "Status": "error",
  "StatusMessage": "Unable to download update"
}

Notes:

installUpdate

Description:

The installUpdate API installs the latest downloaded update for the SvanLINK application. It starts the update process and may require elevated privileges depending on the operating system.

Request Format:

Request Body:

{
  "Request": "installUpdate",
  "token": "userToken"
}

Success Response:

The response indicates that the update process has started.

Response Format:

{
  "Request": "installUpdate",
  "Status": "ok",
  "Response": {
    "status": "updating"
  }
}

Error Response:

{
  "Request": "installUpdate",
  "Status": "error",
  "StatusMessage": "Error message"
}

Notes:

setMqttConfig

Description:

The setMqttConfig API configures the MQTT broker connection settings for SvanLINK. This includes the broker host, port, authentication credentials, and enables or disables the MQTT service. After configuration, the application will restart to apply the changes.

Request Format:

Request Body:

{
  "Request": "setMqttConfig",
  "Params": {
    "enabled": true,                     // Optional: Enable or disable MQTT service (boolean)
    "host": "mqtt.example.com",          // Optional: MQTT broker host address
    "port": 1883,                        // Optional: MQTT broker port number
    "username": "mqtt_user",             // Optional: MQTT broker username
    "password": "mqtt_password",         // Optional: MQTT broker password
    "ssl": true,                         // Optional: A boolean indicating if the MQTT is using SSL/TLS (e.g., true).
    "caCert": "base64_encoded_cert",     // Optional: The CA certificate for the MQTT (e.g., "base64_encoded_cert").
    "certFile": "base64_encoded_cert",   // Optional: The certificate file for the MQTT (e.g., "base64_encoded_cert").
    "keyFile": "base64_encoded_key"      // Optional: The key file for the MQTT (e.g., "base64_encoded_key").
  },
  "token": "userToken"
}

Success Response:

If the configuration is successfully applied, the response will indicate success. Note that the application will restart after a successful configuration update.

Response Format:

{
  "Request": "setMqttConfig",
  "Status": "ok"
}

Error Response:

If the request fails, an error response is returned.

Response Format:

{
  "Request": "setMqttConfig",
  "Status": "error",
  "StatusMessage": "Error message describing what went wrong"
}

Notes:

getMqttConfig

Description:

The getMqttConfig API retrieves the current MQTT broker configuration settings, including the broker host, port, username, and enabled status. Note that the password is not returned for security reasons.

Request Format:

Request Body:

{
  "Request": "getMqttConfig",
  "token": "userToken"
}

Success Response:

The response contains the current MQTT broker configuration.

Response Format:

{
  "Request": "getMqttConfig",
  "Status": "ok",
  "Response": {
    "enabled": true,
    "host": "mqtt.example.com",
    "port": 1883,
    "username": "mqtt_user",
    "ssl": true
  }
}

Notes:

addMqttTopic

Description:

The addMqttTopic API creates or updates an MQTT topic configuration. This allows you to configure which data requests should be automatically published to the MQTT broker at specified intervals. The configuration is similar to WebSocket channel configuration.

Request Format:

Request Body:

{
  "Request": "addMqttTopic",
  "Params": {
    "Topic": "main",  // Optional: Topic name. Default is "main"
    "Requests": [
      {
        "Request": "getResults",
        "Interval": 1000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
        "startSync": 1       // Optional: align first emission to next multiple of N seconds (default: 1).
      },
      {
        "Request": "getSpectrumResults",
        "Interval": 5000,    // Interval in milliseconds (ms). Minimum interval is 100ms.
        "startSync": 60      // Optional: start on the next whole minute boundary.
      }
    ]
  },
  "token": "userToken"
}

Success Response:

If the MQTT topic is successfully created or updated, the response will indicate success.

Response Format:

{
  "Request": "addMqttTopic",
  "Status": "ok"
}

Error Response:

If the request fails, an error response is returned.

Response Format:

{
  "Request": "addMqttTopic",
  "Status": "error",
  "StatusMessage": "missing config param" or "config must be in json"
}

Note: The error message "missing config param" refers to the Params object being missing or empty. The error message "config must be in json" indicates that Params must be a valid JSON object.

Notes:

deleteMqttTopic

Description:

The deleteMqttTopic API deletes a specific MQTT topic configuration. This will stop all automatic data publishing for that topic and remove it from the configuration.

Request Format:

Request Body:

{
  "Request": "deleteMqttTopic",
  "Params": {
    "topic": "main"  // Required: The name of the MQTT topic to delete
  },
  "token": "userToken"
}

Success Response:

If the topic is successfully deleted, the response will indicate success.

Response Format:

{
  "Request": "deleteMqttTopic",
  "Status": "ok",
  "StatusMessage": "The topic has been deleted successfully"
}

Error Response:

If the request fails, an error response is returned.

Missing Parameter:

{
  "Request": "deleteMqttTopic",
  "Status": "error",
  "StatusMessage": "The \"topic\" parameter is missing"
}

Topic Doesn't Exist:

{
  "Request": "deleteMqttTopic",
  "Status": "error",
  "StatusMessage": "Error delete topic"
}

Notes:

getMqttTopicList

Description:

The getMqttTopicList API retrieves a list of all configured MQTT topics and their configurations. This includes information about which requests are being published and at what intervals.

Request Format:

Request Body:

{
  "Request": "getMqttTopicList",
  "token": "userToken"
}

Success Response:

The response contains all configured MQTT topics and their associated request configurations.

Response Format:

{
  "Request": "getMqttTopicList",
  "Status": "ok",
  "Response": [    
    {
      "Topic": "main",
      "Requests": [
        {
          "Request": "getResults",
          "Interval": 1000,
          "startSync": 1
        },
        {
          "Request": "getSpectrumResults",
          "Interval": 5000,
          "startSync": 60
        }
      ]
    },
    {
      "Topic": "deviceStatus",
      "Requests": [
        {
          "Request": "getStatus",
          "Interval": 15000,
          "startSync": 1
        }
      ]
    }
  ]
}

Response Fields:

Notes:

subscribeChannel

Description:

The subscribeChannel API allows a WebSocket client to subscribe to a specific channel for receiving real-time data. This request can only be sent via WebSocket connection and enables the client to receive periodic updates from the specified channel.

Note: This request is WebSocket-only and cannot be sent via HTTP/TCP connections.

Request Format:

Request Body:

{
  "Request": "subscribeChannel",
  "Params": {
    "channel": "main"
  }
}

Success Response:

If the subscription is successful, the response will indicate that the client has been subscribed to the specified channel.

Response Format:

{
  "Request": "subscribeChannel",
  "Status": "ok",
  "Response": {
    "message": "Subscribed to channel successfully"
  }
}

Error Responses:

No Channel Specified:

{
  "Request": "subscribeChannel",
  "Status": "error",
  "StatusMessage": "The "channel" parameter is missing"
}

Channel Doesn't Exist:

{
  "Request": "subscribeChannel",
  "Status": "error",
  "StatusMessage": "The channel doesn't exist. Subscribing to the 'main' channel."
}

Notes:

getChannelList

Description:

The getChannelList API retrieves a list of all available WebSocket channels and their configurations. This request can only be sent via WebSocket connection and returns information about all configured channels, including their associated requests and intervals.

Note: This request is WebSocket-only and cannot be sent via HTTP/TCP connections.

Request Format:

Request Body:

{
  "Request": "getChannelList"
}

Success Response:

The response contains all configured WebSocket channels and their associated request configurations.

Response Format:

{
  "Request": "getChannelList",
  "Status": "ok",
  "Response": [
    {
      "Channel": "main",
      "Requests": [
        {
          "Request": "getResults",
          "Interval": 1000,
          "startSync": 1
        },
        {
          "Request": "getSpectrumResults",
          "Interval": 5000,
          "startSync": 60
        }
      ]
    },
    {
      "Channel": "deviceStatus",
      "Requests": [
        {
          "Request": "getStatus",
          "Interval": 15000,
          "startSync": 1
        }
      ]
    }
  ]
}

Response Fields:

Notes:

This configuration creates a new channel or updates an existing one with the specified requests and intervals.

deleteChannel

Description:

The deleteChannel API allows a WebSocket client to delete a specific channel and its associated configuration. This request can only be sent via WebSocket connection and permanently removes the channel from the system, including all its configured requests and intervals.

Note: This request is WebSocket-only and cannot be sent via HTTP/TCP connections.

Request Format:

Request Body:

{
  "Request": "deleteChannel",
  "Params": {
    "channel": "main"
  }
}

Success Response:

If the channel is successfully deleted, the response will indicate that the channel has been removed from the system.

Response Format:

{
  "Request": "deleteChannel",
  "Status": "ok",
  "StatusMessage": "The channel has been deleted successfully"
}

Error Responses:

No Channel Specified:

{
  "Request": "deleteChannel",
  "Status": "error",
  "StatusMessage": "The "channel" parameter is missing"
}

Channel Doesn't Exist:

{
  "Request": "deleteChannel",
  "Status": "error",
  "StatusMessage": "Error, the channel doesn't exist!"
}

Notes:

downloadFileStatus - WebSocket Message

Description:

The downloadFileStatus is a WebSocket message sent automatically by the server to clients subscribed to the "UI" channel. This message provides real-time updates about the status of file downloads from devices to SvanLINK. It is sent periodically during active downloads and when download status changes.

Note: This is a WebSocket message sent by the server, not a request that can be sent by clients.

Message Format:

Message Structure:

{
  "Request": "downloadFileStatus",
  "Response": {
    "serial": "3502",
    "path": "/R41.WAV",
    "size": 61536506,
    "dateCreated": "2025-05-15 15:25:18",
    "afdPath": "/path/to/afd/3502/R41_2025-05-15_15-25-18.WAV",
    "status": "downloading",
    "downloadedSize": 1605632
  }
}

Message Fields:

Usage:

To receive downloadFileStatus messages, clients must:

  1. Establish a WebSocket connection to the server (default port 8001).
  2. Authenticate by sending a valid token.
  3. Subscribe to the "UI" channel using the channel subscription mechanism.

Example Client Code:

// JavaScript example
const ws = new WebSocket('ws://localhost:8001');

ws.onopen = () => {
  // Send authentication token
  ws.send('yourAuthToken');
  
  // Subscribe to UI channel
  ws.send(JSON.stringify({
    "Channel": "UI",
    "Requests": []
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  if (data.Request === 'downloadFileStatus') {
    const file = data.Response;
    console.log(`File: ${file.path}`);
    console.log(`Status: ${file.status}`);
    console.log(`Progress: ${file.downloadedSize}/${file.size} bytes`);
    
    // Calculate download percentage
    if (file.downloadedSize && file.size) {
      const percentage = (file.downloadedSize / file.size * 100).toFixed(2);
      console.log(`Download progress: ${percentage}%`);
    }
  }
};

Notes: