Обрабатывать сообщения AVL с йодом

Сейчас я разрабатываю какой-то парсер для сообщений Skypatrol TT8750+, и мой многопоточный TCP-сервер работает. Проблема в том, что это не очень хороший подход, если одновременно подключено много устройств. Я использую йод, но я не могу заставить работать какой-то код, который мне дали. Моя цель - сначала получить сообщение размером 33 байта для идентификации устройства, а затем начать получать сообщения размером 86 байтов с информацией об автомобиле.

require 'iodine'

# define the protocol for our service
class TT8750plus
  @timeout = 10
  def on_open
    puts "New Connection Accepted."
    # this file is just for testing purposes.
    t = Time.now.strftime("%d-%m-%Y %H%M")
    file_name = t + '.txt'
    @out_file = File.new(file_name, "w+")

    # a rolling buffer for fragmented messages
    @expecting = 33
    @msg = ""
  end

  def on_message buffer
    length = buffer.length
    pos = 0
    while length >= @expecting
      @msg << (buffer[pos, @expecting])
      @out_file.puts(@msg.unpack('H*')[0])
      length -= @expecting
      po += @expecting
      @expecting = 86
      @msg.clear
    end
    if(length > 0)
      @msg << (buffer[pos, length])
      @expecting = 86 - length
    end
    puts @msg
  end

  def on_close
    @out_file.close
  end
end
# create the service instance
Iodine.listen 12050, TT8750plus
# start the service
Iodine.start

И эта ошибка появляется в каждом сообщении

New Connection Accepted.
Iodine caught an unprotected exception - NoMethodError: undefined method `+' for nil:NilClass
iodineServer.rb:26:in `on_message'
iodineServer.rb:1:in `on_data'Iodine caught an unprotected exception - NoMethodError: undefined method `+' for nil:NilClass

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

0021000a0800000000000120202020202038363332383630323034333433373020
0021000a08000000000001202020202020383633323836303230343334333730200056000a08100020202020202038363332383630323034333433373020014b0000

И это первые две строки из многопоточной реализации

0021000a0800000000000120202020202038363332383630323034333433373020
0056000a08100020202020202038363332383630323034333433373020000b00000013090044709bfb8109e400000000001100000000000067eb11090c1512012e970020000000000005000000000005000000000007 
0056000a08100020202020202038363332383630323034333433373020010b00000013090044709bfb8109e400000000001200000000000067eb11090c1512042e970020000000000005000000000005000000000008

1 ответ

Решение

Это похоже на вариант непроверенного кода, который я выложил ранее.

Кажется, проблема в орфографической ошибке в коде (возможно, в моем?).

po += ... должно было pos += ...

require 'iodine'

# define the protocol for our service
class TT8750plus
  @timeout = 10
  def on_open
    puts "New Connection Accepted."
    # this file is just for testing purposes.
    t = Time.now.strftime("%d-%m-%Y %H%M")
    file_name = t + '.txt'
    @out_file = File.new(file_name, "w+")

    # a rolling buffer for fragmented messages
    @expecting = 33
    @msg = ""
  end

  def on_message buffer
    length = buffer.length
    pos = 0
    while length >= @expecting
      @msg << (buffer[pos, @expecting])
      @out_file.puts(@msg.unpack('H*')[0])
      length -= @expecting
      pos += @expecting # the spelling mistake was here
      @expecting = 86
      puts "wrote:", @msg
      @msg.clear
    end
    if(length > 0)
      @msg << (buffer[pos, length])
      @expecting = 86 - length
    end
    puts("Waiting for more data:", @msg) unless @msg.empty?
  end

  def on_close
    @out_file.close
  end
end
# create the service instance
Iodine.listen 12050, TT8750plus
# start the service
Iodine.start

Опять же, не имея эмуляции для Skypatrol TT8750+, я не могу протестировать код. Но должна быть возможность следить за сообщениями об ошибках, чтобы медленно отследить эти типы проблем.

PS

Для защиты от исключений рассмотрите возможность использования Ruby:

begin
    # code
rescue => e
    # oops something happened. i.e.
    puts e.message, e.backtrace
end

то есть on_message Метод может выглядеть так:

  def on_message buffer
   begin
    length = buffer.length
    pos = 0
    while length >= @expecting
      @msg << (buffer[pos, @expecting])
      @out_file.puts(@msg.unpack('H*')[0])
      length -= @expecting
      pos += @expecting # the spelling mistake was here
      @expecting = 86
      @msg.clear
    end
    if(length > 0)
      @msg << (buffer[pos, length])
      @expecting = 86 - length
    end
    puts @msg unless @msg.empty? # print leftovers for testing...?
   rescue => e
     # oops something happened. React
     puts e.message, e.backtrace
   end
  end

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

Другие вопросы по тегам