tinkerforge 2.1.23 → 2.1.28

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 (146) hide show
  1. checksums.yaml +5 -5
  2. data/lib/tinkerforge/brick_dc.rb +156 -75
  3. data/lib/tinkerforge/brick_hat.rb +109 -30
  4. data/lib/tinkerforge/brick_hat_zero.rb +119 -21
  5. data/lib/tinkerforge/brick_imu.rb +191 -86
  6. data/lib/tinkerforge/brick_imu_v2.rb +219 -118
  7. data/lib/tinkerforge/brick_master.rb +495 -195
  8. data/lib/tinkerforge/brick_red.rb +197 -74
  9. data/lib/tinkerforge/brick_servo.rb +186 -102
  10. data/lib/tinkerforge/brick_silent_stepper.rb +248 -168
  11. data/lib/tinkerforge/brick_stepper.rb +212 -100
  12. data/lib/tinkerforge/bricklet_accelerometer.rb +61 -36
  13. data/lib/tinkerforge/bricklet_accelerometer_v2.rb +107 -63
  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 +75 -47
  31. data/lib/tinkerforge/bricklet_color_v2.rb +91 -47
  32. data/lib/tinkerforge/bricklet_compass.rb +81 -40
  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 +68 -33
  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 +81 -40
  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 +99 -51
  77. data/lib/tinkerforge/bricklet_lcd_128x64.rb +219 -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 +76 -39
  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 +75 -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_performance_dc.rb +676 -0
  102. data/lib/tinkerforge/bricklet_piezo_buzzer.rb +19 -13
  103. data/lib/tinkerforge/bricklet_piezo_speaker.rb +22 -19
  104. data/lib/tinkerforge/bricklet_piezo_speaker_v2.rb +84 -57
  105. data/lib/tinkerforge/bricklet_ptc.rb +76 -51
  106. data/lib/tinkerforge/bricklet_ptc_v2.rb +96 -54
  107. data/lib/tinkerforge/bricklet_real_time_clock.rb +45 -36
  108. data/lib/tinkerforge/bricklet_real_time_clock_v2.rb +78 -47
  109. data/lib/tinkerforge/bricklet_remote_switch.rb +38 -29
  110. data/lib/tinkerforge/bricklet_remote_switch_v2.rb +86 -49
  111. data/lib/tinkerforge/bricklet_rgb_led.rb +17 -8
  112. data/lib/tinkerforge/bricklet_rgb_led_button.rb +61 -30
  113. data/lib/tinkerforge/bricklet_rgb_led_matrix.rb +78 -33
  114. data/lib/tinkerforge/bricklet_rgb_led_v2.rb +51 -20
  115. data/lib/tinkerforge/bricklet_rotary_encoder.rb +40 -25
  116. data/lib/tinkerforge/bricklet_rotary_encoder_v2.rb +60 -27
  117. data/lib/tinkerforge/bricklet_rotary_poti.rb +55 -37
  118. data/lib/tinkerforge/bricklet_rotary_poti_v2.rb +57 -26
  119. data/lib/tinkerforge/bricklet_rs232.rb +89 -28
  120. data/lib/tinkerforge/bricklet_rs232_v2.rb +121 -47
  121. data/lib/tinkerforge/bricklet_rs485.rb +250 -164
  122. data/lib/tinkerforge/bricklet_segment_display_4x7.rb +24 -14
  123. data/lib/tinkerforge/bricklet_segment_display_4x7_v2.rb +75 -36
  124. data/lib/tinkerforge/bricklet_servo_v2.rb +565 -0
  125. data/lib/tinkerforge/bricklet_solid_state_relay.rb +24 -13
  126. data/lib/tinkerforge/bricklet_solid_state_relay_v2.rb +58 -25
  127. data/lib/tinkerforge/bricklet_sound_intensity.rb +36 -24
  128. data/lib/tinkerforge/bricklet_sound_pressure_level.rb +77 -41
  129. data/lib/tinkerforge/bricklet_temperature.rb +43 -28
  130. data/lib/tinkerforge/bricklet_temperature_ir.rb +61 -47
  131. data/lib/tinkerforge/bricklet_temperature_ir_v2.rb +74 -44
  132. data/lib/tinkerforge/bricklet_temperature_v2.rb +62 -31
  133. data/lib/tinkerforge/bricklet_thermal_imaging.rb +118 -68
  134. data/lib/tinkerforge/bricklet_thermocouple.rb +46 -30
  135. data/lib/tinkerforge/bricklet_thermocouple_v2.rb +65 -30
  136. data/lib/tinkerforge/bricklet_tilt.rb +23 -10
  137. data/lib/tinkerforge/bricklet_uv_light.rb +37 -24
  138. data/lib/tinkerforge/bricklet_uv_light_v2.rb +87 -46
  139. data/lib/tinkerforge/bricklet_voltage.rb +54 -37
  140. data/lib/tinkerforge/bricklet_voltage_current.rb +94 -85
  141. data/lib/tinkerforge/bricklet_voltage_current_v2.rb +92 -77
  142. data/lib/tinkerforge/bricklet_xmc1400_breakout.rb +81 -36
  143. data/lib/tinkerforge/device_display_names.rb +167 -0
  144. data/lib/tinkerforge/ip_connection.rb +156 -33
  145. data/lib/tinkerforge/version.rb +1 -1
  146. metadata +8 -3
@@ -0,0 +1,167 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+ #############################################################
3
+ # This file was automatically generated on 2021-01-15. #
4
+ # #
5
+ # Ruby Bindings Version 2.1.28 #
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
+ 2156 => 'Performance DC Bricklet',
152
+ 2157 => 'Servo Bricklet 2.0',
153
+ 2161 => 'IMU Bricklet 3.0',
154
+ 2162 => 'Industrial Dual AC Relay Bricklet'
155
+ }
156
+
157
+ # internal
158
+ def get_device_display_name(device_identifier)
159
+ device_display_name = DEVICE_DISPLAY_NAMES[device_identifier]
160
+
161
+ if device_display_name == nil
162
+ device_display_name = "Unknown Device [#{device_identifier}]"
163
+ end
164
+
165
+ device_display_name
166
+ end
167
+ 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 = ''
@@ -131,7 +143,8 @@ module Tinkerforge
131
143
  u = []
132
144
 
133
145
  if f0 == '?'
134
- r = data.unpack "C#{f1}a*"
146
+ n1 = (Integer(f1) / 8.0).ceil()
147
+ r = data.unpack "C#{n1}a*"
135
148
  data = r[-1]
136
149
  r.delete_at(-1)
137
150
 
@@ -207,12 +220,18 @@ module Tinkerforge
207
220
  end
208
221
  end
209
222
 
223
+ # internal
210
224
  class Device
225
+ DEVICE_IDENTIFIER_CHECK_PENDING = 0
226
+ DEVICE_IDENTIFIER_CHECK_MATCH = 1
227
+ DEVICE_IDENTIFIER_CHECK_MISMATCH = 2
228
+
211
229
  RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0
212
230
  RESPONSE_EXPECTED_ALWAYS_TRUE = 1 # getter
213
231
  RESPONSE_EXPECTED_TRUE = 2 # setter
214
232
  RESPONSE_EXPECTED_FALSE = 3 # setter, default
215
233
 
234
+ attr_accessor :replaced
216
235
  attr_accessor :uid
217
236
  attr_accessor :expected_response_function_id
218
237
  attr_accessor :expected_response_sequence_number
@@ -220,10 +239,11 @@ module Tinkerforge
220
239
  attr_accessor :high_level_callbacks
221
240
  attr_accessor :registered_callbacks
222
241
 
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)
242
+ # internal
243
+ def initialize(uid, ipcon, device_identifier, device_display_name)
244
+ @replaced = false
226
245
  @uid = Base58.decode uid
246
+ @uid_string = uid
227
247
 
228
248
  if @uid > (1 << 64) - 1
229
249
  raise ArgumentError, "UID '#{uid}' is too big"
@@ -249,6 +269,12 @@ module Tinkerforge
249
269
 
250
270
  @ipcon = ipcon
251
271
 
272
+ @device_identifier = device_identifier
273
+ @device_display_name = device_display_name
274
+ @device_identifier_lock = Mutex.new
275
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_PENDING # protected by device_identifier_lock
276
+ @wrong_device_display_name = '?' # protected by device_identifier_lock
277
+
252
278
  @request_mutex = Mutex.new
253
279
 
254
280
  @response_expected = Array.new(256, RESPONSE_EXPECTED_INVALID_FUNCTION_ID)
@@ -265,8 +291,6 @@ module Tinkerforge
265
291
  @callback_formats = {}
266
292
  @high_level_callbacks = {}
267
293
  @registered_callbacks = {}
268
-
269
- @ipcon.devices[@uid] = self # FIXME: use a weakref here
270
294
  end
271
295
 
272
296
  # Returns the API version (major, minor, revision) of the bindings for
@@ -288,7 +312,7 @@ module Tinkerforge
288
312
  # Enabling the response expected flag for a setter function allows to
289
313
  # detect timeouts and other error conditions calls of this setter as
290
314
  # 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
315
+ # flag is disabled for a setter function then no response is sent and
292
316
  # errors are silently ignored, because they cannot be detected.
293
317
  def get_response_expected(function_id)
294
318
  if function_id < 0 or function_id > 255
@@ -317,7 +341,7 @@ module Tinkerforge
317
341
  # Enabling the response expected flag for a setter function allows to
318
342
  # detect timeouts and other error conditions calls of this setter as
319
343
  # 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
344
+ # flag is disabled for a setter function then no response is sent and
321
345
  # errors are silently ignored, because they cannot be detected.
322
346
  def set_response_expected(function_id, response_expected)
323
347
  if function_id < 0 or function_id > 255
@@ -360,7 +384,7 @@ module Tinkerforge
360
384
 
361
385
  # internal
362
386
  def send_request(function_id, request_data, request_format,
363
- response_length, response_format)
387
+ expected_response_length, response_format)
364
388
  response = nil
365
389
 
366
390
  if request_data.length > 0
@@ -402,7 +426,13 @@ module Tinkerforge
402
426
  error_code = Packer.get_error_code_from_data packet
403
427
 
404
428
  if error_code == 0
405
- # no error
429
+ if expected_response_length == 0
430
+ expected_response_length = 8 # setter with response-expected enabled
431
+ end
432
+
433
+ if packet.length != expected_response_length
434
+ raise WrongResponseLengthException, "Expected response of #{expected_response_length} byte for function ID #{function_id}, got #{packet.length} byte instead"
435
+ end
406
436
  elsif error_code == 1
407
437
  raise InvalidParameterException, "Got invalid parameter for function ID #{function_id}"
408
438
  elsif error_code == 2
@@ -411,7 +441,7 @@ module Tinkerforge
411
441
  raise UnknownErrorCodeException, "Function ID #{function_id} returned an unknown error"
412
442
  end
413
443
 
414
- if response_length > 0
444
+ if response_format.length > 0
415
445
  response = Packer.unpack packet[8..-1], response_format
416
446
 
417
447
  if response.length == 1
@@ -449,6 +479,34 @@ module Tinkerforge
449
479
 
450
480
  response
451
481
  end
482
+
483
+ # internal
484
+ def check_validity()
485
+ if @replaced
486
+ raise DeviceReplacedException, 'Device has been replaced'
487
+ end
488
+
489
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MATCH
490
+ return
491
+ end
492
+
493
+ @device_identifier_lock.synchronize {
494
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_PENDING
495
+ device_identifier = send_request(255, [], '', 33, 'Z8 Z8 k C3 C3 S')[5] # <device>.get_identity
496
+
497
+ if device_identifier == @device_identifier
498
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MATCH
499
+ else
500
+ @device_identifier_check = DEVICE_IDENTIFIER_CHECK_MISMATCH
501
+ @wrong_device_display_name = get_device_display_name device_identifier
502
+ end
503
+ end
504
+
505
+ if @device_identifier_check == DEVICE_IDENTIFIER_CHECK_MISMATCH
506
+ raise WrongDeviceTypeException, "UID #{@uid_string} belongs to a #{@wrong_device_display_name} instead of the expected #{@device_display_name}"
507
+ end
508
+ }
509
+ end
452
510
  end
453
511
 
454
512
  # internal
@@ -474,16 +532,18 @@ module Tinkerforge
474
532
  # Creates an object with the unique device ID <tt>uid</tt> and adds it to
475
533
  # the IP Connection <tt>ipcon</tt>.
476
534
  def initialize(uid, ipcon)
477
- super uid, ipcon
535
+ super uid, ipcon, 0, 'Brick Daemon'
478
536
 
479
537
  @api_version = [2, 0, 0]
480
538
 
481
539
  @response_expected[FUNCTION_GET_AUTHENTICATION_NONCE] = RESPONSE_EXPECTED_ALWAYS_TRUE
482
540
  @response_expected[FUNCTION_AUTHENTICATE] = RESPONSE_EXPECTED_TRUE
541
+
542
+ @ipcon.add_device self
483
543
  end
484
544
 
485
545
  def get_authentication_nonce
486
- send_request FUNCTION_GET_AUTHENTICATION_NONCE, [], '', 4, 'C4'
546
+ send_request FUNCTION_GET_AUTHENTICATION_NONCE, [], '', 12, 'C4'
487
547
  end
488
548
 
489
549
  def authenticate(client_nonce, digest)
@@ -492,7 +552,6 @@ module Tinkerforge
492
552
  end
493
553
 
494
554
  class IPConnection
495
- attr_accessor :devices
496
555
  attr_accessor :timeout
497
556
 
498
557
  CALLBACK_ENUMERATE = 253
@@ -538,6 +597,7 @@ module Tinkerforge
538
597
  @authentication_mutex = Mutex.new # protects authentication handshake
539
598
 
540
599
  @devices = {}
600
+ @replace_mutex = Mutex.new # used to synchronize replacements in the devices dict
541
601
 
542
602
  @registered_callbacks = {}
543
603
 
@@ -628,6 +688,9 @@ module Tinkerforge
628
688
  # For more information about authentication see
629
689
  # https://www.tinkerforge.com/en/doc/Tutorials/Tutorial_Authentication/Tutorial.html
630
690
  def authenticate(secret)
691
+ if not secret.ascii_only?
692
+ raise ArgumentError, "Authentication secret contains non-ASCII characters"
693
+ end
631
694
  @authentication_mutex.synchronize {
632
695
  if @next_authentication_nonce == 0
633
696
  @next_authentication_nonce = SecureRandom.random_number(1 << 32)
@@ -728,6 +791,19 @@ module Tinkerforge
728
791
  @registered_callbacks[id] = callback
729
792
  end
730
793
 
794
+ # internal
795
+ def add_device(device)
796
+ @replace_mutex.synchronize {
797
+ replaced_device = @devices.fetch device.uid, nil
798
+
799
+ if replaced_device != nil
800
+ replaced_device.replaced = true
801
+ end
802
+
803
+ @devices[device.uid] = device # FIXME: use a weakref here
804
+ }
805
+ end
806
+
731
807
  # internal
732
808
  def get_next_sequence_number
733
809
  @sequence_number_mutex.synchronize {
@@ -948,8 +1024,10 @@ module Tinkerforge
948
1024
  # internal
949
1025
  def dispatch_meta(function_id, parameter, socket_id)
950
1026
  if function_id == CALLBACK_CONNECTED
951
- if @registered_callbacks.has_key? CALLBACK_CONNECTED
952
- @registered_callbacks[CALLBACK_CONNECTED].call parameter
1027
+ cb = @registered_callbacks[CALLBACK_CONNECTED]
1028
+
1029
+ if cb != nil
1030
+ cb.call parameter
953
1031
  end
954
1032
  elsif function_id == CALLBACK_DISCONNECTED
955
1033
  if parameter != DISCONNECT_REASON_REQUEST
@@ -977,8 +1055,10 @@ module Tinkerforge
977
1055
  # socket. the first receive will then fail directly
978
1056
  sleep 0.1
979
1057
 
980
- if @registered_callbacks.has_key? CALLBACK_DISCONNECTED
981
- @registered_callbacks[CALLBACK_DISCONNECTED].call parameter
1058
+ cb = @registered_callbacks[CALLBACK_DISCONNECTED]
1059
+
1060
+ if cb != nil
1061
+ cb.call parameter
982
1062
  end
983
1063
 
984
1064
  if parameter != DISCONNECT_REASON_REQUEST and @auto_reconnect and @auto_reconnect_allowed
@@ -1015,16 +1095,41 @@ module Tinkerforge
1015
1095
  uid = Packer.get_uid_from_data packet
1016
1096
  function_id = Packer.get_function_id_from_data packet
1017
1097
 
1018
- if function_id == CALLBACK_ENUMERATE and \
1019
- @registered_callbacks.has_key? CALLBACK_ENUMERATE
1098
+ if function_id == CALLBACK_ENUMERATE
1099
+ cb = @registered_callbacks[CALLBACK_ENUMERATE]
1100
+
1101
+ if cb == nil
1102
+ return
1103
+ end
1104
+
1105
+ if packet.length != 34
1106
+ return # silently ignoring callback with wrong length
1107
+ end
1108
+
1020
1109
  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]
1110
+
1111
+ cb.call(*payload)
1112
+ return
1113
+ end
1114
+
1115
+ device = @devices[uid]
1116
+
1117
+ if device != nil
1118
+ begin
1119
+ device.check_validity
1120
+ rescue TinkerforgeException
1121
+ return # silently ignoring callback for invalid device
1122
+ end
1024
1123
 
1025
1124
  if device.high_level_callbacks.has_key?(-function_id)
1026
1125
  hlcb = device.high_level_callbacks[-function_id] # [roles, options, data]
1027
- payload = Packer.unpack packet[8..-1], device.callback_formats[function_id]
1126
+ format = device.callback_formats[function_id] # FIXME: currently assuming that low-level callback has more than one element
1127
+
1128
+ if packet.length != format[0]
1129
+ return # silently ignoring callback with wrong length
1130
+ end
1131
+
1132
+ payload = Packer.unpack packet[8..-1], format[1]
1028
1133
  has_data = false
1029
1134
  data = nil
1030
1135
 
@@ -1068,7 +1173,9 @@ module Tinkerforge
1068
1173
  end
1069
1174
  end
1070
1175
 
1071
- if has_data and device.registered_callbacks.has_key?(-function_id)
1176
+ cb = device.registered_callbacks[-function_id]
1177
+
1178
+ if has_data and cb != nil
1072
1179
  result = []
1073
1180
 
1074
1181
  hlcb[0].zip(payload).each do |role, value|
@@ -1079,14 +1186,27 @@ module Tinkerforge
1079
1186
  end
1080
1187
  end
1081
1188
 
1082
- device.registered_callbacks[-function_id].call(*result)
1189
+ cb.call(*result)
1083
1190
  end
1084
1191
  end
1085
1192
  end
1086
1193
 
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)
1194
+ cb = device.registered_callbacks[function_id]
1195
+
1196
+ if cb != nil
1197
+ format = device.callback_formats[function_id]
1198
+
1199
+ if format == nil
1200
+ return # silently ignore registered but unknown callback
1201
+ end
1202
+
1203
+ if packet.length != format[0]
1204
+ return # silently ignoring callback with wrong length
1205
+ end
1206
+
1207
+ payload = Packer.unpack packet[8..-1], format[1]
1208
+
1209
+ cb.call(*payload)
1090
1210
  end
1091
1211
  end
1092
1212
  end
@@ -1169,7 +1289,6 @@ module Tinkerforge
1169
1289
  def handle_response(packet)
1170
1290
  @disconnect_probe_flag = false
1171
1291
 
1172
- uid = Packer.get_uid_from_data packet
1173
1292
  function_id = Packer.get_function_id_from_data packet
1174
1293
  sequence_number = Packer.get_sequence_number_from_data packet
1175
1294
 
@@ -1177,9 +1296,13 @@ module Tinkerforge
1177
1296
  if @registered_callbacks.has_key? CALLBACK_ENUMERATE
1178
1297
  @callback.queue.push [QUEUE_KIND_PACKET, packet]
1179
1298
  end
1180
- elsif @devices.has_key? uid
1181
- device = @devices[uid]
1299
+ return
1300
+ end
1301
+
1302
+ uid = Packer.get_uid_from_data packet
1303
+ device = @devices[uid]
1182
1304
 
1305
+ if device != nil
1183
1306
  if sequence_number == 0
1184
1307
  if device.registered_callbacks.has_key? function_id or \
1185
1308
  device.high_level_callbacks.has_key?(-function_id)