Class: Ecobee::Thermostat

Inherits:
Hash
  • Object
show all
Defined in:
lib/ecobee/thermostat.rb

Constant Summary collapse

DEFAULT_SELECTION_ARGS =
{
  includeRuntime: true,
  includeExtendedRuntime: true,
  includeElectricity: true,
  includeSettings: true,
  includeLocation: true,
  includeProgram: true,
  includeEvents: true,
  includeDevice: true,
  includeTechnician: true,
  includeUtility: true,
  includeAlerts: true,
  includeWeather: true,
  includeOemConfig: true,
  includeEquipmentStatus: true,
  includeNotificationSettings: true,
  includeVersion: true,
  includeSensors: true
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(auto_refresh: 0, fake_index: nil, index: 0, fake_max_index: 0, selection: nil, selection_args: {}, token: nil) ⇒ Thermostat

Returns a new instance of Thermostat.

Raises:

  • (ArgumentError)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ecobee/thermostat.rb', line 29

def initialize(
  auto_refresh: 0,
  fake_index: nil,
  index: 0,
  fake_max_index: 0,
  selection: nil,
  selection_args: {},
  token: nil
)
  # TODO: add auto-refresh thread handling
  @auto_refresh = auto_refresh

  raise ArgumentError.new('No token: specified') unless token
  @http = token.http
  @fake_index = fake_index
  @fake_max_index = fake_max_index
  @index = index
  @selection ||= Ecobee::Selection(
    DEFAULT_SELECTION_ARGS.merge(selection_args)
  )
  refresh
end

Instance Attribute Details

#auto_refreshObject (readonly)

Returns the value of attribute auto_refresh.



27
28
29
# File 'lib/ecobee/thermostat.rb', line 27

def auto_refresh
  @auto_refresh
end

#httpObject (readonly)

Returns the value of attribute http.



27
28
29
# File 'lib/ecobee/thermostat.rb', line 27

def http
  @http
end

Instance Method Details

#acknowledge(ack_ref: nil, ack_type: 'accept') ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ecobee/thermostat.rb', line 52

def acknowledge(
  ack_ref: nil,
  ack_type: 'accept'
)
  params = { 
    'ackRef' => ack_ref,
    'ackType' => ack_type,
    'thermostatIdentifier' => self[:identifier]
  }
  update(functions: [{ 'type' => 'acknowledge', 'params' => params }])
end

#celsius?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/ecobee/thermostat.rb', line 64

def celsius?
  self[:settings][:useCelsius]
end

#cool_range(with_delta: false) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/ecobee/thermostat.rb', line 68

def cool_range(with_delta: false)
  if with_delta
    low_range = [unitize(self[:settings][:coolRangeLow]),
                 desired_heat + heat_cool_min_delta].max
  else
    low_range = unitize(self[:settings][:coolRangeLow])
  end
  to_range(low_range, unitize(self[:settings][:coolRangeHigh]))
end

#desired_coolObject



86
87
88
# File 'lib/ecobee/thermostat.rb', line 86

def desired_cool
  unitize(self[:runtime][:desiredCool])
end

#desired_cool=(temp) ⇒ Object



90
91
92
# File 'lib/ecobee/thermostat.rb', line 90

def desired_cool=(temp)
  set_hold(cool_hold_temp: temp)
end

#desired_fan_modeObject



94
95
96
# File 'lib/ecobee/thermostat.rb', line 94

def desired_fan_mode
  self[:runtime][:desiredFanMode]
end

#desired_fan_mode=(fan) ⇒ Object



98
99
100
# File 'lib/ecobee/thermostat.rb', line 98

def desired_fan_mode=(fan)
  set_hold(fan: fan)
end

#desired_heatObject



102
103
104
# File 'lib/ecobee/thermostat.rb', line 102

def desired_heat
  unitize(self[:runtime][:desiredHeat])
end

#desired_heat=(temp) ⇒ Object



106
107
108
109
# File 'lib/ecobee/thermostat.rb', line 106

def desired_heat=(temp)
  # need celcius un_unitize
  set_hold(heat_hold_temp: temp)
end

#desired_rangeObject



111
112
113
# File 'lib/ecobee/thermostat.rb', line 111

def desired_range
  to_range(desired_heat, desired_cool)
end

#dump(pretty: true) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/ecobee/thermostat.rb', line 78

def dump(pretty: true)
  if pretty
    self.select { |k, v| k.is_a? Symbol }.pretty_inspect
  else
    self.select { |k, v| k.is_a? Symbol }
  end
end

#heat_cool_min_deltaObject



115
116
117
# File 'lib/ecobee/thermostat.rb', line 115

def heat_cool_min_delta
  unitize(self[:settings][:heatCoolMinDelta])
end

#heat_range(with_delta: false) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/ecobee/thermostat.rb', line 119

def heat_range(with_delta: false)
  if with_delta
    high_range = [unitize(self[:settings][:heatRangeHigh]),
                 desired_cool - heat_cool_min_delta].min
  else
    high_range = unitize(self[:settings][:heatRangeHigh])
  end
  to_range(unitize(self[:settings][:heatRangeLow]), high_range)
end

#humidityObject



129
130
131
# File 'lib/ecobee/thermostat.rb', line 129

def humidity
  self[:runtime][:actualHumidity]
end

#indexObject



133
134
135
# File 'lib/ecobee/thermostat.rb', line 133

def index
  @fake_index || @index
end

#max_indexObject



137
138
139
# File 'lib/ecobee/thermostat.rb', line 137

def max_index
  [@fake_index || 0, @max_index, @fake_max_index].max
end

#modeObject



141
142
143
# File 'lib/ecobee/thermostat.rb', line 141

def mode
  self[:settings][:hvacMode]
end

#mode=(mode) ⇒ Object



145
146
147
# File 'lib/ecobee/thermostat.rb', line 145

def mode=(mode)
  set_mode(mode)
end

#modelObject



149
150
151
# File 'lib/ecobee/thermostat.rb', line 149

def model
  Ecobee::Model(self[:modelNumber])
end

#my_selectionObject



153
154
155
156
157
158
159
160
# File 'lib/ecobee/thermostat.rb', line 153

def my_selection
  { 
    'selection' => {
      'selectionType' => 'thermostats',
      'selectionMatch' => self[:identifier]
    }
  }
end

#nameObject



162
163
164
165
166
167
168
# File 'lib/ecobee/thermostat.rb', line 162

def name
  if @fake_index
    "Fake No. #{@fake_index}"
  else
    self[:name]
  end
end

#refreshObject



170
171
172
173
174
175
176
177
178
179
# File 'lib/ecobee/thermostat.rb', line 170

def refresh
  response = @http.get(arg: :thermostat, options: @selection)
  if @index + 1 > response['thermostatList'].length
    raise ThermostatError.new('No such thermostat')
  end
  @max_index = response['thermostatList'].length - 1
  list = response['thermostatList'][@index]
 
  self.replace list.merge(to_sym(list))
end

#set_hold(cool_hold_temp: unitize(self[:runtime][:desiredCool]), fan: nil, heat_hold_temp: unitize(self[:runtime][:desiredHeat]), hold_type: 'nextTransition') ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/ecobee/thermostat.rb', line 181

def set_hold(
  cool_hold_temp: unitize(self[:runtime][:desiredCool]),
  fan: nil,
  heat_hold_temp: unitize(self[:runtime][:desiredHeat]),
  hold_type: 'nextTransition'
)
  params = { 
    'holdType' => 'nextTransition',
    'coolHoldTemp' => un_unitize(cool_hold_temp),
    'heatHoldTemp' => un_unitize(heat_hold_temp)
  }
  params.merge!({ 'fan' => fan }) if fan
  update(functions: [{ 'type' => 'setHold', 'params' => params }])
end

#set_mode(mode) ⇒ Object



196
197
198
# File 'lib/ecobee/thermostat.rb', line 196

def set_mode(mode)
  update(thermostat: { 'settings' => { 'hvacMode' => mode } })
end

#temperatureObject



200
201
202
# File 'lib/ecobee/thermostat.rb', line 200

def temperature
  unitize(self[:runtime][:actualTemperature])
end

#to_range(low, high) ⇒ Object



204
205
206
207
208
209
210
211
# File 'lib/ecobee/thermostat.rb', line 204

def to_range(low, high)
  if celsius?
    ((low * 2).round..(high * 2).round).to_a
      .map { |deg| deg / 2.0 }
  else
    (low.round..high.round).to_a
  end
end

#to_sym(obj = self) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/ecobee/thermostat.rb', line 213

def to_sym(obj = self)
  if obj.is_a? Hash
    Hash[obj.map do |key, val|
          if key.is_a? String
            [key.to_sym, to_sym(val)]
          else
            [key, to_sym(val)]
          end
        end]
  elsif obj.is_a? Array
    obj.map { |item| to_sym(item) }
  else
    obj
  end
end

#un_unitize(value) ⇒ Object



229
230
231
232
233
234
235
# File 'lib/ecobee/thermostat.rb', line 229

def un_unitize(value)
  if celsius?
    (((value.to_f * 9/5) + 32) * 10).round
  else
    (value.to_f * 10).round
  end
end

#unitize(value) ⇒ Object

converts Ecobee farenheit * 10 integer input, returns

farenheit or celsius output rounded to nearest .5


239
240
241
242
243
244
245
246
# File 'lib/ecobee/thermostat.rb', line 239

def unitize(value)
  if celsius?
    celsius = (value.to_f / 10.0 - 32) * 5/9
    (celsius / 5).round(1) * 5
  else
    value.to_f / 10.0
  end
end

#update(functions: nil, thermostat: nil) ⇒ Object



248
249
250
251
252
253
254
255
256
# File 'lib/ecobee/thermostat.rb', line 248

def update(
  functions: nil,
  thermostat: nil
)
  body = my_selection
  body.merge!({ 'functions' => functions }) if functions
  body.merge!({ 'thermostat' => thermostat }) if thermostat
  @http.post(arg: :thermostat, body: body)
end