renstar 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +23 -0
- data/LICENSE +21 -0
- data/README.md +85 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/renstar/api_client/api.json +206 -0
- data/lib/renstar/api_client/api_object.rb +40 -0
- data/lib/renstar/api_client/api_objects/alert.rb +13 -0
- data/lib/renstar/api_client/api_objects/info.rb +14 -0
- data/lib/renstar/api_client/api_objects/runtime.rb +13 -0
- data/lib/renstar/api_client/api_objects/sensor.rb +12 -0
- data/lib/renstar/api_client/control.rb +16 -0
- data/lib/renstar/api_client/query.rb +36 -0
- data/lib/renstar/api_client/settings.rb +16 -0
- data/lib/renstar/api_client.rb +49 -0
- data/lib/renstar/thermostat.rb +138 -0
- data/lib/renstar/version.rb +5 -0
- data/lib/renstar.rb +10 -0
- data/renstar.gemspec +39 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 11e7559010ba3e22d518b8b0ced9c1da2df22ed0ed9454dc1a5c48cfa2976ad3
|
4
|
+
data.tar.gz: ed103efb4673b76c61b1352f2ca3f400426afccede2788d0ae047fc441abcfd5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 13546148e8cec7fd6b228ffea5a41f59a77cc762c1cb5ef19908cdc11a536934c8d086a97077dd765efaab584512f7496227a91453428e692d123a513e21ab39
|
7
|
+
data.tar.gz: 71b61b017a0ce28ded19d4566c632d28e603ef76728e44bc16792b79c1722f6ff1b43f93e10842cf65cea6c1006da180a6dea33899ff0b2d29a5db5cea9d5ca4
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
renstar (0.1.0)
|
5
|
+
json
|
6
|
+
ssdp
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
json (2.6.1)
|
12
|
+
rake (13.0.6)
|
13
|
+
ssdp (1.1.7)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
x86_64-linux
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
rake (~> 13.0)
|
20
|
+
renstar!
|
21
|
+
|
22
|
+
BUNDLED WITH
|
23
|
+
2.2.22
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 mikerodrigues
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Renstar
|
2
|
+
|
3
|
+
Renstar is a Ruby SDK for interacting with the Venstar API.
|
4
|
+
|
5
|
+
You can control your thermostat programmatically!
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'renstar'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install renstar
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
* Search for thermostats on the LAN, return the first one found:
|
26
|
+
```ruby
|
27
|
+
thermo = Renstar::Thermostat.search.first
|
28
|
+
```
|
29
|
+
|
30
|
+
* Heat to 80 degrees:
|
31
|
+
```ruby
|
32
|
+
thermo.heat(80)
|
33
|
+
```
|
34
|
+
|
35
|
+
* Cool to 60 degrees:
|
36
|
+
```ruby
|
37
|
+
thermo.cool(60)
|
38
|
+
```
|
39
|
+
|
40
|
+
* Automatically keep the temp between 70 and 74 degrees:
|
41
|
+
```ruby
|
42
|
+
thermo.auto(70, 74)
|
43
|
+
```
|
44
|
+
|
45
|
+
* Turn off heeating and/or cooling
|
46
|
+
```ruby
|
47
|
+
thermo.off
|
48
|
+
```
|
49
|
+
|
50
|
+
* Control the fan:
|
51
|
+
```ruby
|
52
|
+
thermo.fan_on
|
53
|
+
|
54
|
+
thermo.fan_off
|
55
|
+
|
56
|
+
thermo.fan_toggle
|
57
|
+
```
|
58
|
+
|
59
|
+
* Control the schedule:
|
60
|
+
```ruby
|
61
|
+
thermo.schedule_on
|
62
|
+
|
63
|
+
thermo.scheduel_off
|
64
|
+
|
65
|
+
thermo.schedule_toggle
|
66
|
+
```
|
67
|
+
|
68
|
+
* Set Home/Away:
|
69
|
+
```ruby
|
70
|
+
thermo.home
|
71
|
+
|
72
|
+
thermo.away
|
73
|
+
```
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
## Development
|
78
|
+
|
79
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
80
|
+
|
81
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
82
|
+
|
83
|
+
## Contributing
|
84
|
+
|
85
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/renstar.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'renstar'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
{
|
2
|
+
"info": {
|
3
|
+
"name": {
|
4
|
+
"description": "The name of the thermostat",
|
5
|
+
"values": "raw"
|
6
|
+
},
|
7
|
+
"mode": {
|
8
|
+
"description": "Current thermostat mode",
|
9
|
+
"values": {
|
10
|
+
"0": "Off",
|
11
|
+
"1": "Heat",
|
12
|
+
"2": "Cool",
|
13
|
+
"3": "Auto"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"state": {
|
17
|
+
"description": "Current thermostat state",
|
18
|
+
"values": {
|
19
|
+
"0": "Idle",
|
20
|
+
"1": "Heating",
|
21
|
+
"2": "Cooling",
|
22
|
+
"3": "Lockout",
|
23
|
+
"4": "Error"
|
24
|
+
}
|
25
|
+
},
|
26
|
+
"fan": {
|
27
|
+
"description": "Current fan setting",
|
28
|
+
"values": {
|
29
|
+
"0": "Auto",
|
30
|
+
"1": "On"
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"fanstate": {
|
34
|
+
"description": "Current fan state",
|
35
|
+
"values": {
|
36
|
+
"0": "Off",
|
37
|
+
"1": "On"
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"tempunits": {
|
41
|
+
"description": "Current temperature units",
|
42
|
+
"values": {
|
43
|
+
"0": "Fahrenheit",
|
44
|
+
"1": "Celsius"
|
45
|
+
}
|
46
|
+
},
|
47
|
+
"schedule": {
|
48
|
+
"description": "Current schedule state",
|
49
|
+
"values": {
|
50
|
+
"0": "Disabled",
|
51
|
+
"1": "Enabled"
|
52
|
+
}
|
53
|
+
},
|
54
|
+
"schedulepart": {
|
55
|
+
"description": "Current schedule part",
|
56
|
+
"values": {
|
57
|
+
"0": "Occupied 1 or morning",
|
58
|
+
"1": "Occupied 2 or day",
|
59
|
+
"2": "Occupied 3 or eventing",
|
60
|
+
"3": "Unoccupied or night",
|
61
|
+
"255": "Inactive"
|
62
|
+
}
|
63
|
+
},
|
64
|
+
"away": {
|
65
|
+
"description": "Current away state",
|
66
|
+
"values": {
|
67
|
+
"0": "Home",
|
68
|
+
"1": "Away"
|
69
|
+
},
|
70
|
+
"requires": "residential"
|
71
|
+
},
|
72
|
+
"override": {
|
73
|
+
"description": "Current override state",
|
74
|
+
"values": {
|
75
|
+
"0": "Off",
|
76
|
+
"1": "On"
|
77
|
+
},
|
78
|
+
"requires": "commercial"
|
79
|
+
},
|
80
|
+
"overridetime": {
|
81
|
+
"description": "Time left in override",
|
82
|
+
"values": "raw",
|
83
|
+
"requires": "commercial"
|
84
|
+
},
|
85
|
+
"forceunocc": {
|
86
|
+
"description": "Current forceunocc state",
|
87
|
+
"values": {
|
88
|
+
"0": "Off",
|
89
|
+
"1": "On"
|
90
|
+
},
|
91
|
+
"requires": "commercial"
|
92
|
+
},
|
93
|
+
"spacetemp": {
|
94
|
+
"description": "Current space temperature",
|
95
|
+
"values": "raw"
|
96
|
+
},
|
97
|
+
"heattemp": {
|
98
|
+
"description": "Current heat to temperature",
|
99
|
+
"values": "raw"
|
100
|
+
},
|
101
|
+
"cooltemp": {
|
102
|
+
"description": "Current cool to temperature",
|
103
|
+
"values": "raw"
|
104
|
+
},
|
105
|
+
"cooltempmin": {
|
106
|
+
"description": "Minimum cool to temperature",
|
107
|
+
"values": "raw"
|
108
|
+
},
|
109
|
+
"cooltempmax": {
|
110
|
+
"description": "Maximum cool to temperature",
|
111
|
+
"values": "raw"
|
112
|
+
},
|
113
|
+
"heattempmin": {
|
114
|
+
"description": "Minimum heat to temperature",
|
115
|
+
"values": "raw"
|
116
|
+
},
|
117
|
+
"heattempmax": {
|
118
|
+
"description": "Maximum heat to temperature",
|
119
|
+
"values": "raw"
|
120
|
+
},
|
121
|
+
"setpointdelta": {
|
122
|
+
"description": "Minimum temperature difference \n of heat and cool temperatures",
|
123
|
+
"values": "raw"
|
124
|
+
},
|
125
|
+
"hum": {
|
126
|
+
"description": "Current humidity if available",
|
127
|
+
"values": "raw"
|
128
|
+
},
|
129
|
+
"availablemodes": {
|
130
|
+
"description": "Available thermostat modes",
|
131
|
+
"values": {
|
132
|
+
"0": "all modes",
|
133
|
+
"1": "heat/cool only",
|
134
|
+
"2": "heat only",
|
135
|
+
"3": "cool only"
|
136
|
+
}
|
137
|
+
}
|
138
|
+
},
|
139
|
+
"sensors": {
|
140
|
+
"name": {
|
141
|
+
"description": "Sensor name",
|
142
|
+
"values": "raw"
|
143
|
+
},
|
144
|
+
"temp": {
|
145
|
+
"description": "Sensor temperature",
|
146
|
+
"values": "raw"
|
147
|
+
},
|
148
|
+
"hum": {
|
149
|
+
"description": "Humidity sensor if available",
|
150
|
+
"values": "raw"
|
151
|
+
}
|
152
|
+
},
|
153
|
+
"runtimes": {
|
154
|
+
"ts": {
|
155
|
+
"description": "Timestamp",
|
156
|
+
"values": "epoch"
|
157
|
+
},
|
158
|
+
"heat1": {
|
159
|
+
"description": "Stage 1 Heat runtime in minutes",
|
160
|
+
"values": "raw"
|
161
|
+
},
|
162
|
+
"heat2": {
|
163
|
+
"description": "Stage 2 Heat runtime in minutes",
|
164
|
+
"values": "raw"
|
165
|
+
},
|
166
|
+
"cool1": {
|
167
|
+
"description": "Stage 1 Cool runtime in minutes",
|
168
|
+
"values": "raw"
|
169
|
+
},
|
170
|
+
"cool2": {
|
171
|
+
"description": "Stage 2 Cool runtime in minutes",
|
172
|
+
"values": "raw"
|
173
|
+
},
|
174
|
+
"aux1": {
|
175
|
+
"description": "Stage 1 Auxiliary runtime in minutes",
|
176
|
+
"values": "raw"
|
177
|
+
},
|
178
|
+
"aux2": {
|
179
|
+
"description": "Stage 2 Auxiliary runtime in minutes",
|
180
|
+
"values": "raw"
|
181
|
+
},
|
182
|
+
"fc": {
|
183
|
+
"description": "Free Cooling runtime in minutes",
|
184
|
+
"values": "raw"
|
185
|
+
},
|
186
|
+
"ov": {
|
187
|
+
"description": "Override runtime in minutes",
|
188
|
+
"values": "raw"
|
189
|
+
}
|
190
|
+
},
|
191
|
+
"alerts": {
|
192
|
+
"name": {
|
193
|
+
"description": "Alert name",
|
194
|
+
"values": "raw"
|
195
|
+
},
|
196
|
+
"active": {
|
197
|
+
"description": "If the alert is active",
|
198
|
+
"values": "raw"
|
199
|
+
}
|
200
|
+
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Renstar
|
4
|
+
module APIClient
|
5
|
+
# Base API Object class from which other objects inherit
|
6
|
+
class APIObject
|
7
|
+
def initialize(raw_hash)
|
8
|
+
@raw_hash = raw_hash
|
9
|
+
raw_hash.each do |key, value|
|
10
|
+
if key == 'ts'
|
11
|
+
instance_variable_set("@#{key}", Time.at(value))
|
12
|
+
else
|
13
|
+
instance_variable_set("@#{key}", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
define_singleton_method(key) do
|
17
|
+
return instance_variable_get("@#{key}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
@raw_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def human_readable
|
27
|
+
@raw_hash.map do |key, value|
|
28
|
+
description = APIClient.key_to_description('runtimes', key)
|
29
|
+
formatted_value = APIClient.value_to_formatted('runtimes', key, value)
|
30
|
+
format("%-35<description>s %<formatted_value>s\n",
|
31
|
+
{ description: description, formatted_value: formatted_value })
|
32
|
+
end.join
|
33
|
+
end
|
34
|
+
|
35
|
+
def pp
|
36
|
+
puts human_readable
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../api_object'
|
4
|
+
|
5
|
+
module Renstar
|
6
|
+
module APIClient
|
7
|
+
# An abstraction to the info hash that gets returned from the API
|
8
|
+
# It defines getters and instance variables for each key/value pair in the
|
9
|
+
# info response from the API for clean access.
|
10
|
+
#
|
11
|
+
class Info < APIObject
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../api_object'
|
4
|
+
|
5
|
+
module Renstar
|
6
|
+
module APIClient
|
7
|
+
# Represents a day of "runtime"
|
8
|
+
# Breaks down how much time the system spent in various states
|
9
|
+
# like heating or cooling.
|
10
|
+
class Runtime < APIObject
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../api_client'
|
4
|
+
module Renstar
|
5
|
+
module APIClient
|
6
|
+
# Interface to the "Control" portion of the Venstar API
|
7
|
+
# This can be used to send a hash of raw options to the API
|
8
|
+
# bypassing the convenience methods built into `Thermostat`
|
9
|
+
#
|
10
|
+
module Control
|
11
|
+
def control(options = {})
|
12
|
+
post('control', options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../api_client'
|
4
|
+
require_relative 'api_objects/info'
|
5
|
+
require_relative 'api_objects/sensor'
|
6
|
+
require_relative 'api_objects/runtime'
|
7
|
+
require_relative 'api_objects/alert'
|
8
|
+
module Renstar
|
9
|
+
module APIClient
|
10
|
+
# Interface to the "Query" portion of the API
|
11
|
+
# This can get general info, settings, runtime data, and alerts
|
12
|
+
module Query
|
13
|
+
def info
|
14
|
+
Info.new(get('query/info'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def sensors
|
18
|
+
get('query/sensors')['sensors'].map do |sensor|
|
19
|
+
Sensor.new(sensor)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def runtimes
|
24
|
+
get('query/runtimes')['runtimes'].map do |runtime|
|
25
|
+
Runtime.new(runtime)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def alerts
|
30
|
+
get('query/alerts')['alerts'].map do |alert|
|
31
|
+
Alert.new(alert)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../api_client'
|
4
|
+
module Renstar
|
5
|
+
module APIClient
|
6
|
+
# Interface to the "Settings" portion of the API
|
7
|
+
# This allows you to set any settings like Home/Away, or enabling the
|
8
|
+
# schedule
|
9
|
+
#
|
10
|
+
module Settings
|
11
|
+
def settings(options = {})
|
12
|
+
post('settings', options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
require_relative 'api_client/query'
|
7
|
+
require_relative 'api_client/control'
|
8
|
+
require_relative 'api_client/settings'
|
9
|
+
|
10
|
+
require_relative 'api_client/api_object'
|
11
|
+
|
12
|
+
module Renstar
|
13
|
+
# The actual client that handles getting, posting, and parsing API responses
|
14
|
+
#
|
15
|
+
module APIClient
|
16
|
+
def get(endpoint)
|
17
|
+
uri = URI(location + endpoint)
|
18
|
+
response = Net::HTTP.get(uri)
|
19
|
+
JSON.parse(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
def post(endpoint, options = {})
|
23
|
+
uri = URI(location + endpoint)
|
24
|
+
response = Net::HTTP.post_form(uri, options)
|
25
|
+
JSON.parse(response.body)
|
26
|
+
end
|
27
|
+
|
28
|
+
include Query
|
29
|
+
include Control
|
30
|
+
include Settings
|
31
|
+
|
32
|
+
@api_ref = JSON.parse(File.read(File.join(__dir__, './api_client/api.json')))
|
33
|
+
|
34
|
+
def self.key_to_description(type, key)
|
35
|
+
@api_ref.dig(type, key, 'description') || key
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.value_to_formatted(type, key, value)
|
39
|
+
case @api_ref.dig(type, key, 'values')
|
40
|
+
when 'raw'
|
41
|
+
value
|
42
|
+
when 'epoch'
|
43
|
+
Time.at(value)
|
44
|
+
else
|
45
|
+
@api_ref.dig(type, key, 'values', value.to_s) || value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ssdp'
|
4
|
+
require_relative 'api_client'
|
5
|
+
|
6
|
+
module Renstar
|
7
|
+
# Thermostat object
|
8
|
+
# Contains convenience methods along the lines of what is provided in the
|
9
|
+
# mobile app, website, or control panel, e.g. Heat, Cool, Auto, Fan, Schedule
|
10
|
+
# Home/Away, and Off
|
11
|
+
#
|
12
|
+
class Thermostat
|
13
|
+
SERVICE = 'venstar:thermostat:ecp'
|
14
|
+
DEFAULT_TIMEOUT = 5
|
15
|
+
|
16
|
+
attr_reader :location, :usn, :cached_info
|
17
|
+
|
18
|
+
include APIClient
|
19
|
+
|
20
|
+
def initialize(location, usn)
|
21
|
+
@location = location
|
22
|
+
@usn = usn
|
23
|
+
@cache_timestamp = Time.now
|
24
|
+
@cached_info = info
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.search(timeout = DEFAULT_TIMEOUT)
|
28
|
+
ssdp = SSDP::Consumer.new
|
29
|
+
thermos = ssdp.search(service: SERVICE, timeout: timeout)
|
30
|
+
thermos.map do |thermo|
|
31
|
+
location = thermo[:params]['Location']
|
32
|
+
usn = thermo[:params]['USN']
|
33
|
+
Renstar::Thermostat.new(location, usn)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def update
|
38
|
+
@cache_timestamp = Time.now
|
39
|
+
@cached_info = info
|
40
|
+
end
|
41
|
+
|
42
|
+
def off
|
43
|
+
response = control("mode": 0, "cooltemp": @cached_info.cooltemp, "heattemp": @cached_info.heattemp)
|
44
|
+
update
|
45
|
+
response
|
46
|
+
end
|
47
|
+
|
48
|
+
def heat(heattemp = nil)
|
49
|
+
update
|
50
|
+
if heattemp
|
51
|
+
cooltemp = heattemp + 1.0
|
52
|
+
else
|
53
|
+
cooltemp = @cached_info.cooltemp
|
54
|
+
heattemp = @cached_info.heattemp
|
55
|
+
end
|
56
|
+
response = control("mode": 1, "cooltemp": cooltemp, "heattemp": heattemp)
|
57
|
+
update
|
58
|
+
response
|
59
|
+
end
|
60
|
+
|
61
|
+
def cool(cooltemp = nil)
|
62
|
+
update
|
63
|
+
if cooltemp
|
64
|
+
heattemp = cooltemp - 1.0
|
65
|
+
# heattemp = cooltemp - @cached_info.setpointdelta
|
66
|
+
else
|
67
|
+
cooltemp = @cached_info.cooltemp
|
68
|
+
heattemp = @cached_info.heattemp
|
69
|
+
end
|
70
|
+
response = control("mode": 2, "cooltemp": cooltemp, "heattemp": heattemp)
|
71
|
+
update
|
72
|
+
response
|
73
|
+
end
|
74
|
+
|
75
|
+
def auto(heattemp = nil, cooltemp = nil)
|
76
|
+
# we want to make sure we have the latest values
|
77
|
+
# so we'll update then set the defaults
|
78
|
+
update
|
79
|
+
heattemp ||= @cached_info.heattemp
|
80
|
+
cooltemp ||= @cached_info.cooltemp
|
81
|
+
response = control("mode": 3, "cooltemp": cooltemp, "heattemp": heattemp)
|
82
|
+
update
|
83
|
+
response
|
84
|
+
end
|
85
|
+
|
86
|
+
def fan_off
|
87
|
+
response = control("fan": 0)
|
88
|
+
update
|
89
|
+
response
|
90
|
+
end
|
91
|
+
|
92
|
+
def fan_on
|
93
|
+
response = control("fan": 1)
|
94
|
+
update
|
95
|
+
response
|
96
|
+
end
|
97
|
+
|
98
|
+
def fan_toggle
|
99
|
+
if @cached_info.fan == 1
|
100
|
+
fan_off
|
101
|
+
else
|
102
|
+
fan_on
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def schedule_off
|
107
|
+
response = settings("schedule": 0)
|
108
|
+
update
|
109
|
+
response
|
110
|
+
end
|
111
|
+
|
112
|
+
def schedule_on
|
113
|
+
response = settings("schedule": 1)
|
114
|
+
update
|
115
|
+
response
|
116
|
+
end
|
117
|
+
|
118
|
+
def schedule_toggle
|
119
|
+
if @cached_info.schedule == 1
|
120
|
+
schedule_off
|
121
|
+
else
|
122
|
+
schedule_on
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def home
|
127
|
+
response = settings("away": 0)
|
128
|
+
update
|
129
|
+
response
|
130
|
+
end
|
131
|
+
|
132
|
+
def away
|
133
|
+
response = settings("away": 1)
|
134
|
+
update
|
135
|
+
response
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/renstar.rb
ADDED
data/renstar.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/renstar/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'renstar'
|
7
|
+
spec.version = Renstar::VERSION
|
8
|
+
spec.authors = ['Michael Rodrigues']
|
9
|
+
spec.email = ['mikebrodrigues@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'Control Venstar thermostats.'
|
12
|
+
spec.description = 'Control Venstar thermostats with Ruby via their local API.'
|
13
|
+
spec.homepage = 'https://github.com/mikerodrigues/renstar'
|
14
|
+
spec.required_ruby_version = '>= 3.0.0'
|
15
|
+
|
16
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/mikerodrigues/renstar'
|
20
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = 'exe'
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ['lib']
|
30
|
+
|
31
|
+
spec.add_runtime_dependency 'json'
|
32
|
+
spec.add_runtime_dependency 'ssdp'
|
33
|
+
|
34
|
+
# Uncomment to register a new dependency of your gem
|
35
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
36
|
+
|
37
|
+
# For more information and examples about making a new gem, checkout our
|
38
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: renstar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Rodrigues
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ssdp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Control Venstar thermostats with Ruby via their local API.
|
42
|
+
email:
|
43
|
+
- mikebrodrigues@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- Gemfile.lock
|
51
|
+
- LICENSE
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- bin/console
|
55
|
+
- bin/setup
|
56
|
+
- lib/renstar.rb
|
57
|
+
- lib/renstar/api_client.rb
|
58
|
+
- lib/renstar/api_client/api.json
|
59
|
+
- lib/renstar/api_client/api_object.rb
|
60
|
+
- lib/renstar/api_client/api_objects/alert.rb
|
61
|
+
- lib/renstar/api_client/api_objects/info.rb
|
62
|
+
- lib/renstar/api_client/api_objects/runtime.rb
|
63
|
+
- lib/renstar/api_client/api_objects/sensor.rb
|
64
|
+
- lib/renstar/api_client/control.rb
|
65
|
+
- lib/renstar/api_client/query.rb
|
66
|
+
- lib/renstar/api_client/settings.rb
|
67
|
+
- lib/renstar/thermostat.rb
|
68
|
+
- lib/renstar/version.rb
|
69
|
+
- renstar.gemspec
|
70
|
+
homepage: https://github.com/mikerodrigues/renstar
|
71
|
+
licenses: []
|
72
|
+
metadata:
|
73
|
+
allowed_push_host: https://rubygems.org
|
74
|
+
homepage_uri: https://github.com/mikerodrigues/renstar
|
75
|
+
source_code_uri: https://github.com/mikerodrigues/renstar
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 3.0.0
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubygems_version: 3.2.22
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Control Venstar thermostats.
|
95
|
+
test_files: []
|