class Tinkerforge::Device
internal
Constants
- DEVICE_IDENTIFIER_CHECK_MATCH
- DEVICE_IDENTIFIER_CHECK_MISMATCH
- DEVICE_IDENTIFIER_CHECK_PENDING
- RESPONSE_EXPECTED_ALWAYS_TRUE
- RESPONSE_EXPECTED_FALSE
- RESPONSE_EXPECTED_INVALID_FUNCTION_ID
- RESPONSE_EXPECTED_TRUE
Attributes
Public Class Methods
internal
# File lib/tinkerforge/ip_connection.rb, line 242 def initialize(uid, ipcon, device_identifier, device_display_name) @replaced = false @uid = Base58.decode uid @uid_string = uid if @uid > (1 << 64) - 1 raise ArgumentError, "UID '#{uid}' is too big" end if @uid > (1 << 32) - 1 # convert from 64bit to 32bit value1 = @uid & 0xFFFFFFFF value2 = (@uid >> 32) & 0xFFFFFFFF @uid = (value1 & 0x00000FFF) @uid |= (value1 & 0x0F000000) >> 12 @uid |= (value2 & 0x0000003F) << 16 @uid |= (value2 & 0x000F0000) << 6 @uid |= (value2 & 0x3F000000) << 2 end if @uid == 0 raise ArgumentError, "UID '#{uid}' is empty or maps to zero" end @api_version = [0, 0, 0] @ipcon = ipcon @device_identifier = device_identifier @device_display_name = device_display_name @device_identifier_lock = Mutex.new @device_identifier_check = DEVICE_IDENTIFIER_CHECK_PENDING # protected by device_identifier_lock @wrong_device_display_name = '?' # protected by device_identifier_lock @request_mutex = Mutex.new @response_expected = Array.new(256, RESPONSE_EXPECTED_INVALID_FUNCTION_ID) @expected_response_function_id = 0 @expected_response_sequence_number = 0 @response_mutex = Mutex.new @response_condition = ConditionVariable.new @response_queue = Queue.new @stream_mutex = Mutex.new @callback_formats = {} @high_level_callbacks = {} @registered_callbacks = {} end
Public Instance Methods
internal
# File lib/tinkerforge/ip_connection.rb, line 483 def check_validity() if @replaced raise DeviceReplacedException, 'Device has been replaced' end if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MATCH return end @device_identifier_lock.synchronize { if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_PENDING device_identifier = send_request(255, [], '', 33, 'Z8 Z8 k C3 C3 S')[5] # <device>.get_identity if device_identifier == @device_identifier @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MATCH else @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MISMATCH @wrong_device_display_name = get_device_display_name device_identifier end end if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MISMATCH raise WrongDeviceTypeException, "UID #{@uid_string} belongs to a #{@wrong_device_display_name} instead of the expected #{@device_display_name}" end } end
internal
# File lib/tinkerforge/ip_connection.rb, line 466 def dequeue_response(message) response = nil @response_mutex.synchronize { @response_condition.wait @response_mutex, @ipcon.timeout if @response_queue.empty? raise TimeoutException, message end response = @response_queue.pop } response end
internal
# File lib/tinkerforge/ip_connection.rb, line 458 def enqueue_response(response) @response_mutex.synchronize { @response_queue.push response @response_condition.signal } end
Returns the API version (major, minor, revision) of the bindings for this device.
# File lib/tinkerforge/ip_connection.rb, line 297 def get_api_version @api_version end
Returns the response expected flag for the function specified by the function_id
parameter. It is true
if the function is expected to send a response, false
otherwise.
For getter functions this is enabled by default and cannot be disabled, because those functions will always send a response. For callback configuration functions it is enabled by default too, but can be disabled via the set_response_expected
function. For setter functions it is disabled by default and can be enabled.
Enabling the response expected flag for a setter function allows to detect timeouts and other error conditions calls of this setter as well. The device will then send a response for this purpose. If this flag is disabled for a setter function then no response is sent and errors are silently ignored, because they cannot be detected.
# File lib/tinkerforge/ip_connection.rb, line 316 def get_response_expected(function_id) if function_id < 0 or function_id > 255 raise ArgumentError, "Function ID #{function_id} out of range" end flag = @response_expected[function_id] if flag == RESPONSE_EXPECTED_INVALID_FUNCTION_ID raise ArgumentError, "Invalid function ID #{function_id}" end if flag == RESPONSE_EXPECTED_ALWAYS_TRUE or \ flag == RESPONSE_EXPECTED_TRUE true else false end end
internal
# File lib/tinkerforge/ip_connection.rb, line 385 def send_request(function_id, request_data, request_format, expected_response_length, response_format) response = nil if request_data.length > 0 payload = Packer.pack request_data, request_format else payload = '' end header, response_expected, sequence_number = \ @ipcon.create_packet_header self, 8 + payload.length, function_id request = header + payload if response_expected packet = nil @request_mutex.synchronize { @expected_response_function_id = function_id @expected_response_sequence_number = sequence_number begin @ipcon.send_request request while true packet = dequeue_response "Did not receive response in time for function ID #{function_id}" if function_id == Packer.get_function_id_from_data(packet) and \ sequence_number == Packer.get_sequence_number_from_data(packet) # ignore old responses that arrived after the timeout expired, but before setting # expected_response_function_id and expected_response_sequence_number back to None break end end ensure @expected_response_function_id = 0 @expected_response_sequence_number = 0 end } error_code = Packer.get_error_code_from_data packet if error_code == 0 if expected_response_length == 0 expected_response_length = 8 # setter with response-expected enabled end if packet.length != expected_response_length raise WrongResponseLengthException, "Expected response of #{expected_response_length} byte for function ID #{function_id}, got #{packet.length} byte instead" end elsif error_code == 1 raise InvalidParameterException, "Got invalid parameter for function ID #{function_id}" elsif error_code == 2 raise NotSupportedException, "Function ID #{function_id} is not supported" else raise UnknownErrorCodeException, "Function ID #{function_id} returned an unknown error" end if response_format.length > 0 response = Packer.unpack packet[8..-1], response_format if response.length == 1 response = response[0] end end else @ipcon.send_request request end response end
Changes the response expected flag of the function specified by the function_id
parameter. This flag can only be changed for setter (default value: false
) and callback configuration functions (default value: true
). For getter functions it is always enabled.
Enabling the response expected flag for a setter function allows to detect timeouts and other error conditions calls of this setter as well. The device will then send a response for this purpose. If this flag is disabled for a setter function then no response is sent and errors are silently ignored, because they cannot be detected.
# File lib/tinkerforge/ip_connection.rb, line 345 def set_response_expected(function_id, response_expected) if function_id < 0 or function_id > 255 raise ArgumentError, "Function ID #{function_id} out of range" end flag = @response_expected[function_id] if flag == RESPONSE_EXPECTED_INVALID_FUNCTION_ID raise ArgumentError, "Invalid function ID #{function_id}" end if flag == RESPONSE_EXPECTED_ALWAYS_TRUE raise ArgumentError, "Response Expected flag cannot be changed for function ID #{function_id}" end if response_expected @response_expected[function_id] = RESPONSE_EXPECTED_TRUE else @response_expected[function_id] = RESPONSE_EXPECTED_FALSE end end
Changes the response expected flag for all setter and callback configuration functions of this device at once.
# File lib/tinkerforge/ip_connection.rb, line 369 def set_response_expected_all(response_expected) if response_expected flag = RESPONSE_EXPECTED_TRUE else flag = RESPONSE_EXPECTED_FALSE end for function_id in 0..255 if @response_expected[function_id] == RESPONSE_EXPECTED_TRUE or \ @response_expected[function_id] == RESPONSE_EXPECTED_FALSE @response_expected[function_id] = flag end end end