API основного бэкенд приложения и другая полезная информация о нём - Glost/iot-olap-clickhouse GitHub Wiki

Общая информация

Исходный код приложения находится в директории server. Технологический стек: Java 8, Spring Boot, PostgreSQL (реляционная СУБД для кратковременного хранения текущих данных), ClickHouse (OLAP column-oriented СУБД для выгрузки аналитических данных за промежуток времени для хранения на постоянной основе и использования в аналитических целях).

Данные в ClickHouse выгружаются в начале каждого астрономического часа. Данные, выгружаемые в ClickHouse, удаляются из PostgreSQL.

Используются POST-запросы, тело POST-запросов передаётся в JSON-формате, ответы запросов, если они есть, передаются также в JSON-формате.

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

Статус запроса будет 200, если запрос отработал корректно.

Хост приложения

To be defined.

Подключение к виртуальной машине (по SSH) и к БД

Виртуальная машина с развёрнутым и запущенным бэкенд-приложением и кластеры обеих БД (PostgreSQL и ClickHouse) расположены в To be defined. Все данные (кроме паролей, но они есть в файлах с пропертями) и инструкции для подключения к БД можно найти по ссылкам ниже, а для подключения к виртуальной машине - надо добавить свой SSH-ключ в доверенные.

  • Виртуальная машина: To be defined.
  • Кластер PostgreSQL: To be defined.
  • Кластер ClickHouse: To be defined.

Пользовательские типы данных

  • Coordinates - координаты датчика, поля:
    • latitude - широта (в градусах), на которой расположен датчик - тип double - обязательное
    • longitude - долгота (в градусах), на которой расположен датчик - тип double - обязательное
    • altitude - высота над уровнем моря (в метрах), на которой расположен датчик - тип double - обязательное
  • Values - показания датчика, поля:
    • air_temperature - температура воздуха (в градусах Цельсия) - тип double - обязательное
    • air_humidity - влажность воздуха (в процентах) - тип double - обязательное
    • wind_speed - скорость ветра (в метрах в секунду) - тип double - обязательное
    • is_raining - флаг, идёт ли дождь (true, если идёт, иначе false) - тип boolean - обязательное
    • illuminance - освещённостьлюксах) - тип double - обязательное
  • CoordinateInterval - отрезок для значения координаты датчика, поля:
    • from - начальное значение отрезка (включительно) - тип double - обязательное
    • to - конечное значение отрезка (включительно) - должно быть не меньше, чем from - тип double - обязательное
  • TimestampInterval - отрезок для значения времени произведения замера показаний на датчике, поля:
    • from - начальное значение отрезка (включительно) - строка (тип String) в формате yyyy-MM-dd['T'][ ]HH:mm:ss.SSSXXXX (например: 2019-12-01 17:18:48.126+0300, 2019-12-01T17:18:48.126+0300, 2019-12-01 17:18:48.126Z, 2019-12-01T17:18:48.126Z, и т. д.) - обязательное
    • to - конечное значение отрезка (включительно) - должно быть не меньше, чем from - строка (тип String) в формате yyyy-MM-dd['T'][ ]HH:mm:ss.SSSXXXX (например: 2019-12-01 17:18:48.126+0300, 2019-12-01T17:18:48.126+0300, 2019-12-01 17:18:48.126Z, 2019-12-01T17:18:48.126Z, и т. д.) - обязательное
  • AggregatedPeriod - период времени, по которому производится агрегация данных - перечисление (enum), возможные значения:
    • MINUTE - одна минута
    • HOUR - один час
    • DAY - один день
  • AggregatedValue - агрегированные значения того или иного показания датчика(-ов) за то или иное время, поля:
    • timestamp - время, начиная с которого агрегированы показания на датчике, с указанием часового пояса - строка (тип String) в формате yyyy-MM-dd HH:mm:ss.SSSXXXX (например: 2019-12-01 17:18:48.126+0300) - обязательное
    • min - наименьшее значение показания - тип double - обязательное
    • max - наибольшее значение показания - тип double - обязательное
    • avg - среднее значение показания - тип double - обязательное
    • median - медианное значение показания - тип double - обязательное
    • variance - несмещённая оценка дисперсии значений показания - тип double - обязательное
  • AggregatedRainValue - агрегированные значения показания наличия дождя датчика(-ов) за то или иное время, поля:
    • timestamp - время, начиная с которого агрегированы показания на датчике, с указанием часового пояса - строка (тип String) в формате yyyy-MM-dd HH:mm:ss.SSSXXXX (например: 2019-12-01 17:18:48.126+0300) - обязательное
    • avg_rains - среднее количество показаний по учитываемым датчикам за данный промежуток времени, в которых шёл дождь, то есть is_raining в показаниях датчика (Values) было равно true (если показания агрегируются для одного датчика, то количество показаний по данному датчику за данный промежуток времени, в которых шёл дождь) - тип double - обязательное
  • AggregatedValues - агрегированные значения показаний датчика(-ов), поля:
    • air_temperature - массив объектов AggregatedValue агрегированных за разное время значений для температуры воздуха (в градусах Цельсия) - тип AggregatedValue[] - обязательное
    • air_humidity - массив объектов AggregatedValue агрегированных за разное время значений для влажности воздуха (в процентах) - тип AggregatedValue[] - обязательное
    • wind_speed - массив объектов AggregatedValue агрегированных за разное время значений для скорости ветра (в метрах в секунду) - тип AggregatedValue[] - обязательное
    • illuminance - массив объектов AggregatedValue агрегированных за разное время значений для освещённостилюксах) - тип AggregatedValue[] - обязательное
    • avg_rains_values - массив объектов AggregatedRainValue со средними количествами показаний по учитываемым датчикам за данные промежутки времени, в которых шёл дождь, то есть is_raining в показаниях датчика (Values) было равно true (если показания агрегируются для одного датчика, то количество показаний по данному датчику за данный промежуток времени, в которых шёл дождь) - тип AggregatedRainValue[] - обязательное
  • SensorAggregatedValues - агрегированные значения показаний датчика(-ов) с информацией о самом(-их) датчике(-ах), поля:
    • coordinates - координаты датчика - тип Coordinates - необязательное (если null или не задано, то агрегированные показания представляют собой агрегированные данные по всем удовлетворяющим запросу датчикам, а не по одному конкретному)
    • aggregated_values - агрегированные значения показаний датчика(-ов) за разные промежутки времени - тип AggregatedValues - обязательное

Описание методов API

POST /pushData

Передача данных от датчика серверу.

Поля тела запроса:

  • coordinates - координаты датчика - тип Coordinates - обязательное
  • values - значения датчика - тип Values - обязательное
  • timestamp - время произведения замера показаний на датчике, с указанием часового пояса - строка (тип String) в формате yyyy-MM-dd['T'][ ]HH:mm:ss.SSSXXXX (например: 2019-12-01 17:18:48.126+0300, 2019-12-01T17:18:48.126+0300, 2019-12-01 17:18:48.126Z, 2019-12-01T17:18:48.126Z, и т. д.) - обязательное

Пример тела запроса в формате JSON:

{
  "coordinates": {
    "latitude": 55.755831,
    "longitude": 37.617673,
    "altitude": 156.5
  },
  "values": {
    "air_temperature": 15.7,
    "air_humidity": 72.1,
    "wind_speed": 5.62,
    "is_raining": false,
    "illuminance": 5072.134
  },
  "timestamp": "2019-12-01 17:18:48.126+0300"
}

Тело ответа пустое, но необходимо смотреть на статус выполнения запроса (200 или не 200), возвращённый сервером.

POST /getAggregatedData

Получение агрегированных в ClickHouse данных от сервера.

Поля тела запроса:

  • latitude_intervals - массив объектов типа CoordinateInterval для широты (в градусах), на которой расположен датчик - тип CoordinateInterval[] - необязательное (если null или не задано, то широта, на которой расположен датчик, не ограничивается)
  • longitude_intervals - массив объектов типа CoordinateInterval для долготы (в градусах), на которой расположен датчик - тип CoordinateInterval[] - необязательное (если null или не задано, то долгота, на которой расположен датчик, не ограничивается)
  • altitude_intervals - массив объектов типа CoordinateInterval для высоты над уровнем моря (в метрах), на которой расположен датчик - тип CoordinateInterval[] - необязательное (если null или не задано, то высота над уровнем моря, на которой расположен датчик, не ограничивается)
  • timestamp_interval - объект типа TimestampInterval для времени произведения замера показаний на датчике - тип TimestampInterval - обязательное
  • aggregated_period - период времени, по которому производится агрегация данных - тип AggregatedPeriod (в JSON представлен как строка - String) - обязательное
  • need_split_by_coordinates - показывает, нужно ли возвращать агрегированные данные по каждому отдельному датчику (true) или только агрегированные данные по всем удовлетворяющим запросу датчикам (false) - необязательное (по умолчанию false)

Пример тела запроса в формате JSON:

{
  "latitude_intervals": [
    {
      "from": 55.755831,
      "to": 57.854573
    },
    {
      "from": 65.459327,
      "to": 69.423342
    }
  ],
  "longitude_intervals": [
    {
      "from": 37.617673,
      "to": 41.965782
    }
  ],
  "altitude_intervals": [
    {
      "from": 150.0,
      "to": 450.0
    }
  ],
  "timestamp_interval": {
    "from": "2019-12-01 17:18:48.126+0300",
    "to": "2019-12-05 15:00:00.000+0300"
  },
  "aggregated_period": "HOUR",
  "need_split_by_coordinates": true
}

Другой пример тела запроса в формате JSON, здесь не ограничены широта и долгота, на которых расположен датчик, а также не требуется возвращать агрегированные данные по каждому отдельному датчику, будут возвращены только агрегированные данные по всем удовлетворяющим запросу датчикам:

{
  "altitude_intervals": [
    {
      "from": 150.0,
      "to": 450.0
    }
  ],
  "timestamp_interval": {
    "from": "2019-12-01 17:18:48.126+0300",
    "to": "2019-12-05 15:00:00.000+0300"
  },
  "aggregated_period": "HOUR",
  "need_split_by_coordinates": false
}

Поля тела ответа:

  • is_success - выполнен ли запрос успешно (true) или нет (false) - тип boolean - обязательное
  • error_message - текст ошибки (в тех случаях, когда is_success равен false) - строка (тип String) - необязательное (отсутствует либо равно null, если is_success равен true, но обязательное, если is_success равен false)
  • click_house_query_execution_time - суммарное время выполнения всех запросов в ClickHouse, выполненных при исполнении данного запроса к бэкенд-приложению (в миллисекундах) - тип int - необязательное (отсутствует либо равно null, если is_success равен false, но обязательное, если is_success равен true)
  • sensor_aggregated_values - массив объектов типа SensorAggregatedValues с агрегированными значениями показаний датчика(-ов) с информацией о самом(-их) датчике(-ах) - тип SensorAggregatedValues[] - необязательное (может отсутствовать либо быть равно null или пустому массиву, если is_success равен false либо не найдено ни одного датчика или показаний датчика для указанных в запросе ограничений по координатам и времени)

Пример тела ответа в формате JSON, если флаг need_split_by_coordinates в теле запроса был равен true:

{
  "is_success": true,
  "click_house_query_execution_time": 2791,
  "sensor_aggregated_values": [
    {
      "coordinates": {
        "latitude": 55.755831,
        "longitude": 37.617673,
        "altitude": 156.5
      },
      "aggregated_values": {
        "air_temperature": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 15.5,
            "max": 16.1,
            "avg": 15.82,
            "median": 15.7,
            "variance": 0.357
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 15.3,
            "max": 15.9,
            "avg": 15.62,
            "median": 15.5,
            "variance": 0.357
          }
        ],
        "air_humidity": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 70.5,
            "max": 82.36,
            "avg": 77.89,
            "median": 72.34,
            "variance": 3.359
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 70.7,
            "max": 82.56,
            "avg": 78.09,
            "median": 72.54,
            "variance": 3.359
          }
        ],
        "wind_speed": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 5.21,
            "max": 5.87,
            "avg": 5.72,
            "median": 5.34,
            "variance": 0.12376
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 5.41,
            "max": 6.07,
            "avg": 5.92,
            "median": 5.54,
            "variance": 0.12376
          }
        ],
        "illuminance":[
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 4045.45,
            "max": 5201.01,
            "avg": 5145.54,
            "median": 5054.45,
            "variance": 45.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 3045.45,
            "max": 4201.01,
            "avg": 4145.54,
            "median": 4054.45,
            "variance": 45.5
          }
        ],
        "avg_rains": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "avg_rains": 7.0
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "avg_rains": 3.0
          }
        ]
      }
    },
    {
      "coordinates": {
        "latitude": 56.124057,
        "longitude": 40.750421,
        "altitude": 300.0
      },
      "aggregated_values": {
        "air_temperature": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 13.5,
            "max": 14.1,
            "avg": 13.82,
            "median": 13.7,
            "variance": 0.357
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 13.3,
            "max": 13.9,
            "avg": 13.62,
            "median": 13.5,
            "variance": 0.357
          }
        ],
        "air_humidity": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 72.5,
            "max": 84.36,
            "avg": 79.89,
            "median": 74.34,
            "variance": 3.359
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 72.7,
            "max": 84.56,
            "avg": 80.09,
            "median": 74.54,
            "variance": 3.359
          }
        ],
        "wind_speed": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 7.21,
            "max": 7.87,
            "avg": 7.72,
            "median": 7.34,
            "variance": 0.12376
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 7.41,
            "max": 8.07,
            "avg": 7.92,
            "median": 7.54,
            "variance": 0.12376
          }
        ],
        "illuminance":[
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 4065.45,
            "max": 5221.01,
            "avg": 5165.54,
            "median": 5074.45,
            "variance": 45.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 5065.45,
            "max": 6221.01,
            "avg": 6165.54,
            "median": 6074.45,
            "variance": 45.5
          }
        ],
        "avg_rains": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "avg_rains": 0.0
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "avg_rains": 0.0
          }
        ]
      }
    },
    {
      "aggregated_values": {
        "air_temperature": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 14.5,
            "max": 15.1,
            "avg": 14.82,
            "median": 14.7,
            "variance": 0.357
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 14.3,
            "max": 14.9,
            "avg": 14.62,
            "median": 14.5,
            "variance": 0.357
          }
        ],
        "air_humidity": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 71.5,
            "max": 83.36,
            "avg": 78.89,
            "median": 73.34,
            "variance": 3.359
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 71.7,
            "max": 83.56,
            "avg": 79.09,
            "median": 73.54,
            "variance": 3.359
          }
        ],
        "wind_speed": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 6.21,
            "max": 6.87,
            "avg": 6.72,
            "median": 6.34,
            "variance": 0.12376
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 6.41,
            "max": 7.07,
            "avg": 6.92,
            "median": 6.54,
            "variance": 0.12376
          }
        ],
        "illuminance":[
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 4055.45,
            "max": 5211.01,
            "avg": 5155.54,
            "median": 5064.45,
            "variance": 45.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 3055.45,
            "max": 4211.01,
            "avg": 4155.54,
            "median": 4064.45,
            "variance": 45.5
          }
        ],
        "avg_rains": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "avg_rains": 3.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "avg_rains": 1.5
          }
        ]
      }
    }
  ]
}

Другой пример тела ответа в формате JSON, если флаг need_split_by_coordinates в теле запроса был равен false:

{
  "is_success": true,
  "click_house_query_execution_time": 1248,
  "sensor_aggregated_values": [
    {
      "aggregated_values": {
        "air_temperature": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 14.5,
            "max": 15.1,
            "avg": 14.82,
            "median": 14.7,
            "variance": 0.357
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 14.3,
            "max": 14.9,
            "avg": 14.62,
            "median": 14.5,
            "variance": 0.357
          }
        ],
        "air_humidity": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 71.5,
            "max": 83.36,
            "avg": 78.89,
            "median": 73.34,
            "variance": 3.359
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 71.7,
            "max": 83.56,
            "avg": 79.09,
            "median": 73.54,
            "variance": 3.359
          }
        ],
        "wind_speed": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 6.21,
            "max": 6.87,
            "avg": 6.72,
            "median": 6.34,
            "variance": 0.12376
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 6.41,
            "max": 7.07,
            "avg": 6.92,
            "median": 6.54,
            "variance": 0.12376
          }
        ],
        "illuminance":[
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "min": 4055.45,
            "max": 5211.01,
            "avg": 5155.54,
            "median": 5064.45,
            "variance": 45.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "min": 3055.45,
            "max": 4211.01,
            "avg": 4155.54,
            "median": 4064.45,
            "variance": 45.5
          }
        ],
        "avg_rains": [
          {
            "timestamp": "2019-12-01 17:00:00.000+0300",
            "avg_rains": 3.5
          },
          {
            "timestamp": "2019-12-01 18:00:00.000+0300",
            "avg_rains": 1.5
          }
        ]
      }
    }
  ]
}

Другой пример тела ответа в формате JSON, если не найдено ни одного датчика или показаний датчика для указанных в запросе ограничений по координатам и времени:

{
  "is_success": true,
  "click_house_query_execution_time": 971
}

Другой пример тела ответа в формате JSON, если произошла ошибка выполнения запроса:

{
    "is_success": false,
    "error_message": "There were some errors:\ncoordinateInterval.to [55.854573] should be not less than coordinateInterval.from [57.755831]\ntimestampInterval.to [2019-12-01T 20:18:48.126Z] should be not less than timestampInterval.from [2019-12-02T 17:18:48.126Z]"
}