Skip to content

Services and features

The Central Server is composed of multiple concurrent services that run in the background, depending on the active configuration and license. Some may be toggled on and off and some are always running.

Device connection service

This service is always enabled, and is responsible for connecting and maintaining sessions with all managed RAVAS devices on the network. On startup it will read the database for devices to connect to.

During runtime It works hand-in-hand with the Device scanning service to automatically add new devices and initiate or resume existing connections.

Devices may also be added manually by any user with at least the Manager role in the web interface. This is intended for cases where a device is not discoverable or is not intended to be connected to (e.g. it is in RDC mode and will only push to the server, more on the RDC service)

This service will attempt to maintain connections with all managed devices, reconnecting and logging the error when something goes wrong.

Device scanning service

This service periodically broadcasts UDP packets on the ports 49111 (RedBox) and/or 30718 (ASCII). This service may be toggled on and off in app settings.

The discovery process involves:

  • (Every 5 seconds) Broadcast the UDP packet on all network interfaces
  • Receiving a response from the scale
  • Initiate a TCP connection to the presumed scale
    • On RedBox: initiate a RedBox protocol connection and ask for the device UID, this confirms the validity of the device
    • On a new ASCII device: send a request to get all parameters until the device unique id (macS) is retrieved, confirming that this is a valid device.
    • On a remembered ASCII device: will fetch the parameter data from the database for a device matching the given location and assume it is a valid device. This is done because retrieving ASCII parameters is slow and may affect the indicator's operation
  • Save the valid device in the database and Disconnect from it
  • On failure, pause handling the discovery of this IP address for 1 minute by "tracking" the location, to avoid flooding the network with connection requests

Discovered network locations that failed to connect are considered "Tracked locations" - this will appear only in application logs.

If a device is managed and in the Awaiting reconnect connection phase (mostly due to many consecutive failed attempts) - and if it is re-discovered on the local network, then the connection timeout will be reset and the connection will be re-attempted immediately.

This early reconnect will not happen if the error is not a connection timeout error - and instead the device is broken, for example if the device accepts TCP connection but refuses to accept commands - the connection process will be failed and a reconnect will be scheduled, however a re-discovery of this device will not trigger an early reconnect

RDC Service

This service replicates the legacy behavior of the RAVAS Data collector (RDC). It will open a TCP socket (by default 5555) awaiting weight records in the special push data record (PDR) format defined for RDC.

The central server fully implements this protocol, and similarly to the legacy RDC - will log all connection events and requests made over this service.

The pushed weight records contain a scale identifier. The central server will find the appropriate device by associating this id to the device's Custom Id field which can be changed at any time by users with at least Manager role.

If an associated scale cannot be found the central server will reject the request, log it, and effectively ignore the weight data.

Also similarly to the legacy RDC, the scales must be defined manually in the central server beforehand. These scales shouldn't be managed, as an indicator in RDC mode will not accept ASCII commands nor has any way to collect parameters or data in the server to scale flow.

In order to view the collected weights, you may access Saved weights from the sidebar for an overview for all scales. Set the Source filter to Uploaded via RDC to only see weights collected from this service.

This can also be done per-scale by accessing the relevant scale page, then going to the Saved weights tab

REST API

The central server exposes a RESTful API for managing scales, settings, fetching historical data, current status, and more. The web interface uses the browser to access the API endpoints, any other service can also execute the same requests.

Most API endpoints have the following request prefix: "/api/v1/"

The full API endpoint description and documentation can be found on any running instance of the server at /scalar, for example http://localhost:7080/scalar

For example the endpoint /api/v1/activated (e.g. GET http://localhost:7080/api/v1/activated) returns a JSON encoded boolean value of whether the license is active or not. This endpoint is among one of the first thing the web interface checks to request a license to be entered.

With some exceptions, nearly all API requests must be authenticated using valid credentials. Each API request may be authenticated using one of the 2 following ways:

  • Using a valid HTTP-only session cookie (used by the web interface, stored in the browser)
  • Using a valid access token in the request header (retrieved by using the login endpoint)

The second method is recommended for network services that want to integrate with the central server.

Authenticating requests using access tokens

First, you must ensure that an account exists. This can be done through the web interface or by using the API endpoint to create a user. On initial startup the web interface will prompt for the default admin account creation, which is the same as executing a request at this endpoint:

POST /api/v1/users/admin HTTP/1.1
Host: localhost
Content-Type: application/json

{"username":"<username>","password":"<password>"}

This request will fail with Unauthorized if an account already exists

Logging in

To obtain the authentication token, you must use the /api/v1/users/login endpoint.

Note the useCookies=false parameter to prevent the server from setting a session cookie, and return an access token response instead. If set to true, the server will return a HTTP cookie intended for browsers instead.

POST /api/v1/users/login?useCookies=false HTTP/1.1
Host: localhost
Content-Type: application/json

{"username":"<username>","password":"<password>"}

The response will be of the following format:

{
    "tokenType": "Bearer",
    "accessToken": "<access token>",
    "expiresIn": 3600,
    "refreshToken": "<refresh token>"
}

Make sure to store both the accessToken and refreshToken values somewhere secure.

The string under accessToken represents the secure token that must be used in the Authorization header of every authenticated request. This token expires by default after 1 hour.

Refreshing the access token

In order to avoid having to login again after 1 hour, call the api/v1/users/refresh endpoint with the previously received refreshToken, as such:

POST /api/v1/users/refresh HTTP/1.1
Host: localhost
Content-Type: application/json

{"refreshToken":"<refresh token>"}

The response is the same as for the login request. You will a new accessToken which expires in 1 hour and a new refreshToken which expires in 90 days.

If the user is updated or deleted in the meantime the tokens will be invalidated. You will be able to keep using the access token until it expires for endpoints that have nothing to do with user-specific information.

With a cookie type session, the server will automatically renew the cookie when it is close to the expiration time - by returning the cookie along with a response to any API call where the cookie was passed, which the browser will know to replace.

Making authenticated requests

Let's say that you want to get the current status of all devices known by the server. For the request to go through, you need to include the Authorization header with the accessToken you received from the login or refresh token request.

The value of the Authorization header is the token type (Bearer) followed by a space and the accessToken value.

GET /api/v1/devices/states HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

Example response:

{
    "01997046-fe18-78bf-8895-fed35b18b997": {
        "connectionStatus": 2,
        "observingWeight": false,
        "weight": {
            "statusBits": 112,
            "alibiText": null,
            "deviceId": "01997046-fe18-78bf-8895-fed35b18b997",
            "significantDigits": 1,
            "protocol": 1,
            "status": 0,
            "unit": 0,
            "net": 93,
            "gross": 161.6,
            "tare": 68.600006,
            "stable": true,
            "inZeroRange": false,
            "time": "2025-09-30T12:37:23.9714247+00:00"
        }
    }
}

Scale management using the API

Most endpoints allowing you to get current scale status, historical data, update scales, require the use of the scale ID. This is a unique identifier the server randomly generates for each scale, and cannot be customized.

Therefore, the first step will usually be to list the available scales using the /api/v1/devices​ endpoint.

GET /api/v1/devices HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

The response will enumerate all available scales:

[
    {
        "id": "01997046-fe18-78bf-8895-fed35b18b997",
        "uidName": "6CCE8D",
        "customId": "103",
        "customName": null,
        "networkLocation": "192.168.0.100",
        "lastConnected": "2025-09-30T12:37:42.46625+00:00",
        "updatedAt": "2025-09-22T07:15:24.824767+00:00",
        "locationValid": true,
        "managed": true,
        "deleted": false,
        "deviceProtocol": 1
    },
    {
        "id": "01997047-2089-7f3b-9526-d8b8de694dbe",
        "uidName": "14F290",
        "customId": null,
        "customName": null,
        "networkLocation": "192.168.0.101",
        "lastConnected": "2025-09-30T13:24:18.035218+00:00",
        "updatedAt": "2025-09-22T07:15:33.641574+00:00",
        "locationValid": true,
        "managed": false,
        "deleted": false,
        "deviceProtocol": 0
    }
]

About scale fields & names

The scale uidName is the unique name of the scale as it was fetched from the scale using its respective protocol. It is also unique and cannot be changed.

The requirement for having and using a random unique id is because scales may also be added manually without ever having to connect to them, as such for these scales the uidName will always be null. (e.g. scales intended to be used for RDC)

Scales can also be assigned a customName which is nothing more than a user-defined name for the scale, for convenience, will appear in the web interface of the central server to more easily identify scales. This name does not have to be unique and may be changed at any time, no APIs require it to be sent.

Lastly, scales may also be assigned a customId which will be elaborated upon below.

Requesting weights

One of the most common use cases for the central server is to provide unified access to scales. The only pre-requisite to access a scale using the API is that the scale is known by the server, either because it was auto-discovered or was added manually. After obtaining the scale's id, you can request the current weight, regardless of protocol (Ascii/RedBox), using the endpoint /api/v1/devices/{id}/weight.

GET /api/v1/devices/01997046-fe18-78bf-8895-fed35b18b997/weight HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

The central server weight response includes all known weighing information in one message, with data on how to display the given weight. The exact format varies slightly between protocols. The RedBox weight response includes much more information: scale interval index, X/Y angles, totalization data, weigh in motion progress and some extra flags.

The RedBox protocol response includes everything in the ASCII response + additional fields, with the exception that the alibiText field is now the alibiNr - the alibi is always a number in the RedBox, while for ASCII it is possible to have any string, though it is usually numerical.

ASCII example:

{
    "statusBits": 112,
    "alibiText": null,
    "deviceId": "01997046-fe18-78bf-8895-fed35b18b997",
    "significantDigits": 1,
    "protocol": 1,
    "status": 0,
    "unit": 0,
    "net": 93,
    "gross": 161.6,
    "tare": 68.600006,
    "stable": true,
    "inZeroRange": false,
    "time": "2025-09-30T14:34:31.3197938+00:00"
}

RedBox example:

{
    "scaleNumber": 0,
    "alibiNr": 0,
    "wiMProgress": 0,
    "canBeShown": true,
    "safetyCriticalError": false,
    "xAngle": -0.5827853,
    "yAngle": 0.45657697,
    "totalFinalized": false,
    "totalNeedToSeeZero": false,
    "totalBiggestScaleIntervalIndex": 0,
    "totalNumberOfWeighings": 0,
    "totalNet": 0,
    "totalGross": 0,
    "deviceId": "01997047-2089-7f3b-9526-d8b8de694dbe",
    "significantDigits": 1,
    "protocol": 0,
    "status": 0,
    "unit": 0,
    "net": 1,
    "gross": 1,
    "tare": 0,
    "stable": true,
    "inZeroRange": false,
    "time": "2025-09-30T14:46:11.8676344+00:00"
}

Scale commands

Common commands

The following commands are supported for both ASCII and RedBox protocols:

  • Set Zero: POST /api/v1/devices/{id}/zero​

    empty body

  • Automatic Tare: POST /api/v1/devices/{id}/auto-tare

    empty body

  • Manual tare: POST /api/v1/devices/{id}/manual-tare

    body containing JSON encoded floating point number

Note about scale commands and weight request

If the requested device is managed, the request will be immediately processed using the active connection. If the device is not connected, commands will wait for 3 seconds before timing out.

If the device is not managed, the central server will attempt to establish a connection to the device then process the request. Here the server will wait at most 30 seconds for the connection to be established and then executes the request.

After the request is completed, the scale will remain connected for at least another 30 seconds, With each subsequent request resetting this timer. The connection will be closed when no request is made and succeds for at least 30 seconds.

ASCII specific commands

Devices using the ASCII protocol have the following additional commands:

  • ASCII Command: POST /api/v1/devices/{id}/ascii-command

    body containing the command name, allowed values are: GG, GN, GT, SZ, RZ, SR, RS, GP, GA, MN, MG, AN, AG

  • Reconfigure: POST /api/v1/devices/{id}/ascii-reconfigure

    empty body. This command will re-fetch and save the updated ASCII parameters from the scale. This is useful if scale parameters like unit label change. Unlike with RedBox devices, the central server cannot detect these changes normally and regularly fetching ASCII parameters may cause performance issues with the scale.

Legacy API

Each scale may be assigned a Custom ID. This is a user-defined value that must be either null or unique. This identifier will also appear next to the device name in the UI (preceded by a hashtag).

This can be used as a way to identify scales similar to customName (with the unique requirement), but it mainly exists for what we call the legacy APIs:

  • POST /rest/scale/weight
  • GET /rest/scale/{customId}/weight/gross: Get current gross weight
  • GET /rest/scale/{customId}/weight/net: Get current net weight
  • GET /rest/scale/{customId}/weight-alibi-nr/gross: Get gross with alibi
  • GET /rest/scale/{customId}/weight-alibi-nr/net: Get net with alibi

These APIs match the requests and responses of the old Ravas Integration Server (RIS)

Example request and response

GET /rest/scale/103/weight/gross?noMotion=true HTTP/1.1
Host: localhost
Authorization: Bearer <access token>
{
    "timestamp": "2025-09-30 15:43:56.419",
    "alias": "103",
    "type": "GROSS_WEIGHT",
    "weight": 162.4
}