API: документация

Общие сведения
Составление запроса для получения данных
Описание данных, предоставляемых по запросу сервисом API
Пример разархивации данных на Java
Расширенный формат данных
Пример данных, получаемых при запросе
Пример отображения полученных данных на картах Google
Пример обработки данных с расширенными полями
Расшифровка ошибок сервера
Квоты
Полный текст примера разархивации KMZ файла на Java
Полный текст примера отображения полученных данных на картах Google
Полный текст примера обработки данных с расширенными полями

Общие сведения

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

При этом пользователю необходимо сгенерировать API ключ. Затем, используя ключ и указав необходимые параметры в запросе, пользователь имеет возможность в автоматическом режиме получить сжатый файл в KMZ формате, который содержит информацию о качестве дорожного покрытия дорог и, непосредственно координатную информацию с уровнями качества для запрашиваемого участка, готовый для использования в соответствующих сервисах Google и других программных интерфейсах.

Для запросов существуют квоты, ограничивающие как количество запросов в сутки, так и размер запрашиваемой области.

Составление запроса для получения данных

Для получения сжатого файла KMZ с данными необходимо составить GET запрос на /apiservice. Данные можно получить как в базовом формате, достаточном для использования отображения раскраски на карте, так и в расширенном, для решения специфических задач, снабженном дополнительной информацией.

Доступны следующие параметры запроса:

ПараметрОписание
lngдолгота центра запрашиваемого участка
latширота центра запрашиваемого участка
apikeyваш API ключ
zoomуровень зума, для которого необходимо получить данные. Может принимать значения от 1 до 10, где 10 - самый крупный масштаб. Игнорируется, в случае применения параметра extended
sizeне обязательный параметр. Для указания размера запрашиваемой области можно добавить к запросу параметр size=XX, где XX - целое число, обозначающее размер области в километрах. Если число указано неверно, или превышает максимальный размер, будет возвращена область максимального размера
extendedне обязательный параметр. Чтобы получить данные в расширенном формате, к запросу следует добавить параметр extended=1

параметры, помеченные жирным - обязательны

Пример:
/apiservice?lng=37.5&lat=55.7&apikey=1234-abc-5678de

Описание данных, предоставляемых по запросу сервисом API

В ответ на запрос предоставляется сжатый файл в KMZ формате, готовый для использования в соответствующих сервисах Google и других программных интерфейсах. При этом по запросу предоставляется базовый набор полей или расширенный. Базовый набор полей полностью соответствует спецификации KML, расширенный разобран ниже.

Пример разархивации KMZ файла на Java

// Создание потока, для разархивации данных в файле                            
BufferedInputStream is =new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
byte data[] = new byte[BUFFER];

// Создание потока, для чтения данных из файла
FileOutputStream fos = new FileOutputStream(destFile);

// Создание потока, принимающего зарархивированные данные
BufferedOutputStream dest =new BufferedOutputStream(fos, BUFFER);

// Чтение файла
while ((currentByte = is.read(data, 0, BUFFER)) != -1)
{
    // Запись данных в поток
    dest.write(data, 0, currentByte);
}
                            

Аналогичные стандартные библиотеки присутствуют в других языках программирования, предназначенные для разархивирования сжатых файлов алгоритмом ZIP. (PHP.NET C#PythonRuby)

Расширенный формат данных

В случае использования параметра extended=1 в запросе, в результирующий файл будет добавлена секция расширенных данных, в соотвествии со спецификацией: https://developers.google.com/kml/documentation/extendeddata.

Список дополнительных параметров:

ПараметрОписание
qualityCodeиндекс качества дороги, число от 1 (хорошее качество) до 4 (очень плохое)
internalQualityCodeвнутренний индекс качества дороги. Может принимать значения от 10 до 40. Чем выше индекс, тем хуже качество
qualityDataCountобщее количество оценок данного участка дороги
qualityValueChangeDateдата (дд.мм.гггг), когда произошло последнее изменение оценки качества
lastDateдата поступления последней оценки участка

Пример:
/apiservice?lng=37.5&lat=55.7&apikey=1234-abc-5678d&size=10&extended=1

Пример данных, получаемых при запросе

                                <?xml version="1.0" encoding="UTF-8"?>
                                <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
                                <Document>
                                    <Style id="u1"><LineStyle><outline>0</outline><width>5</width><color>7d00ff00</color></LineStyle></Style>
                                    <Style id="u2"><LineStyle><outline>0</outline><width>5</width><color>7d00ffff</color></LineStyle></Style>
                                    <Style id="u3"><LineStyle><outline>0</outline><width>5</width><color>7d0000aa</color></LineStyle></Style>
                                    <Style id="u4"><LineStyle><outline>0</outline><width>5</width><color>ad0000ff</color></LineStyle></Style>
                                    <Placemark>
                                        <styleUrl>#u1</styleUrl>
                                        <LineString>
                                        <coordinates>37.394291620998914,55.71415842146296
                                        37.393773,55.714077</coordinates></LineString>
                                        <ExtendedData>
                                            <Data name="qualityCode">
                                            <value>1</value></Data>
                                            <Data name="qualityDataCount">
                                            <value>1</value></Data>
                                            <Data name="qualityValueChangeDate">
                                            <value>15.5.2012</value></Data>
                                            <Data name="lastDate">
                                            <value>15.5.2012</value></Data>
                                        </ExtendedData>
                                    </Placemark>
                                </Document></kml>
                            

Пример отображения полученных данных на картах Google

Необходимо разместить полученный файл, в примере это apiservice.kmz, на ресурсе, доступном по HTTP, в примере это my-site.ru.

Фрагмент кода на javascript:

                                function initialize() {
                                    // Задание координат центра карты
                                    var mapCenter= new google.maps.LatLng(55.7, 37.5);
                                    // Параметры карты (масштаб, центр, тип карты - в данном случае карта-схема)
                                    var myOptions = {
                                        zoom: 11,
                                        center: mapCenter,
                                        mapTypeId: google.maps.MapTypeId.ROADMAP
                                    }
                                 
                                    // Создание объекта карты. Отображение карты будет осуществляться в элементе DIV с ID map_canvas
                                    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
                                
                                    // Нанесение на карту слоя “качество дорог”, в формате KMZ, из заранее размещенного на вашем сайте файла
                                    var myLayer = new google.maps.KmlLayer('http://my-site.ru/apiservice.kmz');
                                
                                    // Визуалиpация слоя KMZ
                                    myLayer.setMap(map);
                                }
                            

Работающий пример.

Пример обработки данных с расширенными полями

Пример приведен на языке Java в рамках белого списка классов и в стилистике сервлетов Google App Engine.

Фрагмент объявления класса:


public class RoadSegment {
   
   // Координаты участка дороги (две точки, долгота и широта, в градусах)
   private double lng1;
   private double lat1;
   private double lng2;
   private double lat2;

   // Атрибуты участка дороги
   private long qualityCode;
   private long qualityDataCount;
   private String qualityValueChangeDate;
   private String lastDate;
   
   // Парсинг строки с координатами точек участка дороги
   public void setCoordinates(String s) {
       String[] a=s.split("[,\n]");
       lng1=Double.parseDouble(a[0]);
       lat1=Double.parseDouble(a[1]);
       lng2=Double.parseDouble(a[2]);
       lat2=Double.parseDouble(a[3]);
   }
                            

Фрагмент процедуры обработки данных и создания экземпляра класса:

// Создание списка участков дороги из полученного XML
NodeList placemarkLst = doc.getElementsByTagName("Placemark");

// Создание экземпляра списка участков дороги в виде экземпляров класса, описанного выше
List<RoadSegment> roadSegments=new ArrayList<RoadSegment>();

// Парсинг участков дорог
for (int i=0; i<placemarkLst.getLength(); i++) {

    // Создание экземпляра класса “участок дороги”
    RoadSegment rs=new RoadSegment();

    // Добавление экземпляра в список
    roadSegments.add(rs);
    Element placemark = (Element) placemarkLst.item(i);

    // Парсинг координат участка            
    rs.setCoordinates(placemark.getElementsByTagName("coordinates").item(0).getTextContent());

    // Парсинг “расширенных данных”
    NodeList dataLst = placemark.getElementsByTagName("Data");

    // Извлечение значений “расширеных данных”
    for (int j=0; j<dataLst.getLength(); j++) {
        Element data=(Element) dataLst.item(j);
        String paramName=data.getAttribute("name");
        String paramValue=data.getTextContent();

        // Запись значений “расширенных данных” в экземпляр класса “участок дороги”
        if (paramName.equals("qualityCode")) {
            rs.setQualityCode(paramValue);
        }
        if (paramName.equals("qualityDataCount")) {
            rs.setQualityDataCount(paramValue);
        }

    }
}
// Возврат списка участков дорог в виде списка классов
return roadSegments;       
                                    

Расшифровка ошибок сервера

ОшибкаОписание
ERROR 1001неверный формат запроса (см. пример выше)
ERROR 1002неверный ключ API
ERROR 1003исчерпана квота
ERROR 1004сервис временно не доступен
ERROR 1005 доступ к API заблокирован администратором

Квоты

Один запрос ограничен территорией в 10км2. Количество запросов на данные с расширенными полями не может превышать 24 итераций в сутки. Параметры квот могут быть индивидуально изменены. Для формирования запроса на индивидуальное изменение квот необходимо написать письмо по адресу info@rusdorogi.ru.

Полный текст примера разархивации KMZ файла на Java

import java.io.BufferedInputStream;  
import java.io.BufferedOutputStream;  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.util.Enumeration;  
import java.util.zip.ZipEntry;  
import java.util.zip.ZipFile;  
public class KMZUncompressExample  
{  
	static final int BUFFER = 2048;  

	public static void main(String[] args)  
	{  
		try  
		{  
			String inFileName = "apiservice.kmz";  
			String destinationDirectory ="";  
			File sourceZipFile = new File(inFileName);  
			File unzipDestinationDirectory = new File(destinationDirectory);  
			ZipFile zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);  
			Enumeration zipFileEntries = zipFile.entries();  

			while (zipFileEntries.hasMoreElements())  
			{  
				ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();  
				String currentEntry = entry.getName();  
				File destFile =new File(unzipDestinationDirectory, currentEntry);  
				File destinationParent = destFile.getParentFile();  
				destinationParent.mkdirs();  
				if (!entry.isDirectory())  
				{  
					BufferedInputStream is =new BufferedInputStream(zipFile.getInputStream(entry));  
					int currentByte;  
					byte data[] = new byte[BUFFER];  

					FileOutputStream fos = new FileOutputStream(destFile);  
					BufferedOutputStream dest =new BufferedOutputStream(fos, BUFFER);  

					while ((currentByte = is.read(data, 0, BUFFER)) != -1)  
					{  
						dest.write(data, 0, currentByte);  
					}  
					dest.flush();  
					dest.close();  
					is.close();  
				}  
			}  
			zipFile.close();  
		}  
		catch (IOException ioe)  
		{  
			ioe.printStackTrace();  
		}  
	}  
}  
                            

Полный текст примера отображения полученных данных на картах Google

Необходимо разместить полученный файл, в примере это apiservice.kmz, на ресурсе, доступном по HTTP, в примере это my-site.ru.

                                 <!DOCTYPE html>
                                <html>
                                <head>
                                <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
                                <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
                                <title>Google Maps JavaScript API v3 пример: KmlLayer</title>
                                <link href="/" rel="stylesheet" type="text/css" />
                                <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
                                <script type="text/javascript">
                                function initialize() {
                                 var mapCenter= new google.maps.LatLng(55.7, 37.5);
                                 var myOptions = {
                                   zoom: 11,
                                   center: mapCenter,
                                   mapTypeId: google.maps.MapTypeId.ROADMAP
                                 }
                                
                                var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
                                var myLayer = new google.maps.KmlLayer('http://my-site.ru/apiservice.kmz');
                                 myLayer.setMap(map);
                                }
                                </script>
                                </head>
                                <body onload="initialize()">
                                 <div id="map_canvas"></div>
                                </body>
                                </html>
                             

Полный текст примера обработки данных с расширенными полями

Пример приведен на языке Java в рамках белого списка классов и в стилистике сервлетов Google App Engine.

                                 public class RoadSegment {
                                	private double lng1;
                                	private double lat1;
                                	private double lng2;
                                	private double lat2;
                                	private long qualityCode;
                                	private long qualityDataCount;
                                	private String qualityValueChangeDate;
                                	private String lastDate;
                                	
                                	public void setCoordinates(String s) {
                                		String[] a=s.split("[,\n]");
                                		lng1=Double.parseDouble(a[0]);
                                		lat1=Double.parseDouble(a[1]);
                                		lng2=Double.parseDouble(a[2]);
                                		lat2=Double.parseDouble(a[3]);
                                	}
                                	public long getQualityCode() {
                                		return qualityCode;
                                	}
                                	public void setQualityCode(String qualityCode) {
                                		this.qualityCode = Integer.parseInt(qualityCode);
                                	}
                                	public long getQualityDataCount() {
                                		return qualityDataCount;
                                	}
                                	public void setQualityDataCount(String qualityDataCount) {
                                		this.qualityDataCount = Integer.parseInt(qualityDataCount);
                                	}
                                	public String getQualityValueChangeDate() {
                                		return qualityValueChangeDate;
                                	}
                                	public void setQualityValueChangeDate(String qualityValueChangeDate) {
                                		this.qualityValueChangeDate = qualityValueChangeDate;
                                	}
                                	public String getLastDate() {
                                		return lastDate;
                                	}
                                	public void setLastDate(String lastDate) {
                                		this.lastDate = lastDate;
                                	}
                                	public double getLng1() {
                                		return lng1;
                                	}
                                	public double getLat1() {
                                		return lat1;
                                	}
                                	public double getLng2() {
                                		return lng2;
                                	}
                                	public double getLat2() {
                                		return lat2;
                                	}
                                }
                                
                                public List<RoadSegment> parseXmlInputStream(ByteArrayInputStream bais) 
                                        throws IOException, ParserConfigurationException, SAXException {
                                   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                                   DocumentBuilder db = dbf.newDocumentBuilder();
                                   Document doc = db.parse(bais);
                                   doc.getDocumentElement().normalize();
                                   NodeList placemarkLst = doc.getElementsByTagName("Placemark");
                                   List<RoadSegment> roadSegments=new ArrayList<RoadSegment>();
                                
                                   for (int i=0; i<placemarkLst.getLength(); i++) {
                                       RoadSegment rs=new RoadSegment();
                                       roadSegments.add(rs);
                                       Element placemark = (Element) placemarkLst.item(i);
                                
                                       rs.setCoordinates(placemark.getElementsByTagName("coordinates")
                                            .item(0).getTextContent());
                                       NodeList dataLst = placemark.getElementsByTagName("Data");
                                       for (int j=0; j<dataLst.getLength(); j++) {
                                           Element data=(Element) dataLst.item(j);
                                           String paramName=data.getAttribute("name");
                                           String paramValue=data.getTextContent();
                                           if (paramName.equals("qualityCode")) {
                                               rs.setQualityCode(paramValue);
                                           }
                                           if (paramName.equals("qualityDataCount")) {
                                               rs.setQualityDataCount(paramValue);
                                           }
                                           if (paramName.equals("qualityValueChangeDate")) {
                                               rs.setQualityValueChangeDate(paramValue);
                                           }
                                           if (paramName.equals("lastDate")) {
                                               rs.setLastDate(paramValue);
                                           }
                                       }
                                   }
                                   return roadSegments;
                                }