ruby_home 0.2.1 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +41 -0
  3. data/.gitignore +2 -2
  4. data/.rubocop.yml +2 -9
  5. data/.standard.yml +3 -0
  6. data/CHANGELOG.md +18 -0
  7. data/Gemfile +2 -2
  8. data/README.md +40 -77
  9. data/Rakefile +4 -4
  10. data/examples/air_purifier.rb +66 -0
  11. data/examples/air_quality_sensor.rb +119 -0
  12. data/examples/battery_service.rb +58 -0
  13. data/examples/carbon_dioxide_sensor.rb +78 -0
  14. data/examples/carbon_monoxide_sensor.rb +78 -0
  15. data/examples/contact_sensor.rb +66 -0
  16. data/examples/door.rb +48 -0
  17. data/examples/fan.rb +30 -0
  18. data/examples/fan_v2.rb +68 -0
  19. data/examples/garage_door_opener.rb +71 -0
  20. data/examples/heater_cooler.rb +92 -0
  21. data/examples/humidifier_dehumidifier.rb +88 -0
  22. data/examples/humidity_sensor.rb +62 -0
  23. data/examples/leak_sensor.rb +66 -0
  24. data/examples/light_sensor.rb +64 -0
  25. data/examples/lightbulb.rb +31 -0
  26. data/examples/lock_mechanism.rb +34 -0
  27. data/examples/motion_sensor.rb +66 -0
  28. data/examples/occupancy_sensor.rb +66 -0
  29. data/examples/outlet.rb +29 -0
  30. data/examples/security_system.rb +53 -0
  31. data/examples/smoke_sensor.rb +66 -0
  32. data/examples/switch.rb +16 -0
  33. data/examples/television.rb +73 -0
  34. data/examples/temperature_sensor.rb +62 -0
  35. data/examples/thermostat.rb +113 -0
  36. data/examples/window.rb +48 -0
  37. data/examples/window_covering.rb +72 -0
  38. data/lib/ruby_home.rb +21 -22
  39. data/lib/ruby_home/accessory.rb +1 -1
  40. data/lib/ruby_home/accessory_collection.rb +6 -6
  41. data/lib/ruby_home/accessory_info.rb +18 -18
  42. data/lib/ruby_home/characteristic.rb +13 -7
  43. data/lib/ruby_home/characteristic_collection.rb +13 -13
  44. data/lib/ruby_home/config/categories.yml +39 -0
  45. data/lib/ruby_home/config/characteristics.yml +190 -319
  46. data/lib/ruby_home/config/manual_characteristics.yml +278 -0
  47. data/lib/ruby_home/config/manual_services.yml +45 -0
  48. data/lib/ruby_home/config/services.yml +338 -304
  49. data/lib/ruby_home/configuration.rb +21 -2
  50. data/lib/ruby_home/device_id.rb +3 -3
  51. data/lib/ruby_home/dns/service.rb +4 -6
  52. data/lib/ruby_home/dns/text_record.rb +10 -10
  53. data/lib/ruby_home/errors.rb +1 -0
  54. data/lib/ruby_home/factories/characteristic_factory.rb +38 -37
  55. data/lib/ruby_home/factories/service_factory.rb +72 -72
  56. data/lib/ruby_home/factories/templates/characteristic_template.rb +6 -6
  57. data/lib/ruby_home/factories/templates/service_template.rb +12 -11
  58. data/lib/ruby_home/hap/crypto/chacha20poly1305.rb +2 -2
  59. data/lib/ruby_home/hap/crypto/hkdf.rb +4 -4
  60. data/lib/ruby_home/hap/crypto/session_key.rb +7 -7
  61. data/lib/ruby_home/hap/decrypter.rb +8 -8
  62. data/lib/ruby_home/hap/encrypter.rb +5 -6
  63. data/lib/ruby_home/hap/ev_response.rb +17 -17
  64. data/lib/ruby_home/hap/hap_request.rb +1 -1
  65. data/lib/ruby_home/hap/server.rb +4 -4
  66. data/lib/ruby_home/hap/server_handler.rb +8 -10
  67. data/lib/ruby_home/hap/session.rb +22 -22
  68. data/lib/ruby_home/hap/values/base_value.rb +3 -3
  69. data/lib/ruby_home/hap/values/bool_value.rb +4 -4
  70. data/lib/ruby_home/hap/values/float_value.rb +4 -4
  71. data/lib/ruby_home/hap/values/identify_value.rb +1 -1
  72. data/lib/ruby_home/hap/values/int32_value.rb +4 -4
  73. data/lib/ruby_home/hap/values/null_value.rb +1 -1
  74. data/lib/ruby_home/hap/values/string_value.rb +11 -11
  75. data/lib/ruby_home/hap/values/uint32_value.rb +5 -5
  76. data/lib/ruby_home/hap/values/uint8_value.rb +14 -14
  77. data/lib/ruby_home/hex_helper.rb +3 -3
  78. data/lib/ruby_home/http/application.rb +7 -7
  79. data/lib/ruby_home/http/controllers/accessories_controller.rb +3 -3
  80. data/lib/ruby_home/http/controllers/application_controller.rb +6 -6
  81. data/lib/ruby_home/http/controllers/characteristics_controller.rb +29 -29
  82. data/lib/ruby_home/http/controllers/identify_controller.rb +10 -10
  83. data/lib/ruby_home/http/controllers/pair_setups_controller.rb +19 -19
  84. data/lib/ruby_home/http/controllers/pair_verifies_controller.rb +9 -9
  85. data/lib/ruby_home/http/controllers/pairings_controller.rb +6 -6
  86. data/lib/ruby_home/http/serializers/accessory_serializer.rb +5 -5
  87. data/lib/ruby_home/http/serializers/characteristic_serializer.rb +27 -19
  88. data/lib/ruby_home/http/serializers/characteristic_value_serializer.rb +5 -5
  89. data/lib/ruby_home/http/serializers/object_serializer.rb +1 -1
  90. data/lib/ruby_home/http/serializers/service_serializer.rb +19 -9
  91. data/lib/ruby_home/http/serializers/uuid_helper.rb +2 -2
  92. data/lib/ruby_home/http/services/session_notifier.rb +8 -8
  93. data/lib/ruby_home/http/services/start_srp_service.rb +3 -3
  94. data/lib/ruby_home/http/services/verify_finish_service.rb +22 -22
  95. data/lib/ruby_home/http/services/verify_srp_service.rb +22 -22
  96. data/lib/ruby_home/identifier_cache.rb +4 -5
  97. data/lib/ruby_home/password.rb +14 -14
  98. data/lib/ruby_home/persistable.rb +19 -12
  99. data/lib/ruby_home/service.rb +5 -2
  100. data/lib/ruby_home/service_collection.rb +1 -1
  101. data/lib/ruby_home/version.rb +1 -1
  102. data/rubyhome.gemspec +31 -31
  103. data/sbin/characteristic_generator.rb +22 -24
  104. data/sbin/service_generator.rb +38 -19
  105. metadata +85 -44
  106. data/.travis.yml +0 -31
@@ -0,0 +1,66 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ occupancy_sensor = RubyHome::ServiceFactory.create(:occupancy_sensor,
5
+ motion_detected: false, # required
6
+ name: "occupancy sensor", # optional
7
+ status_low_battery: 0, # optional
8
+ status_tampered: 0, # optional
9
+ status_fault: 0, # optional
10
+ status_active: true) # optional
11
+
12
+ occupancy_sensor.occupancy_detected.after_update do |occupancy_detected|
13
+ if occupancy_detected == 0
14
+ puts "occupancy sensor occupancy not detected"
15
+ else
16
+ puts "occupancy sensor occupancy detected"
17
+ end
18
+ end
19
+
20
+ occupancy_sensor.status_low_battery.after_update do |status_low_battery|
21
+ if status_low_battery == 0
22
+ puts "occupancy sensor battery level normal"
23
+ elsif status_low_battery == 1
24
+ puts "occupancy sensor battery level lormal"
25
+ end
26
+ end
27
+
28
+ occupancy_sensor.status_tampered.after_update do |status_tampered|
29
+ if status_tampered == 0
30
+ puts "occupancy sensor status_tampered not tampered"
31
+ elsif status_tampered == 1
32
+ puts "occupancy sensor status_tampered tampered"
33
+ end
34
+ end
35
+
36
+ occupancy_sensor.status_fault.after_update do |status_fault|
37
+ if status_fault == 0
38
+ puts "occupancy sensor status_fault no fault"
39
+ elsif status_fault == 1
40
+ puts "occupancy sensor status_fault general fault"
41
+ end
42
+ end
43
+
44
+ occupancy_sensor.status_active.after_update do |active|
45
+ if active
46
+ puts "occupancy sensor is active"
47
+ else
48
+ puts "occupancy sensor is inactive"
49
+ end
50
+ end
51
+
52
+ Thread.new do
53
+ sleep 30
54
+
55
+ loop do
56
+ occupancy_sensor.occupancy_detected = (0..1).to_a.sample
57
+ occupancy_sensor.status_low_battery = (0..1).to_a.sample
58
+ occupancy_sensor.status_tampered = (0..1).to_a.sample
59
+ occupancy_sensor.status_fault = (0..1).to_a.sample
60
+ occupancy_sensor.status_active = [true, false].to_a.sample
61
+
62
+ sleep 10
63
+ end
64
+ end
65
+
66
+ RubyHome.run
@@ -0,0 +1,29 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ outlet = RubyHome::ServiceFactory.create(:outlet,
5
+ outlet_in_use: false, # required
6
+ on: false, # required
7
+ name: "occupancy sensor") # optional
8
+
9
+ outlet.outlet_in_use.after_update do |outlet_in_use|
10
+ if outlet_in_use
11
+ puts "outlet in use"
12
+ else
13
+ puts "outlet not in use"
14
+ end
15
+ end
16
+
17
+ outlet.on.after_update do |on|
18
+ if on
19
+ puts "outlet is on"
20
+ sleep 1
21
+ outlet.outlet_in_use = true
22
+ else
23
+ puts "outlet is off"
24
+ sleep 1
25
+ outlet.outlet_in_use = false
26
+ end
27
+ end
28
+
29
+ RubyHome.run
@@ -0,0 +1,53 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ security_system = RubyHome::ServiceFactory.create(:security_system,
5
+ security_system_target_state: 0, # required
6
+ security_system_current_state: 0, # required
7
+ name: "security system", # optional
8
+ security_system_alarm_type: 0, # optional
9
+ status_tampered: 0, # optional
10
+ status_fault: 0) # optional
11
+
12
+ security_system_target_state_values = {
13
+ 0 => "Stay Arm",
14
+ 1 => "Away Arm",
15
+ 2 => "Night Arm",
16
+ 3 => "Disarm"
17
+ }
18
+ security_system.security_system_target_state.after_update do |security_system_target_state|
19
+ state = security_system_target_state_values[security_system_target_state]
20
+ puts "security system security_system_target_state #{state}"
21
+ sleep 1
22
+ security_system.security_system_current_state = security_system_target_state
23
+ end
24
+
25
+ security_system_current_state_values = {
26
+ 0 => "Stay Arm",
27
+ 1 => "Away Arm",
28
+ 2 => "Night Arm",
29
+ 3 => "Disarmed",
30
+ 4 => "Alarm Triggered"
31
+ }
32
+ security_system.security_system_current_state.after_update do |security_system_current_state|
33
+ state = security_system_current_state_values[security_system_current_state]
34
+ puts "security system security_system_current_state state #{state}"
35
+ end
36
+
37
+ security_system.status_tampered.after_update do |status_tampered|
38
+ if status_tampered == 0
39
+ puts "security system status_tampered not tampered"
40
+ elsif status_tampered == 1
41
+ puts "security system status_tampered tampered"
42
+ end
43
+ end
44
+
45
+ security_system.status_fault.after_update do |status_fault|
46
+ if status_fault == 0
47
+ puts "security system status_fault no fault"
48
+ elsif status_fault == 1
49
+ puts "security system status_fault general fault"
50
+ end
51
+ end
52
+
53
+ RubyHome.run
@@ -0,0 +1,66 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ smoke_sensor = RubyHome::ServiceFactory.create(:smoke_sensor,
5
+ smoke_detected: 0, # required
6
+ name: "smoke sensor", # optional
7
+ status_low_battery: 0, # optional
8
+ status_tampered: 0, # optional
9
+ status_fault: 0, # optional
10
+ status_active: true) # optional
11
+
12
+ smoke_sensor.smoke_detected.after_update do |smoke_detected|
13
+ if smoke_detected == 0
14
+ puts "smoke sensor smoke not detected"
15
+ elsif smoke_detected == 1
16
+ puts "smoke sensor smoke detected"
17
+ end
18
+ end
19
+
20
+ smoke_sensor.status_low_battery.after_update do |status_low_battery|
21
+ if status_low_battery == 0
22
+ puts "smoke sensor battery level normal"
23
+ elsif status_low_battery == 1
24
+ puts "smoke sensor battery level lormal"
25
+ end
26
+ end
27
+
28
+ smoke_sensor.status_tampered.after_update do |status_tampered|
29
+ if status_tampered == 0
30
+ puts "smoke sensor status_tampered not tampered"
31
+ elsif status_tampered == 1
32
+ puts "smoke sensor status_tampered tampered"
33
+ end
34
+ end
35
+
36
+ smoke_sensor.status_fault.after_update do |status_fault|
37
+ if status_fault == 0
38
+ puts "smoke sensor status_fault no fault"
39
+ elsif status_fault == 1
40
+ puts "smoke sensor status_fault general fault"
41
+ end
42
+ end
43
+
44
+ smoke_sensor.status_active.after_update do |active|
45
+ if active
46
+ puts "smoke sensor is active"
47
+ else
48
+ puts "smoke sensor is inactive"
49
+ end
50
+ end
51
+
52
+ Thread.new do
53
+ sleep 30
54
+
55
+ loop do
56
+ smoke_sensor.smoke_detected = (0..1).to_a.sample
57
+ smoke_sensor.status_low_battery = (0..1).to_a.sample
58
+ smoke_sensor.status_tampered = (0..1).to_a.sample
59
+ smoke_sensor.status_fault = (0..1).to_a.sample
60
+ smoke_sensor.status_active = [true, false].to_a.sample
61
+
62
+ sleep 10
63
+ end
64
+ end
65
+
66
+ RubyHome.run
@@ -0,0 +1,16 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ switch = RubyHome::ServiceFactory.create(:switch,
5
+ on: false, # required
6
+ name: "switch") # optional
7
+
8
+ switch.on.after_update do |on|
9
+ if on
10
+ puts "switch is on"
11
+ else
12
+ puts "switch is off"
13
+ end
14
+ end
15
+
16
+ RubyHome.run
@@ -0,0 +1,73 @@
1
+ require "ruby_home"
2
+
3
+ RubyHome.configure do |c|
4
+ c.discovery_name = "Television"
5
+ c.category_identifier = :television
6
+ end
7
+
8
+ accessory = RubyHome::Accessory.new
9
+
10
+ RubyHome::ServiceFactory.create(:accessory_information,
11
+ accessory: accessory) # required
12
+
13
+ television = RubyHome::ServiceFactory.create(:television,
14
+ accessory: accessory, # required
15
+ primary: true, # required
16
+ configured_name: "Television", # required
17
+ active: 1, # required
18
+ active_identifier: 1, # required
19
+ sleep_discovery_mode: 1, # required
20
+ remote_key: nil, # required
21
+ name: "Television", # optional
22
+ power_mode_selection: true, # optional
23
+ picture_mode: 4, # optional
24
+ target_media_state: 0, # optional
25
+ current_media_state: 0, # optional
26
+ brightness: 100) # optional
27
+
28
+ television.active.after_update do |active|
29
+ if active == 0
30
+ puts "television is inactive"
31
+ else
32
+ puts "television is active"
33
+ end
34
+ end
35
+
36
+ television.active_identifier.after_update do |active_identifier|
37
+ puts "television active input source #{active_identifier}"
38
+ end
39
+
40
+ television.remote_key.after_update do |remote_key|
41
+ puts "television remote_key #{remote_key}"
42
+ end
43
+
44
+ speaker = RubyHome::ServiceFactory.create(:television_speaker,
45
+ accessory: accessory, # required
46
+ mute: false, # required
47
+ name: "Television Volume", # optional
48
+ active: 1, # optional
49
+ volume_control_type: 1, # optional
50
+ volume_selector: 0) # optional
51
+ speaker.volume_selector.after_update do |volume|
52
+ if volume == 0
53
+ puts "television volume up"
54
+ else
55
+ puts "television volume down"
56
+ end
57
+ end
58
+
59
+ sources = (1..4).map do |index|
60
+ RubyHome::ServiceFactory.create(:input_source,
61
+ accessory: accessory, # required
62
+ subtype: "source#{index}", # required
63
+ name: "Source #{index}", # required
64
+ configured_name: "Source #{index}", # required
65
+ input_source_type: 3, # required
66
+ is_configured: 1, # required
67
+ current_visibility_state: 0, # required
68
+ identifier: index, # optional
69
+ input_device_type: 1) # optional
70
+ end
71
+ television.linked = [speaker] + sources
72
+
73
+ RubyHome.run
@@ -0,0 +1,62 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ temperature_sensor = RubyHome::ServiceFactory.create(:temperature_sensor,
5
+ current_temperature: 30, # required
6
+ name: "temperature sensor", # optional
7
+ status_low_battery: 0, # optional
8
+ status_tampered: 0, # optional
9
+ status_fault: 0, # optional
10
+ status_active: true) # optional
11
+
12
+ temperature_sensor.current_temperature.after_update do |current_temperature|
13
+ puts "temperature sensor current_temperature #{current_temperature}"
14
+ end
15
+
16
+ temperature_sensor.status_low_battery.after_update do |status_low_battery|
17
+ if status_low_battery == 0
18
+ puts "temperature sensor battery level normal"
19
+ elsif status_low_battery == 1
20
+ puts "temperature sensor battery level lormal"
21
+ end
22
+ end
23
+
24
+ temperature_sensor.status_tampered.after_update do |status_tampered|
25
+ if status_tampered == 0
26
+ puts "temperature sensor status_tampered not tampered"
27
+ elsif status_tampered == 1
28
+ puts "temperature sensor status_tampered tampered"
29
+ end
30
+ end
31
+
32
+ temperature_sensor.status_fault.after_update do |status_fault|
33
+ if status_fault == 0
34
+ puts "temperature sensor status_fault no fault"
35
+ elsif status_fault == 1
36
+ puts "temperature sensor status_fault general fault"
37
+ end
38
+ end
39
+
40
+ temperature_sensor.status_active.after_update do |active|
41
+ if active
42
+ puts "temperature sensor is active"
43
+ else
44
+ puts "temperature sensor is inactive"
45
+ end
46
+ end
47
+
48
+ Thread.new do
49
+ sleep 30
50
+
51
+ loop do
52
+ temperature_sensor.current_temperature = (0..100).to_a.sample
53
+ temperature_sensor.status_low_battery = (0..1).to_a.sample
54
+ temperature_sensor.status_tampered = (0..1).to_a.sample
55
+ temperature_sensor.status_fault = (0..1).to_a.sample
56
+ temperature_sensor.status_active = [true, false].to_a.sample
57
+
58
+ sleep 10
59
+ end
60
+ end
61
+
62
+ RubyHome.run
@@ -0,0 +1,113 @@
1
+ require "ruby_home"
2
+
3
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
4
+ thermostat = RubyHome::ServiceFactory.create(:thermostat,
5
+ temperature_display_units: 0, # required
6
+ target_temperature: 18, # required
7
+ current_temperature: 18, # required
8
+ target_heating_cooling_state: 0, # required
9
+ current_heating_cooling_state: 0, # required
10
+ name: "thermostat", # optional
11
+ heating_threshold_temperature: 20, # optional
12
+ cooling_threshold_temperature: 10, # optional
13
+ target_relative_humidity: 0, # optional
14
+ current_relative_humidity: 0) # optional
15
+
16
+ thermostat.temperature_display_units.after_update do |temperature_display_unit|
17
+ if temperature_display_unit == 0
18
+ puts "thermostat temperature display units Celsius"
19
+ elsif temperature_display_unit == 1
20
+ puts "thermostat temperature display units Fahrenheit"
21
+ end
22
+ end
23
+
24
+ thermostat.target_temperature.after_update do |target_temperature|
25
+ puts "thermostat target_temperature #{target_temperature}"
26
+
27
+ if target_temperature.to_i > thermostat.current_temperature.to_i
28
+ thermostat.target_heating_cooling_state = 1
29
+ elsif target_temperature < thermostat.current_temperature
30
+ thermostat.target_heating_cooling_state = 2
31
+ elsif target_temperature.to_i == thermostat.current_temperature.to_i
32
+ thermostat.target_heating_cooling_state = 0
33
+ end
34
+ end
35
+
36
+ thermostat.current_temperature.after_update do |current_temperature|
37
+ puts "thermostat current_temperature #{current_temperature}"
38
+
39
+ if current_temperature.to_i < thermostat.target_temperature.to_i
40
+ thermostat.target_heating_cooling_state = 1
41
+ elsif current_temperature.to_i > thermostat.target_temperature.to_i
42
+ thermostat.target_heating_cooling_state = 2
43
+ elsif current_temperature.to_i == thermostat.target_temperature.to_i
44
+ thermostat.target_heating_cooling_state = 0
45
+ end
46
+ end
47
+
48
+ target_heating_cooling_state_values = {
49
+ 0 => "Off",
50
+ 1 => "Heat",
51
+ 2 => "Cool",
52
+ 3 => "Auto"
53
+ }
54
+ thermostat.target_heating_cooling_state.after_update do |target_heating_cooling_state|
55
+ state = target_heating_cooling_state_values[target_heating_cooling_state]
56
+ puts "heater cooler target heating cooler state is #{state}"
57
+
58
+ return true if thermostat.current_heating_cooling_state == target_heating_cooling_state
59
+
60
+ if target_heating_cooling_state == 1
61
+ thermostat.current_heating_cooling_state = 1
62
+ elsif target_heating_cooling_state == 2
63
+ thermostat.current_heating_cooling_state = 2
64
+ elsif target_heating_cooling_state == 0
65
+ thermostat.current_heating_cooling_state = 0
66
+ end
67
+ end
68
+
69
+ current_heating_cooling_state_values = {
70
+ 0 => "Off",
71
+ 1 => "Heat",
72
+ 2 => "Cool"
73
+ }
74
+ thermostat.current_heating_cooling_state.after_update do |current_heating_cooling_state|
75
+ state = current_heating_cooling_state_values[current_heating_cooling_state]
76
+ puts "heater cooler current heating cooler state is #{state}"
77
+ end
78
+
79
+ thermostat.heating_threshold_temperature.after_update do |heating_threshold_temperature|
80
+ # maximum_value: 25
81
+ # minimum_value: 0
82
+ # step_value: 0.1
83
+ puts "heater cooler heating threshold temperature #{heating_threshold_temperature}"
84
+ end
85
+
86
+ thermostat.cooling_threshold_temperature.after_update do |cooling_threshold_temperature|
87
+ # maximum_value: 35
88
+ # minimum_value: 10
89
+ # step_value: 0.1
90
+ puts "heater cooler cooling threshold temperature temperature #{cooling_threshold_temperature}"
91
+ end
92
+
93
+ thermostat.target_relative_humidity.after_update do |target_relative_humidity|
94
+ puts "thermostat target_relative_humidity #{target_relative_humidity}"
95
+ end
96
+
97
+ thermostat.current_relative_humidity.after_update do |current_relative_humidity|
98
+ puts "thermostat current_relative_humidity #{current_relative_humidity}"
99
+ end
100
+
101
+ Thread.new do
102
+ loop do
103
+ sleep 5
104
+
105
+ if thermostat.target_temperature.to_i > thermostat.current_temperature.to_i
106
+ thermostat.current_temperature += 1
107
+ elsif thermostat.target_temperature.to_i < thermostat.current_temperature.to_i
108
+ thermostat.current_temperature -= 1
109
+ end
110
+ end
111
+ end
112
+
113
+ RubyHome.run