@Override
  public <T extends LwM2mResponse> void send(
      final UplinkRequest<T> request,
      final ResponseCallback<T> responseCallback,
      final ErrorCallback errorCallback) {
    // Create the CoAP request from LwM2m request
    final CoapClientRequestBuilder coapClientRequestBuilder =
        new CoapClientRequestBuilder(serverAddress, client);
    request.accept(coapClientRequestBuilder);
    // TODO manage invalid parameters
    // if (!coapClientRequestBuilder.areParametersValid()) {
    // responseCallback.onFailure(OperationResponse.failure(ResponseCode.INTERNAL_SERVER_ERROR,
    // "Request has invalid parameters.  Not sending."));
    // return;
    // }
    final Request coapRequest = coapClientRequestBuilder.getRequest();

    // Add CoAP request callback
    coapRequest.addMessageObserver(
        new AsyncRequestObserver<T>(coapRequest, responseCallback, errorCallback) {

          @Override
          public T buildResponse(final Response coapResponse) {
            // Build LwM2m response
            final LwM2mClientResponseBuilder<T> lwm2mResponseBuilder =
                new LwM2mClientResponseBuilder<T>(coapRequest, coapResponse);
            request.accept(lwm2mResponseBuilder);
            return lwm2mResponseBuilder.getResponse();
          }
        });

    // Send CoAP request asynchronously
    clientEndpoint.sendRequest(coapRequest);
  }
  @Override
  public <T extends LwM2mResponse> T send(final UplinkRequest<T> request, Long timeout) {
    // Create the CoAP request from LwM2m request
    final CoapClientRequestBuilder coapClientRequestBuilder =
        new CoapClientRequestBuilder(serverAddress, client);
    request.accept(coapClientRequestBuilder);
    // TODO manage invalid parameters
    // if (!coapClientRequestBuilder.areParametersValid()) {
    // return OperationResponse.failure(ResponseCode.INTERNAL_SERVER_ERROR,
    // "Request has invalid parameters.  Not sending.");
    // }
    final Request coapRequest = coapClientRequestBuilder.getRequest();

    // Send CoAP request synchronously
    final SyncRequestObserver<T> syncMessageObserver =
        new SyncRequestObserver<T>(coapRequest, timeout) {
          @Override
          public T buildResponse(final Response coapResponse) {
            // Build LwM2m response
            final LwM2mClientResponseBuilder<T> lwm2mResponseBuilder =
                new LwM2mClientResponseBuilder<T>(coapRequest, coapResponse);
            request.accept(lwm2mResponseBuilder);
            return lwm2mResponseBuilder.getResponse();
          }
        };
    coapRequest.addMessageObserver(syncMessageObserver);

    // Send CoAP request asynchronously
    clientEndpoint.sendRequest(coapRequest);

    // Wait for response, then return it
    return syncMessageObserver.waitForResponse();
  }