code: def inspect(self):
          
          timeout_manager = future_timeout_manager(self.sync_timeout)
          sensor_index_before = copy.copy(self._sensors_index)
          request_index_before = copy.copy(self._requests_index)
          try:
              request_changes = yield self.inspect_requests(
                  timeout=timeout_manager.remaining())
              sensor_changes = yield self.inspect_sensors(
                  timeout=timeout_manager.remaining())
          except Exception:
              # Ensure atomicity of sensor and request updates ; if the one
              # fails, the other should act as if it has failed too.
              self._sensors_index = sensor_index_before
              self._requests_index = request_index_before
              raise
  
          model_changes = AttrDict()
          if request_changes:
              model_changes.requests = request_changes
          if sensor_changes:
              model_changes.sensors = sensor_changes
          if model_changes:
              raise Return(model_changes)
docs: Inspect device requests and sensors, update model
  
          Returns
          -------
  
          Tornado future that resolves with:
  
          model_changes : Nested AttrDict or None
              Contains sets of added/removed request/sensor names
  
              Example structure:
  
              {'requests': {
                  'added': set(['req1', 'req2']),
                  'removed': set(['req10', 'req20'])}
               'sensors': {
                  'added': set(['sens1', 'sens2']),
                  'removed': set(['sens10', 'sens20'])}
              }
  
              If there are no changes keys may be omitted. If an item is in both
              the 'added' and 'removed' sets that means that it changed.
  
              If neither request not sensor changes are present, None is returned
              instead of a nested structure.