Device ====== Object Shape ------------ A device object will always have this shape when not embedded into other objects: .. code-block:: json { "id": "integer", "_type": "string", "parent": "object:device", "children": "array:device", "code": "string", "publicId": "string", "externalId": "string", "name": "string", "shortName": "string", "deviceTags": "string", "sources": "array", "data": "object", "createdAt": "string", "updatedAt": "string" } The ``data`` property inside the device object will have this shape: .. code-block:: json { "Section1": "object", "Section2": "object", "Section3": "object" } Where the sections are defined in the system configuration and are available for inspection in the Control Room. Device Types ------------ .. include:: /partial/devices.rst GET /device/list ---------------- Get the list of all devices. All properties available for the authenticated client will be returned. .. note:: This method supports pagination. Use limit and offset to paginate returned results. The defaults if no limit or offset are provided are limit=5000 and offset=0. GET /device/list?offset=0&limit=5000 The total result set count is returned in all responses in the ``meta`` property. Links to the next or previous page are also provided in the same property. Response ........ The response is a collection of devices. The collection can be empty (``[]`` in JSON). .. code-block:: json { "data": [ { "id": 1, "_type": "device", "name": "Rainbow Room", "code": "5ad2654c-4ce9-4daa-9844-b62b32303553", "deviceType": "room", "createdAt": "2017-08-25T12:44:38+10:00", "updatedAt": "2017-09-06T11:33:48+10:00" }, { "id": 2, "_type": "device", "name": "Sun Room", "code": "282934b9-96b8-4d52-9d9b-91c135d38ba4", "deviceType": "room", "createdAt": "2017-08-25T12:44:38+10:00", "updatedAt": "2017-09-06T11:33:48+10:00" } ], "meta": { "pagination": { "totalItems": 31, "totalPages": 16, "offset": 0, "limit": 2, "next": "/api/5/device/list.json?q=deviceType%3Droom" } } } Errors and Exceptions ..................... General rule is that this method should not return an exception because it's read only. Although general failures or service unavailability may occur, in that case a `5xx` error will be returned. See the list of `Error Responses`_ for more information. GET /device/{idType}:{id} ------------------------- Gets a specific device. All properties available for the authenticated client will be returned. See the list of `Error Responses`_ for more information, in particular error 1401. The response is a single devices (if found). The example below is for ``/device/id:1`` .. code-block:: json { "data": { "id": 1, "_type": "device", "name": "Rainbow Room", "code": "5ad2654c-4ce9-4daa-9844-b62b32303553", "deviceType": "room", "createdAt": "2017-08-25T12:44:38+10:00", "updatedAt": "2017-09-06T11:33:48+10:00" }, "meta": {} } POST /device/new ---------------- Creates a new device and returns it. PATCH /device/{idType}:{id} --------------------------- Updates an existing device. **When calling this you must only provide the properties that you want to change, and nothing else.** See the list of `Error Responses`_ for more information, in particular error 1401. DELETE /device/{idType}:{id} ---------------------------- Deletes an existing device. This will soft-delete a device from the system, hard deletion is available only from the Control Room. See the list of `Error Responses`_ for more information, in particular error 1401. POST /device/ping ----------------- Sends a "ping" to the server, to communicate the client is alive and connected to the internet. The request should contain all properties, always: - **localTime**: current Unix timestamp - **lat**: latitude, as a float - **lon**: longitude, as a float - **battery**: percentage of available battery for clients always connected to a power supply, send 100 - **pingInterval**: the interval set on client side for sending pings - **failedUploads**: number of failed uploads - **network**: name of the network, or "LAN(X.X.X.X)" if wired in - **status**: if the app is running in "foreground" or "background" - **configVersion**: this should be 0 if the app has not downloaded any updated config The server will respond with any global configuration, like the app logo, and if new configuration settings are available for the connected app, then they will be sent down too. Example request: .. code-block:: json { "localTime": 1696201977, "lat": -36.8700467, "lon": 174.7728311, "battery": 100, "pingInterval": 60, "failedUploads": 0, "network": "NZZ-1701", "status": "foreground", "configVersion": 0 } Example response: .. code-block:: json { "data": { "logo": "", "name": "Open Days 2025 LOCAL", "settings": { "enableAt": null, "disableAt": null, "availableFeatures": ["check-in", "check-out", "lead", "delegate-search", "ping"], "allowRejected": false, "delegateType": "Delegate", "deviceHierarchy": [ ["event", "organisation", "promotion"], ["location", "room", "group"], ["session"] ], "forced": ["enableAt", "disableAt", "availableFeatures", "allowRejected", "delegateType", "deviceHierarchy"] }, "configConfirmed": false, "configVersion": 4 }, "meta": [] } You can check the `List of settings`_ below. Device Configuration -------------------- The server holds the configuration for our mobile apps. The configuration is versioned, the version is a simple integer and not a string. Example: `1`, `2`, `123`, `647`. A control room user (admin) can update the app settings, and increment the version number. When this happens all apps should download the new settings and apply them. The process of updating the settings of our apps relies on the Ping API. All apps should send to the server the current version of the configuration they are running (the `configVersion` in the Ping API). If the response payload of the ping call contains new settings, all apps should apply them, and update their current version number. Subsequent calls to ping will not return any settings, if the app version number matches the server version number. The flow is summarised as below: .. mermaid:: sequenceDiagram Actor User participant App participant TAG Actor Admin User->>App: Starts App User->>App: Pairs App (Device Discovery or Portal App-Pairing) App->>TAG: PUT /device-config.json with "mode", "ownDevice" and the local Settings TAG->>App: Acknowledges (200 OK or 400 Bad Request) App->>TAG: POST /ping.json (configVersion=0) TAG->>TAG: Marks the device as not confirmed TAG->>App: Returns Settings and current configVersion=123 App->>App: Applies the new Settings App->>App: Updates local configVersion=123 loop Every X seconds App->>TAG: POST /ping.json (configVersion=123) TAG->>TAG: Marks the device as confirmed TAG->>App: Returns no Settings end Admin->>TAG: Updates the Settings (configVersion=124) App->>TAG: POST /ping.json (configVersion=123) TAG->>TAG: Marks the device as not confirmed TAG->>App: Returns Settings and current configVersion=124 App->>App: Applies the new Settings App->>App: Updates local configVersion=124 loop Every X seconds App->>TAG: POST /ping.json (configVersion=124) TAG->>TAG: Marks the device as confirmed TAG->>App: Returns no Settings end loop As needed User->>App: Update some local Settings App->>TAG: PUT /device-config.json with only the local Settings TAG->>App: Acknowledges (200 OK or 400 Bad Request) end PUT /device-config ------------------ All apps should post only locally configured settings, ``mode`` and ``ownDevice`` against this endpoint. Any unchanged variable should not be sent back to the server. For example let's assume the pool of global settings is: .. code-block:: json { "mode": "gate", "ownDevice": 1, "delegateType": "Delegate", "uiMode": "light" } Let's assume that the only thing that the app can configure locally is `uiMode`. An example of a correct payload is as follow: .. code-block:: json { "value": { "mode": "gate", "ownDevice": 123, "uiMode": "light" } } As you can see the app **MUST** not send to the server the other configuration settings. Posting for example `backgroundColour` too, will make that configuration variable nearly impossible to manage server side. .. _Error Responses: /rest_api/index.html#error-responses List of settings ---------------- The server returns a list of parameters to the apps depending on their type. All values returned by the server must be intended as default values. Some of the parameters can be tweaked locally to be different from their default value. For example an app may allow its user to change the ``delegateType`` used for new people pushed through the delegate API, or to enable/disable the ``allowRejected`` flag used for access control. Some of the parameters must not be tweaked in the app, they will be included in the ``forced`` parameter. For example the same app mentioned above which allows a user to change the ``delegateType``, if that parameter is listed under ``forced``, then the app should roll back to the default value provided by the server, and prevent the user from changing it. +-------------------------+--------------------------------------------------------------------------------------------+ | Parameter | Description | +=========================+============================================================================================+ | enabledAt | The app should not work before the given timestamp | +-------------------------+--------------------------------------------------------------------------------------------+ | disabledAt | The app should not work after the given timestamp | +-------------------------+--------------------------------------------------------------------------------------------+ | availableFeatures | :ref:`List of features` that should be made enabled | | | in the app | +-------------------------+--------------------------------------------------------------------------------------------+ | allowRejected | If enabled: when a ``check-in`` is denied by the server, the app should post a ``join`` | | | followed by a ``check-in``. If the ACL rules are set to follow "Simple ACL", the second | | | ``check-in`` should succeed. If the second ``check-in`` is also rejected the app should | | | post a ``check-in-override`` instead. | +-------------------------+--------------------------------------------------------------------------------------------+ | delegateType | If the ``delegate-create`` feature is enabled, the app should use the given delegate type | | | when posting new delegates. | +-------------------------+--------------------------------------------------------------------------------------------+ | deviceHierarchy | Shows the current hierarchy of devices. The hierarchy can be on multiple ranks. Usually it | | | follows a three-rank system: event → location → session or organisation → event → session. | | | The lower rank devices should be used for checking in/out, higher ranks are used to | | | organise logically the ACL devices. | +-------------------------+--------------------------------------------------------------------------------------------+ | forced | List of parameters that must not be tweaked in the app. | +-------------------------+--------------------------------------------------------------------------------------------+ .. _list-of-settings-available-features: The list of current features that can be listed under ``availableFeatures`` are: check-in People can be checked in through the app check-out People can be checked out through the app lead Leads can be recorded through the app delegate-create New delegates can be created through the app delegate-search The app user can search for delegate through the app ping The app should ping the server at regular intervals and send local time, failed uploads, config version ping-info The app should send additional ping information to the server: battery level, status, coordinates and network name