Служба технічної підтримки

Система контролю транспорту ГЛОБУС

Служба технічної підтримки

WebSocket API

Шлюз для получения данных СКТ Глобус через websocket

Сервис, который служит для конвертации старого протокола (для настольного клиента СКТ Глобус) в API для доступа к данным о перемещениях тарнспортного средства через Websocket.

Протокол представляет собой посылки данных в формате json. Данные от сервера могут быть как ответами на запрос клиента, так и асинхронными посылками, вызванными приходом данных от устройств при изменении их состояния (положения, датчиков и т.д.)

Любая посылка данных имеет вид json объекта. Тип запроса определяется значением его поля name.

Запросы от клиента к серверу

Авторизация "auth"

После установления соединения c сервером по протоколу websocket клиент должен авторизоваться. Для этого служит один из вариантов запроса.

Авторизация при помощи имени пользователя и пароля

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["auth"] },
        "login": { "type": "string" },
        "password": { "type": "string" }
    }
    "required": ["name", "login", "password"]
}

Пример:

{
    "name": "auth",
    "login": "имя пользователя",
    "password": "пароль"
}

Авторизация при помощи идентификатора сессии

Этот вариант нужен, когда уже имеется идентификатор сессии, полученный для данного логина и пароля при помощи api авторизации

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["auth"] },
        "sid": { 
            "type": "string",
            "description": "id сессии, полученной путем авторизации через api"
        }
    },
    "required": ["name", "sid"]
}

Пример:

{
    "name": "auth",
    "sid": "880d1335818669842d086600d97f7ee9b7c69497ddfc3ba9ed8ad42457ced967"
}

Ответ

В ответ сервер должен прислать сообщение с таким же типом auth и полем successful типа boolean, которое будет означать удачную (true) или неудачную (false) попытку авторизации.

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["auth"] },
        "successful": { "type": "boolean" },
        "sid": {
            "type": "string",
            "description": "id сессии для использования в запросах к REST API"
        }
    },
    "required": ["name", "successful"]
}

Пример:

{
    "name": "auth",
    "successful": true
}

После неудачной попытки авторизации сервер закрывает соединение с клиентом. После удачной - клиент может послылать другие запросы серверу, а также сервер может посылать данные клиенту.

Запрос списка устройств "devicesList"

После успешной авторизации клиент может запросить список устройств с сервера.

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["devicesList"] }
    },
    "required": ["name"]
}

Пример:

{
    "name": "devicesList"
}

Ответ со списком устройств

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["devicesList"] },
        "devices": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "regId": {
                        "type": "integer",
                        "description": "Уникальный номер устройства в системе"
                    },
                    "name": {
                        "type": "string",
                        "description": "Произвольное название устройства"
                    },
                    "lastKnownTime": {
                        "type": "string",
                        "description": "Время последнего получения данных в формате ISO 8601 ( https://ru.wikipedia.org/wiki/ISO_8601 )"
                    },
                    "latitude": {
                        "type": "number"
                    },
                    "longitude: {
                        "type": "number"
                    },
                    "speed": {
                        "type": "number",
                        "description": "Средняя скорость на последнем участке в метрах в секунду"
                    },
                    "group" {
                        "type": "string",
                        "description": "Группа, к которой относится это устйроство. Если этого поля нет - то устройство в корневой группе"
                    },
                    "reportPeriods" {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "minItems": 2,
                        "maxItems": 2,
                        "description": "Периоды передачи при включенном и выключенном зажигании, соответственно"
                    },
                    "ignition" {
                        "type": "object",
                        "properties": {
                            "on": {
                                "type": "boolean",
                                "description": "Включено ли зажигание"
                            },
                            "used": {
                                "type": "boolean",
                                "description": "Используется ли дачик зажигания на данном устройстве"
                            }
                        },
                        "required": [ "on", "used" ]
                    },
                    "gpsAntennaStatus": {
                        "type": "object",
                        "properties": {
                            "disconnected": {
                                "type": "boolean",
                                "description": "Антенна отключена"
                            },
                            "shortCircuit": {
                                "type": "boolean",
                                "description": "Антенна замкнута"
                            }
                        },
                        "required": [ "disconnected", "shortCircuit" ],
                        "description": "Состояние GPS антенны (если этого поля нет - то антенна впорядке)"
                    },
                    "sensorsValues": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "num": {
                                    "type": "integer",
                                    "description": "Номер датчика"
                                },
                                "name": {
                                    "type": "string",
                                    "description": "Название датчика для отображения пользователю"
                                },
                                "rawValue": {
                                    "type": "number",
                                    "description": "Исходное значение датчика до применения пересчета на стороне сервера (для отладочного режима)"
                                },
                                "scaledValue": {
                                    "type": "number",
                                    "description": "Значение датчика уже в нужных ведичинах"
                                },
                                "displayValue": {
                                    "type": "string",
                                    "description": "Отформатированное для показа пользователю значение (с нужным количеством знаков после запятой, единицами измерения и т.д."
                                },
                                "flags" {
                                    "type": "object",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "isFuelLevel": {
                                                "type": "boolean",
                                                "description": "Является ли датчиков уровня топлива"
                                            },
                                            "isFuelMeter": {
                                                "type": "boolean",
                                                "description": "Является ли расходомером топлива"
                                            }
                                        },
                                        "required": [ "isFuelLevel", "isFuelMeter" ]
                                    }
                                }
                            },
                            "required": [ "num", "name", "flags" ]
                        }
                    }
                },
                "required": ["regId", "name", "lastKnownTime", "reportPeriods", "ignition"]
            }
        }
    },
    "required": ["name", "devices"]
}

Пример:

{
    "devices": [
        {
            "ignition": {
                "on": false,
                "used": true
            },
            "name": "\"Мерседес - Бенц АР 7926 СВ\"",
            "latitude": 47.41034666666667,
            "reportPeriods": [60, 600],
            "longitude": 34.820725,
            "regId": 52857,
            "sensorsValues": [{
                "name": "\"БортСеть\"",
                "rawValue": 404.0,
                "flags": {
                    "isFuelLevel": false,
                    "isFuelMeter": false
                },
                "num": 1,
                "displayValue": "\"13,03 В\"",
                "scaledValue": 13.032257856000001
            }],
            "lastKnownTime": "2016-05-10T07:54:06Z",
            "speed": 0.0
        },
        {
            "ignition": {
                "on": false,
                "used": true
            },
            "name": "\"KAMAZ 4308\"",
            "latitude": 47.852666666666664,
            "reportPeriods": [30, 300],
            "longitude": 35.23113166666667,
            "regId": 8908,
            "sensorsValues": [
                {
                    "name": "\"Термодатчик 1\"",
                    "rawValue": 230.0,
                    "flags": {
                        "isFuelLevel": false,
                        "isFuelMeter": false
                    },
                    "num": 0,
                    "displayValue": "\"20,9 ℃\"",
                    "scaledValue": 20.872131147540983
                },
                {
                    "name": "\"Термодатчик 2\"",
                    "rawValue": 230.0,
                    "flags": {
                        "isFuelLevel": false,
                        "isFuelMeter": false
                    },
                    "num": 7,
                    "displayValue": "\"20,9 ℃\"",
                    "scaledValue": 20.872131147540983
                },
                {
                    "name": "\"Уровень топлива\"",
                    "rawValue": 876.0,
                    "flags": {
                        "isFuelLevel": true,
                        "isFuelMeter": false
                    },
                    "num": 27,
                    "displayValue": "\"101,36 л\"",
                    "scaledValue": 101.36363636363637
                }
            ],
            "lastKnownTime": "2016-05-13T13:27:45Z",
            "speed": 0.0
        },
        {
            "ignition": {
                "on": false,
                "used": true
            },
            "name": "\"ГазельАР01-37СМ\"",
            "latitude": 47.262431666666664,
            "reportPeriods": [30, 600],
            "longitude": 35.70977,
            "regId": 14041,
            "sensorsValues": [],
            "lastKnownTime": "2016-05-13T13:24:13Z",
            "speed": 0.0
        },
        {
            "ignition": {
                "on": true,
                "used": false
            },
            "name": "\"Газель-пропан\"",
            "latitude": 48.20518333333333,
            "reportPeriods": [30, 600],
            "longitude": 34.943553333333334,
            "regId": 9533,
            "sensorsValues": [],
            "lastKnownTime": "2016-05-13T13:30:12Z",
            "speed": 0.23
        },
        {
            "ignition": {
                "on": false,
                "used": true
            },
            "name": "\"Газель-дизель АР8462СА\"",
            "latitude": 47.85151166666667,
            "reportPeriods": [30, 600],
            "longitude": 35.236088333333335,
            "regId": 9421,
            "sensorsValues": [{
                "name": "\"Уровень топлива\"",
                "rawValue": 627.0,
                "flags": {
                    "isFuelLevel": true,
                    "isFuelMeter": false
                },
                "num": 27,
                "displayValue": "\"6,32 л\"",
                "scaledValue": 6.3157894736842195
            }],
            "lastKnownTime": "2016-05-13T13:22:29Z",
            "speed": 0.0
        },
        {
            "ignition": {
                "on": false,
                "used": true
            },
            "name": "\"Газель - Метан АР 6451 ВО\"",
            "latitude": 47.85129666666667,
            "reportPeriods": [60, 600],
            "longitude": 35.209718333333335,
            "regId": 52858,
            "sensorsValues": [{
                "name": "\"БортСеть\"",
                "rawValue": 401.0,
                "flags": {
                    "isFuelLevel": false,
                    "isFuelMeter": false
                },
                "num": 1,
                "displayValue": "\"12,94 В\"",
                "scaledValue": 12.935483664000001
            }],
            "lastKnownTime": "2016-05-13T13:23:03Z",
            "speed": 0.0
        }],
    "name": "devicesList"
}

Данные от сервера к клиенту

Кроме описанных выше ответов на запросы, сервер также может передавать данные по мере получения их от устройств. Так как получения этих данных имеет асинхронную природу - то они могут начать приходить сразу же после успешной авторизации, до получения списка устройств. Также следует учесть, что данные от устройства с более новой меткой времени могут поступить до получения списка устройств с данными с более старой меткой времени. Т.е. данные в списке устройств будут старее тех данных от устрйоства, которые пришли ранее.

Положение устройства "location"

Передаются при передаче получении сервером новых данных от устройства.

Схема:

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["location"] }
        "regId": {
            "type": "integer",
            "description": "Номер устройства для которого передаются данные"
        },
        "time": {
            "type": "string",
            "description": "Время фиксации координат устрйоством в формате ISO 8601"
        },
        "latitide": { "type": "number" },
        "longitude": { "type": "number" },
        "speed": {
            "type": "number",
            "description": "Средняя скорость в метрах в секунду на участке от прошлой точки маршрута"
        }
    }
    "required": [ "name", "regId", "time", "latitude", "longitude", "speed" ]
}

Значение датчиков "sensorValue"

Передаются после передачи положения устрйства как отдельное сообщение. Относятся к предыдущему полученному положению устройствa с тем же номером (т.е. записаны в тот же момент времени, что и предыдущие даные о положении).

Схема

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["sensorValue"] },
        "regId": {
            "type": "integer",
            "description": "Номер устройства для которого передаются данные"
        },
        "num": {
            "type": "integer",
            "description": "Номер датчика. Такой же, как и в значениях датчика в devicesList"
        },
        "rawValue": { "type": "number" },
        "scaledValue": { "type": "number" },
        "displayValue": { "type": "string" },
    }
    "required": [ "name", "regId", "num", "rawValue", "scaledValue", "displayValue" ]
}

Значения полей - те же, что и в данных о дачиках devicesList, правда название датчика не передается.

В общем случае, данные о датчиках не обязаны приходить непосредственно после данных о положении, между ними могут прийти и другие данные, от другого устрйоства и т.д. Но они всё равно однозначно связываются с предыдущими данными о положении устройства с таким же regId.

Данные от каждого датчика не обязаны присутствовать после каждой посылки location. Данные могут быть не от всех датчиков или вообще отсутствовать, если по каким-то причинам для данной точки фиксации координат они не были измерены.

Изменение состояния зажигания "ignitionChange"

Передаются после данных о положении устройства как отдельное сообщение. Передаются при изменении состояния зажигания на транспортном средстве.

Могут передаваться даже если поле "used" в значениях датчика в списке устройств было помечено как false. В этом случае - можно отображать это значение клиенту для информации, однако действовать как если бы датчика не было. Ну или игорировать эти сообщения.

Схема

{
    "type": "object",
    "properties": {
        "name" { "type": "string", "enum": ["ignitionChange"] },
        "regId" { "type": "integer" },
        "on" {
            "type": "boolean",
            "description": "Включено или выключено зажиание"
        }
    },
    "required": [ "name", "regId", "on" ]
}

Посылка сообщения об изменении состояния - это событие, которое произошло в момент времени, указанный в предыдущей посылке location для данного транспортного средства, т.е. с этого момента вемени значения зажигание стало таким, как указано в поле on. До этого момента - оно было в предыдущем состоянии. Т.е. клиент может выбрать показывать, например состояние "стоп, зажигание выключено", даже если в предыдущей посылке средняя скорость была не 0, так как это средняя скорость за предыдущий интервал, где оно ещё было включено.

Также, в некоторых случаях, событие об изменении состояния зажигания может прийти, когда зажигание уже и так находится в этом же состоянии.

Ошибка "error"

При возникновении каких-либо ошибок при обработке комманд от клиента, либо сообщений от сервера - клиенту передается сообщение с описанием ошибки.

В случае, когда ошибка считается достаточно серьёзной - соединение может быть закрыто сервером. В других случаях - если соединениене было закрыто - можно продолжить обмен данными с сервером.

Схема

{
    "type": "object",
    "properties": {
        "name": { "type": "string", "enum": ["error"] },
        "causedBy": { 
            "type": "string",
            "description": "Имя запроса, который вызвал эту ошибку (если он известен)" 
        }
        "cause": {
            "type": "string",
            "description": "Описание ошибки в произвольном формате"
        }
    },
    "required": ["name"]
}

Проверка соединения ("ping" - "pong")

На данный момент для соединений по вебсокету установлен таймаут в 300 секунд. При типичном использовании этого будет достаточно даже для в случае, когда все машины клиента стоят и передают с периодом 300 секунд (стандартный период при стоянке). Для каких-то более редких случаем и, при необходимости, проверке соединения на "живость" - можно использовать пару запрос - ответ из команд ping и pong. Вторая - ответ на первую.

Т.е. клиент может настроить отправку запроса ping через, например, 250 секунд, в течении которых не было передачи данных со стороны сервера. В ответ сервер пришлет команду pong. Можно такие запросы отправлять и чаще, например, для проверки связи мобильным клиентом, в условиях проблемного мобильного интернета.

Также, клиент должен быть готов сам ответить на команду ping ответом pong. В текущей реализации сервер не отправляет таких запросов к коиенту, однако такая возможность должна быть предусмотрена клиентом.

ping

{
    "type": "object"
    "properties": {
        "name": { "type": "string", "enum": ["ping"] }
    },
    "required": ["name"]
}

pong

{
    "type": "object"
    "properties": {
        "name": { "type": "string", "enum": ["pong"] }
    },
    "required": ["name"]
} 
© 2016 Система контролю транспорту "Глобус". Всі права захищені

Please publish modules in offcanvas position.