/** 读取所有可读属性 */
  public void getProperties(final GetPropertiesCompletionHandler handler) throws MiotException {
    if (!mDevice.isConnectionEstablished()) {
      throw new MiotException("device not configurated connection");
    }

    PropertyInfo propertyInfo = PropertyInfoFactory.create(getService());
    propertyInfo.addProperty(getService().getProperty(PROPERTY_UsbStatus));
    propertyInfo.addProperty(getService().getProperty(PROPERTY_PowerStatus));

    DeviceManipulator op = MiotManager.getDeviceManipulator();
    op.readProperty(
        propertyInfo,
        new DeviceManipulator.ReadPropertyCompletionHandler() {
          @Override
          public void onSucceed(PropertyInfo info) {
            Boolean usbStatus = (Boolean) info.getValue(PROPERTY_UsbStatus);
            Boolean powerStatus = (Boolean) info.getValue(PROPERTY_PowerStatus);
            handler.onSucceed(usbStatus, powerStatus);
          }

          @Override
          public void onFailed(int errCode, String description) {
            handler.onFailed(errCode, description);
          }
        });
  }
  // -------------------------------------------------------
  // Property: unsubscribeNotifications
  // -------------------------------------------------------
  public void unsubscribeNotifications(final CompletionHandler handler) throws MiotException {
    if (handler == null) {
      throw new IllegalArgumentException("handler is null");
    }

    PropertyInfo propertyInfo = PropertyInfoFactory.create(getService());
    for (Property property : getService().getProperties()) {
      PropertyDefinition definition = property.getDefinition();
      if (definition.isNotifiable()) {
        propertyInfo.addProperty(property);
      }
    }

    DeviceManipulator op = MiotManager.getDeviceManipulator();
    op.removePropertyChangedListener(
        propertyInfo,
        new DeviceManipulator.CompletionHandler() {
          @Override
          public void onSucceed() {
            handler.onSucceed();
          }

          @Override
          public void onFailed(int errCode, String description) {
            handler.onFailed(errCode, description);
          }
        });
  }
  // -------------------------------------------------------
  // Property: subscribeNotifications
  // -------------------------------------------------------
  public void subscribeNotifications(
      final CompletionHandler handler, final PropertyNotificationListener listener)
      throws MiotException {
    if (handler == null) {
      throw new IllegalArgumentException("handler is null");
    }

    if (listener == null) {
      throw new IllegalArgumentException("listener is null");
    }

    PropertyInfo propertyInfo = PropertyInfoFactory.create(getService());
    for (Property property : getService().getProperties()) {
      PropertyDefinition definition = property.getDefinition();
      if (definition.isNotifiable()) {
        propertyInfo.addProperty(property);
      }
    }

    DeviceManipulator op = MiotManager.getDeviceManipulator();
    op.addPropertyChangedListener(
        propertyInfo,
        new DeviceManipulator.CompletionHandler() {
          @Override
          public void onSucceed() {
            handler.onSucceed();
          }

          @Override
          public void onFailed(int errCode, String description) {
            handler.onFailed(errCode, description);
          }
        },
        new DeviceManipulator.PropertyChangedListener() {
          @Override
          public void onPropertyChanged(PropertyInfo info, String propertyName) {
            switch (propertyName) {
              case PROPERTY_UsbStatus:
                Boolean usbStatus = (Boolean) info.getValue(PROPERTY_UsbStatus);
                listener.onUsbStatusChanged(usbStatus);
                break;
              case PROPERTY_PowerStatus:
                Boolean powerStatus = (Boolean) info.getValue(PROPERTY_PowerStatus);
                listener.onPowerStatusChanged(powerStatus);
                break;

              default:
                break;
            }
          }
        });
  }