anchor.diff:      {error, Reason} ->
         em_logger:info("Error: ~s", [Reason]),
         {noreply, State, ?TIMEOUT}
  -  end;
  -handle_info({tcp, _, ?TRASH}, State=#state{socket=Socket, transport=Transport}) ->
  -  Transport:setopts(Socket, [{active, once}]),
  -  {noreply, State, ?TIMEOUT};
  -handle_info({tcp, Socket, Data}, State=#state{protocol = Protocol, socket=Socket, transport=Transport, deviceId = 0}) when byte_size(Data) > 1 ->
  -  Transport:setopts(Socket, [{active, once}]),
  -
  -  em_logger:info("[packet] unit: ip = '~s' data: ~s", [em_hardware:resolve(Socket), Data]),
  -  case parse(Data) of
  -    {ok, Imei, PositionModel} ->
  -      em_logger:info("[packet] unit: ip = '~s' imei = '~s' message: ~w", [em_hardware:resolve(Socket), Imei, PositionModel]),
  -      case em_data_manager:get_device_by_uid(Imei) of
  -        {error, _Reason} ->
  -          em_logger:info("[packet] unit: ip = '~s' unknown device with imei = '~s'", [em_hardware:resolve(Socket), Imei]),
  -          {stop, normal, State};
  -        {ok, Object} ->
  -          em_proc:registry(Object#device.id, self()),
  -          Position = PositionModel#position{
  -            deviceId = Object#device.id,
  -            protocol = atom_to_binary(Protocol, utf8),
  -            attributes = maps:merge(PositionModel#position.attributes, #{
  -              ?KEY_IP => em_hardware:resolve(Socket)
  -            })
  -          },
  -          em_logger:info("save message => unit: ip = '~s' id = '~w' imei = '~s' position: ~w", [em_hardware:resolve(Socket), Object#device.id, Imei, Position]),
  -          em_data_manager:create_position(Object#device.id, Position),
  -          {noreply, State#state{deviceId = Object#device.id}, ?TIMEOUT}
  -      end;
  -    {error, Message} ->
  -      em_logger:info("ERROR: ~s", [Message]),
  -      {stop, normal, State}
  -  end;
  -handle_info({tcp, Socket, Data}, State=#state{protocol = Protocol, socket=Socket, transport=Transport, deviceId = DeviceId}) when byte_size(Data) > 1 ->
  -  Transport:setopts(Socket, [{active, once}]),
  -
  -  em_logger:info("[packet] unit: ip = '~s' data: ~s", [em_hardware:resolve(Socket), Data]),
  -  case parse(Data) of
  -    {ok, Imei, PositionModel} ->
  -      em_logger:info("[packet] unit: ip = '~s' imei = '~s' message: ~w", [em_hardware:resolve(Socket), Imei, PositionModel]),
  -      Position = PositionModel#position{
  -        deviceId = DeviceId,
  -        protocol = atom_to_binary(Protocol, utf8),
  -        attributes = maps:merge(PositionModel#position.attributes, #{
  -          ?KEY_IP => em_hardware:resolve(Socket)
  -        })
  -      },
  -      em_logger:info("save message => unit: ip = '~s' id = '~w' imei = '~s' position: ~w", [em_hardware:resolve(Socket), DeviceId, Imei, Position]),
  -      em_data_manager:create_position(DeviceId, Position),
  -      {noreply, State, ?TIMEOUT};
  -    {error, Message} ->
  -      em_logger:info("ERROR: ~s", [Message]),
  -      {stop, normal, State}
  -  end;
  -handle_info({tcp_closed, _Socket}, State) ->
  -  {stop, normal, State};
  -handle_info({tcp_error, _, Reason}, State) ->
  -  {stop, Reason, State};
  -handle_info(timeout, State) ->
  -  {stop, normal, State};
  -handle_info(_Info, State) ->
  -  {stop, normal, State}.
  -%%handle_info(_Info, State) ->
  -%%  {noreply, State}.
  -
  -%%--------------------------------------------------------------------
  -%% @private
  -%% @doc
  -%% This function is called by a gen_server when it is about to
  -%% terminate. It should be the opposite of Module:init/1 and do any
  -%% necessary cleaning up. When it returns, the gen_server terminates
  -%% with Reason. The return value is ignored.
  -%%
  -%% @spec terminate(Reason, State) -> void()
  -%% @end
  -%%--------------------------------------------------------------------
  --spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
  -    State :: #state{}) -> term()).
  -terminate(_Reason, _State) ->
  -  ok.
  -
  -%%--------------------------------------------------------------------
  -%% @private
  -%% @doc
  -%% Convert process state when code is changed
  -%%
  -%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
  -%% @end
  -%%--------------------------------------------------------------------
  --spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
  -    Extra :: term()) ->
  -  {ok, NewState :: #state{}} | {error, Reason :: term()}).
  -code_change(_OldVsn, State, _Extra) ->
  -  {ok, State}.
  -
  -%%%===================================================================
  -%%% Internal functions
  -%%%===================================================================
  +  end.
  +
   do_encode_command(UniqueId, #command{type = ?TYPE_POSITION_SINGLE}) ->
     {ok, do_format_command(UniqueId, <<"Q">>, <<"A10">>)};
   do_encode_command(UniqueId, #command{type = ?TYPE_ENGINE_STOP}) ->
  
positive.code:   ok = Transport:setopts(Socket, [{active, once}]),
    Protocol = proplists:get_value(protocol, Opts),
    gen_server:enter_loop(?MODULE, [],
      #state{protocol = Protocol, socket=Socket, transport=Transport}, ?TIMEOUT).
  %%{ok, #state{}}.
  
  %%--------------------------------------------------------------------
  
negative.code: 
  do_format_command(UniqueId, DataId, Content) ->
    Length = 1 + byte_size(UniqueId) + 1 + byte_size(Content) + 5,
    Result = list_to_binary(io_lib:format("@@~s~w,~s,~s*", [DataId, Length, UniqueId, Content])),
    CheckSum = em_checksum:sum(Result),
    list_to_binary(io_lib:format("~s~2.16.0B\r\n", [Result, CheckSum])).
  
  
  do_process_data(State = #state{transport = _Transport, socket = Socket, protocol = Protocol, deviceId = 0}, Data) ->
    em_logger:info("[packet] unit: ip = '~s' data: ~s", [em_hardware:resolve(Socket), Data]),
    case parse(Data) of
      {ok, Imei, PositionModel} ->
        em_logger:info("[packet] unit: ip = '~s' imei = '~s' message: ~w", [em_hardware:resolve(Socket), Imei, PositionModel]),
        case em_data_manager:get_device_by_uid(Imei) of
          {error, _Reason} ->
            em_logger:info("[packet] unit: ip = '~s' unknown device with imei = '~s'", [em_hardware:resolve(Socket), Imei]),
            {stop, normal, State};
          {ok, Object} ->
            em_proc:registry(Object#device.id, self()),
            do_save_position(State#state{deviceId = Object#device.id}, Object#device.id, Imei, PositionModel)
        end;
      {error, Message} ->
        em_logger:info("ERROR: ~s", [Message]),
        {stop, normal, State}
    end;
  do_process_data(State = #state{transport = _Transport, socket = Socket, protocol = Protocol, deviceId = DeviceId}, Data) ->
    em_logger:info("[packet] unit: ip = '~s' data: ~s", [em_hardware:resolve(Socket), Data]),
    case parse(Data) of
      {ok, Imei, PositionModel} ->
        do_save_position(State, DeviceId, Imei, PositionModel);
      {error, Message} ->
        em_logger:info("ERROR: ~s", [Message]),
        {stop, normal, State}
    end.
  
  do_save_position(State = #state{socket = Socket, protocol = Protocol}, DeviceId, Imei, PositionModel) ->
    em_logger:info("[packet] unit: ip = '~s' imei = '~s' message: ~w", [em_hardware:resolve(Socket), Imei, PositionModel]),
    Position = PositionModel#position{
      deviceId = DeviceId,
      protocol = atom_to_binary(Protocol, utf8),
      attributes = maps:merge(PositionModel#position.attributes, #{
        ?KEY_IP => em_hardware:resolve(Socket)
      })
    },
    em_logger:info("save message => unit: ip = '~s' id = '~w' imei = '~s' position: ~w", [em_hardware:resolve(Socket), DeviceId, Imei, Position]),
    em_data_manager:create_position(DeviceId, Position),
    {noreply, State, ?TIMEOUT}.
  
  %% echo "20. meitrack"
  %% (echo -n -e "\$\$d138,123456789012345,AAA,35,60.000000,130.000000,120101122000,A,7,18,0,0,0,49,3800,24965,510|10|0081|4F4F,0000,000D|0010|0012|0963|0000,,*BF\r\n";) | nc -v localhost 5020
  