Class: NotamConnector
- Inherits:
-
Object
- Object
- NotamConnector
- Includes:
- ConnectionBase
- Defined in:
- src/notam_connector.rb
Constant Summary collapse
- PARAMS =
{ key: { required: true, name: 'KEY', desc: 'ключ авторизации. текстовая комбинация букв и цифр, позволяющая идентифицировать запрос. Наличие параметра в запросе является строго обязательным' }, request: { name: 'REQUEST', desc: 'Метод основного запроса', values: %w[NOTAM ROUTE] }, charset: { name: 'CHARSET', values: %w[UTF-8 win-1251 KOI8-R KOI8-U], desc: 'кодировка символов в сообщении.' }, date_from: { name: 'DATEFROM', example: '2020-11-16T04:25:03Z', desc: '(ISO 8601 UTC) начало интересуемого интервала времени. Временная зона — UTC. Опциональный параметр, если отсутствует, то нижнее ограничение не учитывается.' }, date_to: { name: 'DATETO', example: '2020-11-16T04:25:03Z', desc: '(ISO 8601 UTC) окончание интересуемого интервала времени. Временная зона — UTC. Опциональный параметр, если отсутствует, то верхнее ограничение не учитывается.' }, points: { name: 'POINTS', example: 'XXXX XXXX', desc: 'список маршрутных точек и аэродромов, через которые осуществляется полет. Точки/Аэродромы указываются в кодах ICAO (четырехбуквенный, маска кода XXXX). Коды Точек/Аэродромов друг от друга отделяются пробелом. Вместо кодов ICAO можно использовать ключевое слово ALL. Данное слово указывает серверу выполнить выгрузку всей имеющейся БД НОТАМ. ' }, n_points: { name: 'POINTS', example: 'SNNNN/YYAAAA SNNNN/YYAAAA', desc: 'список НОТАМ, где S – серия НОТАМ, NNNN – номер НОТАМ, YY – год НОТАМ, AAAA – четырехбуквенный код аэродрома (поле А).' }, format: { name: 'FORMAT', values: %w[NOTAM TEXT PIB BRIEFING RESTRICTION AIRWAYS CLOSED REGLAMENT TEMPORARY SNOWTAM RECEIVED DANGERAREA DB DB+ SITE OBSTACLE], desc: 'формат представления сообщений. Опционально, если не указан, то сообщения передаются в формате NOTAM.' }, options: { name: 'OPTIONS', type: Array[String], desc: 'Дополнительные параметры ', values: { '': '', ADDNOTAM: 'добавляет текст НОТАМ', LISTID: 'возврящает только номера НОТАМ', ADDGEOMETRY: 'добавляет геометрию к ограничениям НОТАМ', }}, # request: 'ROUTE REQUEST' specific dep: { name: 'DEP', example: 'XXXX XXXX', desc: 'Аэропорт вылета' }, arr: { name: 'ARR', example: 'XXXX XXXX', desc: 'Аэропорт посадки' }, alt: { name: 'ALT', example: 'XXXX XXXX', desc: 'Запасные аэродромы' }, aircraft: { name: 'AIRCRAFT', example: 'A320 RA-12345', desc: 'Один тип воздушного судна и регистрационный номер' }, route: { name: 'ROUTE', example: '413224N0624236E 413648N0674155E 423314N0685725E', desc: 'Маршрут' }, airways: { name: 'AIRWAYS', example: 'L412 G313', desc: 'Авиатрассы' }, ralt: { name: 'RALT', example: 'XXXX XXXX', desc: 'Аэродромы на маршруте (RLAT,TALT)' }, flightlevel: { name: 'FLIGHTLEVEL', example: '270 100', desc: 'Эшелон' }, composition: { name: 'COMPOSITION', example: 'ALL', desc: 'Состав' }, lang: { name: 'LANG', values: %w[RU EN RU+EN EN+RU ALL], desc: 'язык НОТАМОВ. RU+EN/EN+RU (только для формата PIB)' }, type: { name: 'TYPE', values: %w[AIP CAI MVL MO OMIT], desc: 'база данных, по которой требуется выполнить запрос.В зависимости от объема информации (полю POINTS присвоено значения ALL) параметр может игнорироваться и в ответ включаются все НОТАМ на заданном языке.' }, compress: { name: 'COMPRESS', desc: '(всегда GZIP) флаг, указывающий, сжимать-ли ответ.', values: { TEXT: 'текст ответа не подвергается обработке', ZIP: 'ответ приходит в виде zip-архива. Текст NOTAM/PIB содержится в файле notam.txt/notam.pib', COMPRESS: 'для сжатия/распаковки используются компоненты qCompress/qUncompress', GZIP: 'ответ приходит в виде gzip-архива' }} }
- ERRORS =
{ 0 => 'The FROM is empty', 1 => 'FROM: found a non-numeric character', 2 => 'FROM: month out of range', 3 => 'FROM: day out of range', 4 => 'FROM: hours out of range', 5 => 'FROM: minutes out of range', 6 => 'The TO is empty', 7 => 'TO: found a non-numeric character', 8 => 'TO: month out of range', 9 => 'TO: day out of range', 10 => 'TO: hours out of range', 11 => 'TO: minutes out of range', 12 => 'Interval boundaries are set incorrectly', 13 => 'List of points is empty', 14 => 'Points must be described with four characters', 15 => 'Non-alphabetic character found in points', 16 => 'Format not specified', 17 => 'Language not specified', 18 => 'Information type not specified', 19 => 'Charset not specified', 20 => 'Compress not specified', 21 => 'Invalid Format', 22 => 'Invalid Language', 23 => 'Invalid Information type', 24 => 'Invalid Compress', 25 => 'Access is denied', 26 => "Departure airport not specified", 27 => "Arrival airport not specified", 28 => "", 29 => "DEP must be described with four characters", 30 => "Non-alphabetic character found in DEP", 31 => "", 32 => "ARR must be described with four characters", 33 => "Non-alphabetic character found in ARR", 34 => "List of ALT is empty", 35 => "Each ALT must be described by four characters", 36 => "Non-alphabetic character found in ALT", 37 => "", 38 => "Each RALT must be described by four characters", 39 => "Non-alphabetic character found in RALT", 40 => "Flight route not specified", 41 => "The coordinate description format is broken", 42 => "Duplicate codes detected", 43 => "There is no guide to ATC zones", 44 => "The flight level is not set or set incorrectly", 45 => "The composition of the PIB is not specified", 46 => "The base language for messages is not defined", 47 => "Unknown aircraft type" }
Instance Method Summary collapse
-
#initialize(server, key) ⇒ NotamConnector
constructor
A new instance of NotamConnector.
- #query(params) ⇒ Object
Methods included from ConnectionBase
#broadcast, #init, #init_connect, #init_core, #shutdown
Constructor Details
#initialize(server, key) ⇒ NotamConnector
Returns a new instance of NotamConnector.
96 |
# File 'src/notam_connector.rb', line 96 def initialize(server, key)=(@server = server; @key = key) |
Instance Method Details
#query(params) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'src/notam_connector.rb', line 98 def query(params) params[:date_from] ||= Time.now.utc params[:date_to] ||= Time.parse("2099-12-31").utc params[:compress] = 'GZIP' # ISO 8601 UTC params[:date_from] = Time.parse(params[:date_from]) if params[:date_from].is_a? String params[:date_to] = Time.parse(params[:date_to]) if params[:date_to].is_a? String # Notam server time format params[:date_from] = params[:date_from].strftime('%Y%m%d-%H%M%S') # '20210910-144300' params[:date_to] = params[:date_to].strftime('%Y%m%d-%H%M%S') # '20210910-230000' if(params[:type] == 'OMIT') params.delete(:type) end request = [ "#{params[:request]} REQUEST", # 'NOTAM REQUEST', # Первая строка заголовка - «NOTAM REQUEST\n» "CHARSET #{params[:charset]}", # Вторая строка Заголовка - «CHARSET <encoding>\n» '', # Символ окончания заголовка «\n» - пустая строка. "KEY #{@key}" ] otl_current_span do span_context = OpenTelemetry::Trace.current_span.context trace_id = span_context.trace_id.unpack1('H*') span_id = span_context.span_id.unpack1('H*') trace_flags = format('%02x', span_context.trace_flags.instance_eval{ @flags }) # Two-digit hex for trace flags (e.g., sampled) traceparent = "00-#{trace_id}-#{span_id}-#{trace_flags}" request << "TRACEPARENT #{traceparent}" end request += params.except(:charset, :key, :parse, :request) .transform_values { |v| v.is_a?(Array) ? v.join(' ') : v } .map { |n, v| raise "parameter not found: #{n.to_sym}" unless PARAMS[n.to_sym] "#{PARAMS[n.to_sym][:name]} #{v}" } request = "#{request.join("\n")}\n" otl_span(:request, request:) do |span| ip,port = @server.split(':') init(ip, port, :connect) do |task| # Первые 4 байта: размер запроса, порядок байт - обратный (@current_stream << [request.size].pack('L<') << request).flush # Если в запросе не найдено ошибок, то возвращается -1. code = @current_stream.read_exactly(4).unpack1('l<') raise [code, ERRORS[code]].to_s unless code == -1 size = @current_stream.read_exactly(4).unpack1('L<') = @current_stream.read_exactly(size).force_encoding(Encoding::UTF_8) span&.add_event("response received", attributes: { event: 'Success', message: "messages size:#{.size}" }.transform_keys(&:to_s) ) begin if params[:compress] == 'GZIP' && !.empty? gz = Zlib::GzipReader.new StringIO.new() = gz.read end rescue =>e span&.add_event("GZIP exception", attributes: { event: 'Error', message: "messages:#{[0..10000]}" }.transform_keys(&:to_s) ) raise end span&.add_event("response un Ziped", attributes: { event: 'Success', message: "messages size:#{.size}" }.transform_keys(&:to_s) ) response = NotamFormatter.format , params[:format], params[:request] span&.add_event("response formatted", attributes: { event: 'Success', message: "messages size:#{.size}" }.transform_keys(&:to_s) ) if params[:parse] == 'Y' Parser. response[:messages], params[:format] span&.add_event("response parsed", attributes: { event: 'Success', message: "messages size:#{.size}" }.transform_keys(&:to_s) ) end response end rescue =>e otl_current_span { _1.add_attributes(response:) } rescue nil raise end end |