tinkerforge 2.1.22 → 2.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. checksums.yaml +5 -5
  2. data/lib/tinkerforge/brick_dc.rb +157 -76
  3. data/lib/tinkerforge/brick_hat.rb +115 -32
  4. data/lib/tinkerforge/brick_hat_zero.rb +119 -21
  5. data/lib/tinkerforge/brick_imu.rb +192 -87
  6. data/lib/tinkerforge/brick_imu_v2.rb +220 -119
  7. data/lib/tinkerforge/brick_master.rb +498 -198
  8. data/lib/tinkerforge/brick_red.rb +197 -74
  9. data/lib/tinkerforge/brick_servo.rb +187 -103
  10. data/lib/tinkerforge/brick_silent_stepper.rb +249 -169
  11. data/lib/tinkerforge/brick_stepper.rb +214 -102
  12. data/lib/tinkerforge/bricklet_accelerometer.rb +61 -36
  13. data/lib/tinkerforge/bricklet_accelerometer_v2.rb +167 -48
  14. data/lib/tinkerforge/bricklet_air_quality.rb +123 -76
  15. data/lib/tinkerforge/bricklet_ambient_light.rb +62 -46
  16. data/lib/tinkerforge/bricklet_ambient_light_v2.rb +41 -28
  17. data/lib/tinkerforge/bricklet_ambient_light_v3.rb +61 -28
  18. data/lib/tinkerforge/bricklet_analog_in.rb +66 -45
  19. data/lib/tinkerforge/bricklet_analog_in_v2.rb +60 -43
  20. data/lib/tinkerforge/bricklet_analog_in_v3.rb +68 -32
  21. data/lib/tinkerforge/bricklet_analog_out.rb +25 -16
  22. data/lib/tinkerforge/bricklet_analog_out_v2.rb +21 -10
  23. data/lib/tinkerforge/bricklet_analog_out_v3.rb +55 -22
  24. data/lib/tinkerforge/bricklet_barometer.rb +108 -58
  25. data/lib/tinkerforge/bricklet_barometer_v2.rb +109 -67
  26. data/lib/tinkerforge/bricklet_can.rb +84 -24
  27. data/lib/tinkerforge/bricklet_can_v2.rb +173 -72
  28. data/lib/tinkerforge/bricklet_co2.rb +36 -25
  29. data/lib/tinkerforge/bricklet_co2_v2.rb +119 -60
  30. data/lib/tinkerforge/bricklet_color.rb +77 -49
  31. data/lib/tinkerforge/bricklet_color_v2.rb +493 -0
  32. data/lib/tinkerforge/bricklet_compass.rb +397 -0
  33. data/lib/tinkerforge/bricklet_current12.rb +61 -40
  34. data/lib/tinkerforge/bricklet_current25.rb +61 -40
  35. data/lib/tinkerforge/bricklet_distance_ir.rb +60 -38
  36. data/lib/tinkerforge/bricklet_distance_ir_v2.rb +85 -45
  37. data/lib/tinkerforge/bricklet_distance_us.rb +43 -30
  38. data/lib/tinkerforge/bricklet_distance_us_v2.rb +335 -0
  39. data/lib/tinkerforge/bricklet_dmx.rb +92 -48
  40. data/lib/tinkerforge/bricklet_dual_button.rb +23 -12
  41. data/lib/tinkerforge/bricklet_dual_button_v2.rb +64 -29
  42. data/lib/tinkerforge/bricklet_dual_relay.rb +27 -14
  43. data/lib/tinkerforge/bricklet_dust_detector.rb +43 -30
  44. data/lib/tinkerforge/bricklet_e_paper_296x128.rb +115 -63
  45. data/lib/tinkerforge/bricklet_energy_monitor.rb +416 -0
  46. data/lib/tinkerforge/bricklet_gps.rb +72 -48
  47. data/lib/tinkerforge/bricklet_gps_v2.rb +124 -73
  48. data/lib/tinkerforge/bricklet_hall_effect.rb +43 -28
  49. data/lib/tinkerforge/bricklet_hall_effect_v2.rb +76 -44
  50. data/lib/tinkerforge/bricklet_humidity.rb +54 -38
  51. data/lib/tinkerforge/bricklet_humidity_v2.rb +86 -49
  52. data/lib/tinkerforge/bricklet_imu_v3.rb +784 -0
  53. data/lib/tinkerforge/bricklet_industrial_analog_out.rb +41 -18
  54. data/lib/tinkerforge/bricklet_industrial_analog_out_v2.rb +84 -40
  55. data/lib/tinkerforge/bricklet_industrial_counter.rb +102 -59
  56. data/lib/tinkerforge/bricklet_industrial_digital_in_4.rb +51 -24
  57. data/lib/tinkerforge/bricklet_industrial_digital_in_4_v2.rb +79 -40
  58. data/lib/tinkerforge/bricklet_industrial_digital_out_4.rb +36 -15
  59. data/lib/tinkerforge/bricklet_industrial_digital_out_4_v2.rb +75 -33
  60. data/lib/tinkerforge/bricklet_industrial_dual_0_20ma.rb +43 -29
  61. data/lib/tinkerforge/bricklet_industrial_dual_0_20ma_v2.rb +81 -44
  62. data/lib/tinkerforge/bricklet_industrial_dual_ac_relay.rb +325 -0
  63. data/lib/tinkerforge/bricklet_industrial_dual_analog_in.rb +51 -30
  64. data/lib/tinkerforge/bricklet_industrial_dual_analog_in_v2.rb +139 -40
  65. data/lib/tinkerforge/bricklet_industrial_dual_relay.rb +63 -28
  66. data/lib/tinkerforge/bricklet_industrial_quad_relay.rb +36 -15
  67. data/lib/tinkerforge/bricklet_industrial_quad_relay_v2.rb +67 -28
  68. data/lib/tinkerforge/bricklet_io16.rb +57 -32
  69. data/lib/tinkerforge/bricklet_io16_v2.rb +93 -48
  70. data/lib/tinkerforge/bricklet_io4.rb +56 -31
  71. data/lib/tinkerforge/bricklet_io4_v2.rb +109 -57
  72. data/lib/tinkerforge/bricklet_isolator.rb +111 -35
  73. data/lib/tinkerforge/bricklet_joystick.rb +63 -42
  74. data/lib/tinkerforge/bricklet_joystick_v2.rb +71 -35
  75. data/lib/tinkerforge/bricklet_laser_range_finder.rb +87 -59
  76. data/lib/tinkerforge/bricklet_laser_range_finder_v2.rb +101 -53
  77. data/lib/tinkerforge/bricklet_lcd_128x64.rb +241 -131
  78. data/lib/tinkerforge/bricklet_lcd_16x2.rb +49 -25
  79. data/lib/tinkerforge/bricklet_lcd_20x4.rb +59 -29
  80. data/lib/tinkerforge/bricklet_led_strip.rb +69 -47
  81. data/lib/tinkerforge/bricklet_led_strip_v2.rb +105 -48
  82. data/lib/tinkerforge/bricklet_line.rb +35 -22
  83. data/lib/tinkerforge/bricklet_linear_poti.rb +53 -35
  84. data/lib/tinkerforge/bricklet_linear_poti_v2.rb +55 -24
  85. data/lib/tinkerforge/bricklet_load_cell.rb +64 -40
  86. data/lib/tinkerforge/bricklet_load_cell_v2.rb +81 -41
  87. data/lib/tinkerforge/bricklet_moisture.rb +43 -30
  88. data/lib/tinkerforge/bricklet_motion_detector.rb +21 -10
  89. data/lib/tinkerforge/bricklet_motion_detector_v2.rb +62 -29
  90. data/lib/tinkerforge/bricklet_motorized_linear_poti.rb +71 -32
  91. data/lib/tinkerforge/bricklet_multi_touch.rb +30 -17
  92. data/lib/tinkerforge/bricklet_multi_touch_v2.rb +371 -0
  93. data/lib/tinkerforge/bricklet_nfc.rb +130 -80
  94. data/lib/tinkerforge/bricklet_nfc_rfid.rb +32 -13
  95. data/lib/tinkerforge/bricklet_oled_128x64.rb +30 -17
  96. data/lib/tinkerforge/bricklet_oled_128x64_v2.rb +97 -40
  97. data/lib/tinkerforge/bricklet_oled_64x48.rb +30 -17
  98. data/lib/tinkerforge/bricklet_one_wire.rb +65 -24
  99. data/lib/tinkerforge/bricklet_outdoor_weather.rb +84 -41
  100. data/lib/tinkerforge/bricklet_particulate_matter.rb +85 -37
  101. data/lib/tinkerforge/bricklet_piezo_buzzer.rb +19 -13
  102. data/lib/tinkerforge/bricklet_piezo_speaker.rb +22 -19
  103. data/lib/tinkerforge/bricklet_piezo_speaker_v2.rb +84 -57
  104. data/lib/tinkerforge/bricklet_ptc.rb +76 -51
  105. data/lib/tinkerforge/bricklet_ptc_v2.rb +96 -54
  106. data/lib/tinkerforge/bricklet_real_time_clock.rb +45 -36
  107. data/lib/tinkerforge/bricklet_real_time_clock_v2.rb +78 -47
  108. data/lib/tinkerforge/bricklet_remote_switch.rb +38 -29
  109. data/lib/tinkerforge/bricklet_remote_switch_v2.rb +86 -49
  110. data/lib/tinkerforge/bricklet_rgb_led.rb +17 -8
  111. data/lib/tinkerforge/bricklet_rgb_led_button.rb +61 -30
  112. data/lib/tinkerforge/bricklet_rgb_led_matrix.rb +78 -33
  113. data/lib/tinkerforge/bricklet_rgb_led_v2.rb +51 -20
  114. data/lib/tinkerforge/bricklet_rotary_encoder.rb +40 -25
  115. data/lib/tinkerforge/bricklet_rotary_encoder_v2.rb +60 -27
  116. data/lib/tinkerforge/bricklet_rotary_poti.rb +55 -37
  117. data/lib/tinkerforge/bricklet_rotary_poti_v2.rb +290 -0
  118. data/lib/tinkerforge/bricklet_rs232.rb +89 -28
  119. data/lib/tinkerforge/bricklet_rs232_v2.rb +121 -47
  120. data/lib/tinkerforge/bricklet_rs485.rb +303 -207
  121. data/lib/tinkerforge/bricklet_segment_display_4x7.rb +24 -14
  122. data/lib/tinkerforge/bricklet_segment_display_4x7_v2.rb +75 -36
  123. data/lib/tinkerforge/bricklet_solid_state_relay.rb +24 -13
  124. data/lib/tinkerforge/bricklet_solid_state_relay_v2.rb +58 -25
  125. data/lib/tinkerforge/bricklet_sound_intensity.rb +36 -24
  126. data/lib/tinkerforge/bricklet_sound_pressure_level.rb +77 -41
  127. data/lib/tinkerforge/bricklet_temperature.rb +43 -28
  128. data/lib/tinkerforge/bricklet_temperature_ir.rb +63 -47
  129. data/lib/tinkerforge/bricklet_temperature_ir_v2.rb +75 -53
  130. data/lib/tinkerforge/bricklet_temperature_v2.rb +62 -31
  131. data/lib/tinkerforge/bricklet_thermal_imaging.rb +118 -68
  132. data/lib/tinkerforge/bricklet_thermocouple.rb +46 -30
  133. data/lib/tinkerforge/bricklet_thermocouple_v2.rb +65 -30
  134. data/lib/tinkerforge/bricklet_tilt.rb +23 -10
  135. data/lib/tinkerforge/bricklet_uv_light.rb +37 -24
  136. data/lib/tinkerforge/bricklet_uv_light_v2.rb +87 -46
  137. data/lib/tinkerforge/bricklet_voltage.rb +54 -37
  138. data/lib/tinkerforge/bricklet_voltage_current.rb +94 -85
  139. data/lib/tinkerforge/bricklet_voltage_current_v2.rb +103 -77
  140. data/lib/tinkerforge/bricklet_xmc1400_breakout.rb +410 -0
  141. data/lib/tinkerforge/device_display_names.rb +165 -0
  142. data/lib/tinkerforge/ip_connection.rb +155 -33
  143. data/lib/tinkerforge/version.rb +1 -1
  144. metadata +14 -4
@@ -0,0 +1,165 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+ #############################################################
3
+ # This file was automatically generated on 2020-11-02. #
4
+ # #
5
+ # Ruby Bindings Version 2.1.27 #
6
+ # #
7
+ # If you have a bugfix for this file and want to commit it, #
8
+ # please fix the bug in the generator. You can find a link #
9
+ # to the generators git repository on tinkerforge.com #
10
+ #############################################################
11
+
12
+ module Tinkerforge
13
+ DEVICE_DISPLAY_NAMES = {
14
+ 11 => 'DC Brick',
15
+ 13 => 'Master Brick',
16
+ 14 => 'Servo Brick',
17
+ 15 => 'Stepper Brick',
18
+ 16 => 'IMU Brick',
19
+ 17 => 'RED Brick',
20
+ 18 => 'IMU Brick 2.0',
21
+ 19 => 'Silent Stepper Brick',
22
+ 21 => 'Ambient Light Bricklet',
23
+ 23 => 'Current12 Bricklet',
24
+ 24 => 'Current25 Bricklet',
25
+ 25 => 'Distance IR Bricklet',
26
+ 26 => 'Dual Relay Bricklet',
27
+ 27 => 'Humidity Bricklet',
28
+ 28 => 'IO-16 Bricklet',
29
+ 29 => 'IO-4 Bricklet',
30
+ 111 => 'HAT Brick',
31
+ 112 => 'HAT Zero Brick',
32
+ 210 => 'Joystick Bricklet',
33
+ 211 => 'LCD 16x2 Bricklet',
34
+ 212 => 'LCD 20x4 Bricklet',
35
+ 213 => 'Linear Poti Bricklet',
36
+ 214 => 'Piezo Buzzer Bricklet',
37
+ 215 => 'Rotary Poti Bricklet',
38
+ 216 => 'Temperature Bricklet',
39
+ 217 => 'Temperature IR Bricklet',
40
+ 218 => 'Voltage Bricklet',
41
+ 219 => 'Analog In Bricklet',
42
+ 220 => 'Analog Out Bricklet',
43
+ 221 => 'Barometer Bricklet',
44
+ 222 => 'GPS Bricklet',
45
+ 223 => 'Industrial Digital In 4 Bricklet',
46
+ 224 => 'Industrial Digital Out 4 Bricklet',
47
+ 225 => 'Industrial Quad Relay Bricklet',
48
+ 226 => 'PTC Bricklet',
49
+ 227 => 'Voltage/Current Bricklet',
50
+ 228 => 'Industrial Dual 0-20mA Bricklet',
51
+ 229 => 'Distance US Bricklet',
52
+ 230 => 'Dual Button Bricklet',
53
+ 231 => 'LED Strip Bricklet',
54
+ 232 => 'Moisture Bricklet',
55
+ 233 => 'Motion Detector Bricklet',
56
+ 234 => 'Multi Touch Bricklet',
57
+ 235 => 'Remote Switch Bricklet',
58
+ 236 => 'Rotary Encoder Bricklet',
59
+ 237 => 'Segment Display 4x7 Bricklet',
60
+ 238 => 'Sound Intensity Bricklet',
61
+ 239 => 'Tilt Bricklet',
62
+ 240 => 'Hall Effect Bricklet',
63
+ 241 => 'Line Bricklet',
64
+ 242 => 'Piezo Speaker Bricklet',
65
+ 243 => 'Color Bricklet',
66
+ 244 => 'Solid State Relay Bricklet',
67
+ 246 => 'NFC/RFID Bricklet',
68
+ 249 => 'Industrial Dual Analog In Bricklet',
69
+ 250 => 'Accelerometer Bricklet',
70
+ 251 => 'Analog In Bricklet 2.0',
71
+ 253 => 'Load Cell Bricklet',
72
+ 254 => 'RS232 Bricklet',
73
+ 255 => 'Laser Range Finder Bricklet',
74
+ 256 => 'Analog Out Bricklet 2.0',
75
+ 258 => 'Industrial Analog Out Bricklet',
76
+ 259 => 'Ambient Light Bricklet 2.0',
77
+ 260 => 'Dust Detector Bricklet',
78
+ 262 => 'CO2 Bricklet',
79
+ 263 => 'OLED 128x64 Bricklet',
80
+ 264 => 'OLED 64x48 Bricklet',
81
+ 265 => 'UV Light Bricklet',
82
+ 266 => 'Thermocouple Bricklet',
83
+ 267 => 'Motorized Linear Poti Bricklet',
84
+ 268 => 'Real-Time Clock Bricklet',
85
+ 270 => 'CAN Bricklet',
86
+ 271 => 'RGB LED Bricklet',
87
+ 272 => 'RGB LED Matrix Bricklet',
88
+ 276 => 'GPS Bricklet 2.0',
89
+ 277 => 'RS485 Bricklet',
90
+ 278 => 'Thermal Imaging Bricklet',
91
+ 279 => 'XMC1400 Breakout Bricklet',
92
+ 282 => 'RGB LED Button Bricklet',
93
+ 283 => 'Humidity Bricklet 2.0',
94
+ 284 => 'Industrial Dual Relay Bricklet',
95
+ 285 => 'DMX Bricklet',
96
+ 286 => 'NFC Bricklet',
97
+ 288 => 'Outdoor Weather Bricklet',
98
+ 289 => 'Remote Switch Bricklet 2.0',
99
+ 290 => 'Sound Pressure Level Bricklet',
100
+ 291 => 'Temperature IR Bricklet 2.0',
101
+ 292 => 'Motion Detector Bricklet 2.0',
102
+ 293 => 'Industrial Counter Bricklet',
103
+ 294 => 'Rotary Encoder Bricklet 2.0',
104
+ 295 => 'Analog In Bricklet 3.0',
105
+ 296 => 'Solid State Relay Bricklet 2.0',
106
+ 297 => 'Air Quality Bricklet',
107
+ 298 => 'LCD 128x64 Bricklet',
108
+ 299 => 'Distance US Bricklet 2.0',
109
+ 2100 => 'Industrial Digital In 4 Bricklet 2.0',
110
+ 2101 => 'PTC Bricklet 2.0',
111
+ 2102 => 'Industrial Quad Relay Bricklet 2.0',
112
+ 2103 => 'LED Strip Bricklet 2.0',
113
+ 2104 => 'Load Cell Bricklet 2.0',
114
+ 2105 => 'Voltage/Current Bricklet 2.0',
115
+ 2106 => 'Real-Time Clock Bricklet 2.0',
116
+ 2107 => 'CAN Bricklet 2.0',
117
+ 2108 => 'RS232 Bricklet 2.0',
118
+ 2109 => 'Thermocouple Bricklet 2.0',
119
+ 2110 => 'Particulate Matter Bricklet',
120
+ 2111 => 'IO-4 Bricklet 2.0',
121
+ 2112 => 'OLED 128x64 Bricklet 2.0',
122
+ 2113 => 'Temperature Bricklet 2.0',
123
+ 2114 => 'IO-16 Bricklet 2.0',
124
+ 2115 => 'Analog Out Bricklet 3.0',
125
+ 2116 => 'Industrial Analog Out Bricklet 2.0',
126
+ 2117 => 'Barometer Bricklet 2.0',
127
+ 2118 => 'UV Light Bricklet 2.0',
128
+ 2119 => 'Dual Button Bricklet 2.0',
129
+ 2120 => 'Industrial Dual 0-20mA Bricklet 2.0',
130
+ 2121 => 'Industrial Dual Analog In Bricklet 2.0',
131
+ 2122 => 'Isolator Bricklet',
132
+ 2123 => 'One Wire Bricklet',
133
+ 2124 => 'Industrial Digital Out 4 Bricklet 2.0',
134
+ 2125 => 'Distance IR Bricklet 2.0',
135
+ 2127 => 'RGB LED Bricklet 2.0',
136
+ 2128 => 'Color Bricklet 2.0',
137
+ 2129 => 'Multi Touch Bricklet 2.0',
138
+ 2130 => 'Accelerometer Bricklet 2.0',
139
+ 2131 => 'Ambient Light Bricklet 3.0',
140
+ 2132 => 'Hall Effect Bricklet 2.0',
141
+ 2137 => 'Segment Display 4x7 Bricklet 2.0',
142
+ 2138 => 'Joystick Bricklet 2.0',
143
+ 2139 => 'Linear Poti Bricklet 2.0',
144
+ 2140 => 'Rotary Poti Bricklet 2.0',
145
+ 2144 => 'Laser Range Finder Bricklet 2.0',
146
+ 2145 => 'Piezo Speaker Bricklet 2.0',
147
+ 2146 => 'E-Paper 296x128 Bricklet',
148
+ 2147 => 'CO2 Bricklet 2.0',
149
+ 2152 => 'Energy Monitor Bricklet',
150
+ 2153 => 'Compass Bricklet',
151
+ 2161 => 'IMU Bricklet 3.0',
152
+ 2162 => 'Industrial Dual AC Relay Bricklet'
153
+ }
154
+
155
+ # internal
156
+ def get_device_display_name(device_identifier)
157
+ device_display_name = DEVICE_DISPLAY_NAMES[device_identifier]
158
+
159
+ if device_display_name == nil
160
+ device_display_name = "Unknown Device [#{device_identifier}]"
161
+ end
162
+
163
+ device_display_name
164
+ end
165
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
- # Copyright (C) 2012-2014, 2019 Matthias Bolte <matthias@tinkerforge.com>
2
+ # Copyright (C) 2012-2014, 2019-2020 Matthias Bolte <matthias@tinkerforge.com>
3
3
  #
4
4
  # Redistribution and use in source and binary forms of this file,
5
5
  # with or without modification, are permitted. See the Creative
@@ -10,8 +10,10 @@ require 'thread'
10
10
  require 'timeout'
11
11
  require 'securerandom'
12
12
  require 'openssl'
13
+ require_relative './device_display_names'
13
14
 
14
15
  module Tinkerforge
16
+ # internal
15
17
  class Base58
16
18
  ALPHABET = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
17
19
 
@@ -64,6 +66,16 @@ module Tinkerforge
64
66
  class StreamOutOfSyncException < TinkerforgeException
65
67
  end
66
68
 
69
+ class WrongDeviceTypeException < TinkerforgeException
70
+ end
71
+
72
+ class DeviceReplacedException < TinkerforgeException
73
+ end
74
+
75
+ class WrongResponseLengthException < TinkerforgeException
76
+ end
77
+
78
+ # internal
67
79
  class Packer
68
80
  def self.pack(unpacked, format)
69
81
  data = ''
@@ -207,12 +219,18 @@ module Tinkerforge
207
219
  end
208
220
  end
209
221
 
222
+ # internal
210
223
  class Device
224
+ DEVICE_IDENTIFIER_CHECK_PENDING = 0
225
+ DEVICE_IDENTIFIER_CHECK_MATCH = 1
226
+ DEVICE_IDENTIFIER_CHECK_MISMATCH = 2
227
+
211
228
  RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0
212
229
  RESPONSE_EXPECTED_ALWAYS_TRUE = 1 # getter
213
230
  RESPONSE_EXPECTED_TRUE = 2 # setter
214
231
  RESPONSE_EXPECTED_FALSE = 3 # setter, default
215
232
 
233
+ attr_accessor :replaced
216
234
  attr_accessor :uid
217
235
  attr_accessor :expected_response_function_id
218
236
  attr_accessor :expected_response_sequence_number
@@ -220,10 +238,11 @@ module Tinkerforge
220
238
  attr_accessor :high_level_callbacks
221
239
  attr_accessor :registered_callbacks
222
240
 
223
- # Creates the device object with the unique device ID <tt>uid</tt> and adds
224
- # it to the IPConnection <tt>ipcon</tt>.
225
- def initialize(uid, ipcon)
241
+ # internal
242
+ def initialize(uid, ipcon, device_identifier, device_display_name)
243
+ @replaced = false
226
244
  @uid = Base58.decode uid
245
+ @uid_string = uid
227
246
 
228
247
  if @uid > (1 << 64) - 1
229
248
  raise ArgumentError, "UID '#{uid}' is too big"
@@ -249,6 +268,12 @@ module Tinkerforge
249
268
 
250
269
  @ipcon = ipcon
251
270
 
271
+ @device_identifier = device_identifier
272
+ @device_display_name = device_display_name
273
+ @device_identifier_lock = Mutex.new
274
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_PENDING # protected by device_identifier_lock
275
+ @wrong_device_display_name = '?' # protected by device_identifier_lock
276
+
252
277
  @request_mutex = Mutex.new
253
278
 
254
279
  @response_expected = Array.new(256, RESPONSE_EXPECTED_INVALID_FUNCTION_ID)
@@ -265,8 +290,6 @@ module Tinkerforge
265
290
  @callback_formats = {}
266
291
  @high_level_callbacks = {}
267
292
  @registered_callbacks = {}
268
-
269
- @ipcon.devices[@uid] = self # FIXME: use a weakref here
270
293
  end
271
294
 
272
295
  # Returns the API version (major, minor, revision) of the bindings for
@@ -288,7 +311,7 @@ module Tinkerforge
288
311
  # Enabling the response expected flag for a setter function allows to
289
312
  # detect timeouts and other error conditions calls of this setter as
290
313
  # well. The device will then send a response for this purpose. If this
291
- # flag is disabled for a setter function then no response is send and
314
+ # flag is disabled for a setter function then no response is sent and
292
315
  # errors are silently ignored, because they cannot be detected.
293
316
  def get_response_expected(function_id)
294
317
  if function_id < 0 or function_id > 255
@@ -317,7 +340,7 @@ module Tinkerforge
317
340
  # Enabling the response expected flag for a setter function allows to
318
341
  # detect timeouts and other error conditions calls of this setter as
319
342
  # well. The device will then send a response for this purpose. If this
320
- # flag is disabled for a setter function then no response is send and
343
+ # flag is disabled for a setter function then no response is sent and
321
344
  # errors are silently ignored, because they cannot be detected.
322
345
  def set_response_expected(function_id, response_expected)
323
346
  if function_id < 0 or function_id > 255
@@ -360,7 +383,7 @@ module Tinkerforge
360
383
 
361
384
  # internal
362
385
  def send_request(function_id, request_data, request_format,
363
- response_length, response_format)
386
+ expected_response_length, response_format)
364
387
  response = nil
365
388
 
366
389
  if request_data.length > 0
@@ -402,7 +425,13 @@ module Tinkerforge
402
425
  error_code = Packer.get_error_code_from_data packet
403
426
 
404
427
  if error_code == 0
405
- # no error
428
+ if expected_response_length == 0
429
+ expected_response_length = 8 # setter with response-expected enabled
430
+ end
431
+
432
+ if packet.length != expected_response_length
433
+ raise WrongResponseLengthException, "Expected response of #{expected_response_length} byte for function ID #{function_id}, got #{packet.length} byte instead"
434
+ end
406
435
  elsif error_code == 1
407
436
  raise InvalidParameterException, "Got invalid parameter for function ID #{function_id}"
408
437
  elsif error_code == 2
@@ -411,7 +440,7 @@ module Tinkerforge
411
440
  raise UnknownErrorCodeException, "Function ID #{function_id} returned an unknown error"
412
441
  end
413
442
 
414
- if response_length > 0
443
+ if response_format.length > 0
415
444
  response = Packer.unpack packet[8..-1], response_format
416
445
 
417
446
  if response.length == 1
@@ -449,6 +478,34 @@ module Tinkerforge
449
478
 
450
479
  response
451
480
  end
481
+
482
+ # internal
483
+ def check_validity()
484
+ if @replaced
485
+ raise DeviceReplacedException, 'Device has been replaced'
486
+ end
487
+
488
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MATCH
489
+ return
490
+ end
491
+
492
+ @device_identifier_lock.synchronize {
493
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_PENDING
494
+ device_identifier = send_request(255, [], '', 33, 'Z8 Z8 k C3 C3 S')[5] # <device>.get_identity
495
+
496
+ if device_identifier == @device_identifier
497
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MATCH
498
+ else
499
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MISMATCH
500
+ @wrong_device_display_name = get_device_display_name device_identifier
501
+ end
502
+ end
503
+
504
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MISMATCH
505
+ raise WrongDeviceTypeException, "UID #{@uid_string} belongs to a #{@wrong_device_display_name} instead of the expected #{@device_display_name}"
506
+ end
507
+ }
508
+ end
452
509
  end
453
510
 
454
511
  # internal
@@ -474,16 +531,18 @@ module Tinkerforge
474
531
  # Creates an object with the unique device ID <tt>uid</tt> and adds it to
475
532
  # the IP Connection <tt>ipcon</tt>.
476
533
  def initialize(uid, ipcon)
477
- super uid, ipcon
534
+ super uid, ipcon, 0, 'Brick Daemon'
478
535
 
479
536
  @api_version = [2, 0, 0]
480
537
 
481
538
  @response_expected[FUNCTION_GET_AUTHENTICATION_NONCE] = RESPONSE_EXPECTED_ALWAYS_TRUE
482
539
  @response_expected[FUNCTION_AUTHENTICATE] = RESPONSE_EXPECTED_TRUE
540
+
541
+ @ipcon.add_device self
483
542
  end
484
543
 
485
544
  def get_authentication_nonce
486
- send_request FUNCTION_GET_AUTHENTICATION_NONCE, [], '', 4, 'C4'
545
+ send_request FUNCTION_GET_AUTHENTICATION_NONCE, [], '', 12, 'C4'
487
546
  end
488
547
 
489
548
  def authenticate(client_nonce, digest)
@@ -492,7 +551,6 @@ module Tinkerforge
492
551
  end
493
552
 
494
553
  class IPConnection
495
- attr_accessor :devices
496
554
  attr_accessor :timeout
497
555
 
498
556
  CALLBACK_ENUMERATE = 253
@@ -538,6 +596,7 @@ module Tinkerforge
538
596
  @authentication_mutex = Mutex.new # protects authentication handshake
539
597
 
540
598
  @devices = {}
599
+ @replace_mutex = Mutex.new # used to synchronize replacements in the devices dict
541
600
 
542
601
  @registered_callbacks = {}
543
602
 
@@ -626,8 +685,11 @@ module Tinkerforge
626
685
  # is not enabled at all on the Brick Daemon or the WIFI/Ethernet Extension.
627
686
  #
628
687
  # For more information about authentication see
629
- # http://www.tinkerforge.com/en/doc/Tutorials/Tutorial_Authentication/Tutorial.html
688
+ # https://www.tinkerforge.com/en/doc/Tutorials/Tutorial_Authentication/Tutorial.html
630
689
  def authenticate(secret)
690
+ if not secret.ascii_only?
691
+ raise ArgumentError, "Authentication secret contains non-ASCII characters"
692
+ end
631
693
  @authentication_mutex.synchronize {
632
694
  if @next_authentication_nonce == 0
633
695
  @next_authentication_nonce = SecureRandom.random_number(1 << 32)
@@ -728,6 +790,19 @@ module Tinkerforge
728
790
  @registered_callbacks[id] = callback
729
791
  end
730
792
 
793
+ # internal
794
+ def add_device(device)
795
+ @replace_mutex.synchronize {
796
+ replaced_device = @devices.fetch device.uid, nil
797
+
798
+ if replaced_device != nil
799
+ replaced_device.replaced = true
800
+ end
801
+
802
+ @devices[device.uid] = device # FIXME: use a weakref here
803
+ }
804
+ end
805
+
731
806
  # internal
732
807
  def get_next_sequence_number
733
808
  @sequence_number_mutex.synchronize {
@@ -948,8 +1023,10 @@ module Tinkerforge
948
1023
  # internal
949
1024
  def dispatch_meta(function_id, parameter, socket_id)
950
1025
  if function_id == CALLBACK_CONNECTED
951
- if @registered_callbacks.has_key? CALLBACK_CONNECTED
952
- @registered_callbacks[CALLBACK_CONNECTED].call parameter
1026
+ cb = @registered_callbacks[CALLBACK_CONNECTED]
1027
+
1028
+ if cb != nil
1029
+ cb.call parameter
953
1030
  end
954
1031
  elsif function_id == CALLBACK_DISCONNECTED
955
1032
  if parameter != DISCONNECT_REASON_REQUEST
@@ -977,8 +1054,10 @@ module Tinkerforge
977
1054
  # socket. the first receive will then fail directly
978
1055
  sleep 0.1
979
1056
 
980
- if @registered_callbacks.has_key? CALLBACK_DISCONNECTED
981
- @registered_callbacks[CALLBACK_DISCONNECTED].call parameter
1057
+ cb = @registered_callbacks[CALLBACK_DISCONNECTED]
1058
+
1059
+ if cb != nil
1060
+ cb.call parameter
982
1061
  end
983
1062
 
984
1063
  if parameter != DISCONNECT_REASON_REQUEST and @auto_reconnect and @auto_reconnect_allowed
@@ -1015,16 +1094,41 @@ module Tinkerforge
1015
1094
  uid = Packer.get_uid_from_data packet
1016
1095
  function_id = Packer.get_function_id_from_data packet
1017
1096
 
1018
- if function_id == CALLBACK_ENUMERATE and \
1019
- @registered_callbacks.has_key? CALLBACK_ENUMERATE
1097
+ if function_id == CALLBACK_ENUMERATE
1098
+ cb = @registered_callbacks[CALLBACK_ENUMERATE]
1099
+
1100
+ if cb == nil
1101
+ return
1102
+ end
1103
+
1104
+ if packet.length != 34
1105
+ return # silently ignoring callback with wrong length
1106
+ end
1107
+
1020
1108
  payload = Packer.unpack packet[8..-1], 'Z8 Z8 k C3 C3 S C'
1021
- @registered_callbacks[CALLBACK_ENUMERATE].call(*payload)
1022
- elsif @devices.has_key? uid
1023
- device = @devices[uid]
1109
+
1110
+ cb.call(*payload)
1111
+ return
1112
+ end
1113
+
1114
+ device = @devices[uid]
1115
+
1116
+ if device != nil
1117
+ begin
1118
+ device.check_validity
1119
+ rescue TinkerforgeException
1120
+ return # silently ignoring callback for invalid device
1121
+ end
1024
1122
 
1025
1123
  if device.high_level_callbacks.has_key?(-function_id)
1026
1124
  hlcb = device.high_level_callbacks[-function_id] # [roles, options, data]
1027
- payload = Packer.unpack packet[8..-1], device.callback_formats[function_id]
1125
+ format = device.callback_formats[function_id] # FIXME: currently assuming that low-level callback has more than one element
1126
+
1127
+ if packet.length != format[0]
1128
+ return # silently ignoring callback with wrong length
1129
+ end
1130
+
1131
+ payload = Packer.unpack packet[8..-1], format[1]
1028
1132
  has_data = false
1029
1133
  data = nil
1030
1134
 
@@ -1068,7 +1172,9 @@ module Tinkerforge
1068
1172
  end
1069
1173
  end
1070
1174
 
1071
- if has_data and device.registered_callbacks.has_key?(-function_id)
1175
+ cb = device.registered_callbacks[-function_id]
1176
+
1177
+ if has_data and cb != nil
1072
1178
  result = []
1073
1179
 
1074
1180
  hlcb[0].zip(payload).each do |role, value|
@@ -1079,14 +1185,27 @@ module Tinkerforge
1079
1185
  end
1080
1186
  end
1081
1187
 
1082
- device.registered_callbacks[-function_id].call(*result)
1188
+ cb.call(*result)
1083
1189
  end
1084
1190
  end
1085
1191
  end
1086
1192
 
1087
- if device.registered_callbacks.has_key? function_id
1088
- payload = Packer.unpack packet[8..-1], device.callback_formats[function_id]
1089
- device.registered_callbacks[function_id].call(*payload)
1193
+ cb = device.registered_callbacks[function_id]
1194
+
1195
+ if cb != nil
1196
+ format = device.callback_formats[function_id]
1197
+
1198
+ if format == nil
1199
+ return # silently ignore registered but unknown callback
1200
+ end
1201
+
1202
+ if packet.length != format[0]
1203
+ return # silently ignoring callback with wrong length
1204
+ end
1205
+
1206
+ payload = Packer.unpack packet[8..-1], format[1]
1207
+
1208
+ cb.call(*payload)
1090
1209
  end
1091
1210
  end
1092
1211
  end
@@ -1169,7 +1288,6 @@ module Tinkerforge
1169
1288
  def handle_response(packet)
1170
1289
  @disconnect_probe_flag = false
1171
1290
 
1172
- uid = Packer.get_uid_from_data packet
1173
1291
  function_id = Packer.get_function_id_from_data packet
1174
1292
  sequence_number = Packer.get_sequence_number_from_data packet
1175
1293
 
@@ -1177,9 +1295,13 @@ module Tinkerforge
1177
1295
  if @registered_callbacks.has_key? CALLBACK_ENUMERATE
1178
1296
  @callback.queue.push [QUEUE_KIND_PACKET, packet]
1179
1297
  end
1180
- elsif @devices.has_key? uid
1181
- device = @devices[uid]
1298
+ return
1299
+ end
1300
+
1301
+ uid = Packer.get_uid_from_data packet
1302
+ device = @devices[uid]
1182
1303
 
1304
+ if device != nil
1183
1305
  if sequence_number == 0
1184
1306
  if device.registered_callbacks.has_key? function_id or \
1185
1307
  device.high_level_callbacks.has_key?(-function_id)