anchor.diff:  handle_info({uplink, _Node, _Vars0}, #state{publish_uplinks=PatPub}=State)
           when PatPub == undefined; PatPub == ?EMPTY_PATTERN ->
       {noreply, State};
  -handle_info({uplink, _Node, Vars0}, #state{conn=Connector, pid=undefined}=State) ->
  -    case connect(Connector) of
  -        {ok, ConnPid} ->
  -            {noreply, handle_uplink(Vars0, State#state{pid=ConnPid})};
  -        {error, _} ->
  -            % will try to reconnect upon next uplink
  -            {noreply, State#state{pid=undefined}}
  -    end;
  -handle_info({uplink, _Node, Vars0}, #state{pid=ConnPid}=State) when is_pid(ConnPid) ->
  -    {noreply, handle_uplink(Vars0, State)};
  +handle_info({uplink, _Node, Vars0}, #state{conn=Conn}=State) ->
  +    case ensure_connected(State) of
  +        {ok, State2} ->
  +            {noreply, handle_uplink(Vars0, State2)};
  +        {error, State2} ->
  +            lager:warning("Connector ~p not connected, uplink lost", [Conn#connector.connid]),
  +            {noreply, State2}
  +    end;
   
   handle_info({event, _Node, _Vars0}, #state{publish_events=PatPub}=State)
           when PatPub == undefined; PatPub == ?EMPTY_PATTERN ->
       {noreply, State};
  -handle_info({event, _Node, Vars0}, #state{conn=Connector, pid=undefined}=State) ->
  -    case connect(Connector) of
  -        {ok, ConnPid} ->
  -            {noreply, handle_event(Vars0, State#state{pid=ConnPid})};
  -        {error, _} ->
  -            {noreply, State#state{pid=undefined}}
  -    end;
  -handle_info({event, _Node, Vars0}, #state{pid=ConnPid}=State) when is_pid(ConnPid) ->
  -    {noreply, handle_event(Vars0, State)};
  -
  -handle_info({gun_up, C, http}, State=#state{pid=C}) ->
  -    {noreply, State};
  +handle_info({event, _Node, Vars0}, #state{conn=Conn}=State) ->
  +    case ensure_connected(State) of
  +        {ok, State2} ->
  +            {noreply, handle_event(Vars0, State2)};
  +        {error, State2} ->
  +            lager:warning("Connector ~p not connected, event lost", [Conn#connector.connid]),
  +            {noreply, State2}
  +    end;
  +
  +handle_info({gun_up, C, http}, State=#state{pid={C,_}}) ->
  +    {noreply, #state{ready=true}=State};
   handle_info({gun_down, C, _Proto, _Reason, Killed, Unprocessed},
  -        State=#state{pid=C, streams=Streams}) ->
  -    {noreply, State#state{streams=remove_list(remove_list(Streams, Killed), Unprocessed)}};
  +        State=#state{pid={C,_}, streams=Streams}) ->
  +    {noreply, State#state{ready=false, streams=remove_list(remove_list(Streams, Killed), Unprocessed)}};
   handle_info({gun_response, C, StreamRef, Fin, 401, Headers},
  -        State=#state{pid=C, streams=Streams}) ->
  +        State=#state{pid={C,_}, streams=Streams}) ->
       State3 =
           case proplists:get_value(<<"www-authenticate">>, Headers) of
               undefined ->
  
positive.code:             ok
      end,
      {noreply, fin_stream(StreamRef, Fin, State)};
  handle_info({gun_data, C, StreamRef, Fin, _Data}, State=#state{pid=C}) ->
      {noreply, fin_stream(StreamRef, Fin, State)};
  
  handle_info({'DOWN', _MRef, process, C, Reason}, #state{conn=#connector{connid=ConnId}, pid=C}=State) ->
      lager:warning("Connector ~s disconnected: ~p", [ConnId, Reason]),
      % will try to reconnect when new uplink arrives
      {noreply, State#state{pid=undefined}};
  handle_info(Unknown, State) ->
      lager:debug("Unknown message: ~p", [Unknown]),
      {noreply, State}.
  
  terminate(normal, #state{conn=#connector{connid=ConnId}, pid=C}) ->
      lager:debug("Connector ~s terminated: normal", [ConnId]),
      disconnect(C);
  terminate(Reason, #state{conn=#connector{connid=ConnId}, pid=C}) ->
      lager:warning("Connector ~s terminated: ~p", [ConnId, Reason]),
      disconnect(C).
  
  code_change(_OldVsn, State, _Extra) ->
      {ok, State}.
  
  connect(#connector{uri= <<"http:">>}) ->
      {ok, undefined};
  connect(#connector{connid=ConnId, uri=Uri}) ->
      lager:debug("Connecting ~s to ~s", [ConnId, Uri]),
      {ok, ConnPid} =
          case http_uri:parse(binary_to_list(Uri), [{scheme_defaults, [{http, 80}, {https, 443}]}]) of
              {ok, {http, _UserInfo, HostName, Port, _Path, _Query}} ->
                  gun:open(HostName, Port);
              {ok, {https, _UserInfo, HostName, Port, _Path, _Query}} ->
                  gun:open(HostName, Port, #{transport=>ssl})
          end,
      MRef = monitor(process, ConnPid),
      case gun:await_up(ConnPid, 5000, MRef) of
          {ok, Protocol} ->
              lager:debug("~s connected to ~s (~p)", [ConnId, Uri, Protocol]),
              {ok, ConnPid};
          {error, Reason} ->
              demonitor(MRef),
              lager:error("~s failed to connect to ~p ~p", [ConnId, Uri, Reason]),
              {error, Reason}
      end.
  
  disconnect(undefined) ->
      ok;
  disconnect(ConnPid) ->
      gun:close(ConnPid).
  
  handle_uplink(Vars0, State) when is_list(Vars0) ->
  
negative.code: init([#connector{connid=Id, app=App,
          publish_uplinks=PubUp, publish_events=PubEv, name=UserName, pass=Password}=Conn]) ->
      ok = pg2:join({backend, App}, self()),
      try
          {ok, #state{conn=Conn, pid=create_gun(Conn), ready=false, streams=#{},
              publish_uplinks=lorawan_connector:prepare_filling(PubUp),
              publish_events=lorawan_connector:prepare_filling(PubEv),
              auth=lorawan_connector:prepare_filling([UserName, Password]),
  