def _mock(*args, **kwargs): readings = [ api.DeviceReading( rack='rack', board='board', device='device', reading=api.Reading( timestamp='2018-10-18T16:43:18+00:00', type='temperature', int64_value=10, ) ), api.DeviceReading( rack='rack', board='board', device='device', reading=api.Reading( timestamp='2018-10-18T16:43:18+00:00', type='humidity', int64_value=30, ) ) ] for r in readings: yield r
def test_read_scheme_null_value(): """Test that the read scheme matches the expected when there is no read value. """ dev = make_device_response() reading = api.Reading( timestamp='november', type='temperature', ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [ { 'info': '', 'type': 'temperature', 'value': None, 'timestamp': 'november', 'unit': { 'name': 'celsius', 'symbol': 'C' } } ] }
def test_read_scheme_no_precision(): """Test that the read scheme matches the expected when no precision is given for the device """ dev = make_device_response() dev.output[0].precision = 0 reading = api.Reading( timestamp='november', type='temperature', float64_value=10.98765432 ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [ { 'info': '', 'type': 'temperature', 'value': 10.98765432, 'timestamp': 'november', 'unit': { 'name': 'celsius', 'symbol': 'C' } } ] }
def test_read_scheme_no_unit(): """Test that the read scheme matches the expected when no unit is given for the device """ dev = make_device_response() dev.output[0].unit.name = '' dev.output[0].unit.symbol = '' reading = api.Reading( timestamp='november', type='temperature', float64_value=10.98765432 ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [ { 'info': '', 'type': 'temperature', 'value': 10.988, 'timestamp': 'november', 'unit': None } ] }
def test_read_scheme_with_precision_rounding_2(): """Test that the read scheme matches the expected when the read value must be rounded to the specified precision. """ dev = make_device_response() reading = api.Reading( timestamp='november', type='temperature', float64_value=10.98765432 ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [ { 'info': '', 'type': 'temperature', 'value': 10.988, 'timestamp': 'november', 'unit': { 'name': 'celsius', 'symbol': 'C' } } ] }
def test_read_scheme_non_convertible_value(): """Test that the read scheme matches the expected when the read value is non-convertible. In this case, it doesn't raise the error but log a warning. The error value is still processed and left for the plugin level to handle. """ dev = make_device_response() reading = api.Reading( timestamp='november', type='temperature', string_value='101a' ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [ { 'info': '', 'type': 'temperature', 'value': '101a', 'timestamp': 'november', 'unit': { 'name': 'celsius', 'symbol': 'C' } } ] }
def test_read_scheme_wrong_type_value(): """Test that the read scheme matches the expected when the read value has the wrong type. """ with pytest.raises(TypeError): _ = api.Reading( timestamp='november', type='temperature', string_value=101 )
def _mock_read(*args, **kwargs): yield api.DeviceReading( rack='rack', board='board', device='device', reading=api.Reading( timestamp='2018-10-18T16:43:18+00:00', type='temperature', int64_value=10, ) )
def test_read_scheme_with_no_matching_readings(): """Test that the read scheme matches the expected when no matching readings are provided. """ dev = make_device_response() reading = api.Reading( timestamp='november', type='humidity', int32_value=5 ) response_scheme = ReadResponse(dev, [reading]) assert response_scheme.data == { 'kind': 'thermistor', 'data': [] }
def test_read_cached_scheme(): """Test that the read cached scheme matches the expected.""" dev = api.Device(timestamp='october', uid='12345', kind='thermistor', metadata=dict(model='test', manufacturer='vapor io'), plugin='foo', info='bar', location=api.Location(rack='rack-1', board='vec'), output=[ api.Output(name='foo.temperature', type='temperature', precision=3, unit=api.Unit(name='celsius', symbol='C')) ]) reading = api.DeviceReading(rack='rack-1', board='vec', device='12345', reading=api.Reading(timestamp='november', type='temperature', int64_value=10)) response_scheme = ReadCachedResponse(dev, reading) assert response_scheme.data == { 'location': { 'rack': 'rack-1', 'board': 'vec', 'device': '12345' }, 'kind': 'thermistor', 'info': '', 'type': 'temperature', 'value': 10.0, 'timestamp': 'november', 'unit': { 'name': 'celsius', 'symbol': 'C' } }
def mockread(self, rack, board, device): """Mock method to monkeypatch the client read method.""" return [ api.Reading(timestamp='october', type='temperature', int64_value=10) ]
async def read(rack, board, device): """The handler for the Synse Server "read" API command. Args: rack (str): The rack which the device resides on. board (str): The board which the device resides on. device (str): The device to read. Returns: ReadResponse: The "read" response scheme model. """ logger.debug( _('Read Command (args: {}, {}, {})').format(rack, board, device)) # Lookup the known info for the specified device. plugin_name, dev = await cache.get_device_info(rack, board, device) logger.debug( _('Device {} is managed by plugin {}').format(device, plugin_name)) # Get the plugin context for the device's specified protocol. _plugin = plugin.get_plugin(plugin_name) logger.debug(_('Got plugin: {}').format(_plugin)) if not _plugin: raise errors.PluginNotFoundError( _('Unable to find plugin named "{}" to read').format(plugin_name)) try: # Perform a gRPC read on the device's managing plugin read_data = _plugin.client.read(rack, board, device) except grpc.RpcError as ex: # FIXME (etd) - this isn't the nicest way of doing this check. # this string is returned from the SDK, and its not likely to change # anytime soon, so this is "safe" for now, but we should see if there # is a better way to check this other than comparing strings.. if hasattr(ex, 'code') and hasattr(ex, 'details'): if grpc.StatusCode.NOT_FOUND == ex.code( ) and 'no readings found' in ex.details().lower(): # FIXME (etd) - with SDK v1.0, is the below correct? We should not longer # have to pass the "null" string. I think an empty string should also not # indicate no readings.. it should be the NOT_FOUND error (or, at least # some kind of error). # Currently, in the SDK, there are three different behaviors for # devices that do not have readings. Either (a). "null" is returned, # (b). an empty string ("") is returned, or (c). a gRPC error is # returned with the NOT_FOUND status code. Cases (a) and (b) are # handled in the ReadResponse initialization (below). This block # handles case (c). # # The reason for the difference between (a) and (b) is just one # of implementation. The empty string is the default value for the # gRPC read response, but sometimes it is useful to have an explict # value set to make things easier to read. # # The difference between those and (c) is more distinct. (c) should # only happen when a configured device is not being read from at all. # Essentially, (c) is the fallback for when device-specific handlers # fail to read a configured device. # # To summarize: # (a), (b) # A device is configured and the plugin's device handlers # can operate on the device. This indicates that the plugin # is working, but the device could be failing or disconnected. # # (c) # A device is configured, but the plugin's device handler # can not (or is not) able to operate on the device. This # could indicate either a plugin configuration error or # an error with the plugin logic itself. # Create empty readings for each of the device's readings. logger.warning( _('Read for {}/{}/{} returned gRPC "no readings found". Will ' 'apply None as reading value. Note that this response might ' 'indicate plugin error/misconfiguration.').format( rack, board, device)) read_data = [] for output in dev.output: read_data.append( api.Reading( timestamp=utils.rfc3339now(), type=output.type, )) else: raise errors.FailedReadCommandError(str(ex)) from ex else: raise errors.FailedReadCommandError(str(ex)) from ex return ReadResponse(device=dev, readings=read_data)