liftmaster_myq 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ sandbox.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in liftmaster_myq.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 David Pfeffer
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ # LiftmasterMyq
2
+
3
+ Ruby gem to control a Chaimberlain Liftmaster MyQ system.
4
+ Partial documentation of the API is available at http://docs.unofficialliftmastermyq.apiary.io/
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'liftmaster_myq'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install liftmaster_myq-X.X.X.gem (Note: X.X.X should be changed to the current version number)
19
+
20
+ ## Usage
21
+
22
+ To create the gem:
23
+
24
+ $ gem build /path/to/liftmaster_myq/liftmaster_myq.gemspec
25
+
26
+ To instantiate the system:
27
+
28
+ $ require 'liftmaster_myq'
29
+ $ system = LiftmasterMyq::System.new('your_username','your_password')
30
+
31
+ To see your device list in all it's ruby glory:
32
+
33
+ $ system.gateways
34
+ $ system.garage_doors
35
+ $ system.garage_doors.count
36
+
37
+ Have fun with:
38
+
39
+ $ system.garage_doors[0].open
40
+ $ system.garage_doors[0].close
41
+ $ system.garage_doors[0].status
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,65 @@
1
+ FORMAT: 1A
2
+ HOST: http://myqexternal.myqdevice.com
3
+
4
+ # Chamberlain Liftmaster MyQ API
5
+ This is unofficial (and partial) documentation of the Chamberlain/Liftmaster MyQ API used by the iOS and Android apps. It features functionality to monitor and control the garage door system remotely. A ruby gem implementation of this API is available at http://github.com/pfeffed/liftmaster_myq.
6
+
7
+ ## Constant Values
8
+ This API has some static values:
9
+
10
+ Application Id = "Vj8pQggXLhLy0WHahglCD4N1nAkkXQtGYpq2HrHD7H1nvmbT55KqtN6RSF4ILB%2fi"
11
+
12
+ Culture = 'en' (Note: other regions may be supported as well)
13
+
14
+ ## Login [/Membership/ValidateUserWithCulture?appId={appId}&securityToken=null&username={username}&password={password}&culture={culture}]
15
+ ### Send login request [GET]
16
+ You should only need to store the securityToken in the response for subsequent requests. Also, I have noticed that sometimes the call to login returns a token that does not work. From time to time, I have found that retrying the login call once or twice gets one that works.
17
+ + Parameters
18
+ + appId (required, string) ... This appears to be a constant string value associated with the mobile app.
19
+ + username (required, string) ... The account's email address in url encoded format (i.e. someone@test.com -> someone%40test.com).
20
+ + password (required, string) ... The account password in url encoded format.
21
+ + culture (required, string) ... This appears to be the country code. I have only tried it with 'en'.
22
+
23
+ + Response 200 (application/json)
24
+
25
+ {"UserId":987654,"SecurityToken":"YOUR_TOKEN_HERE","ReturnCode":"0","ErrorMessage":"","ExecutionTimes":"15.6;46.8;78;62.4","BrandId":2,"BrandName":"Chamberlain"}
26
+
27
+ ## System Detail [/api/UserDeviceDetails?appId={appId}&securityToken={securityToken}]
28
+ ### Get devices and information about the MyQ system [GET]
29
+ The security token is the one received from the login request. If the system comes back without any MyQ units, it may be a sign your login token needs to be refreshed.
30
+ + Parameters
31
+ + appId (required, string) ... This appears to be a static string associated with the mobile app.
32
+ + securityToken (required, string) ... This appears to be a static string associated with the mobile app.
33
+
34
+ + Response 200 (application/json)
35
+
36
+ {"Devices":[{"MyQDeviceId":987654321098,"MyQDeviceTypeId":1,"MyQDeviceTypeName":"Gateway","DeviceId":"876543","DeviceName":"GW000000XXXX","TypeId":49,"TypeName":"Gateway","RegistrationDateTime":"2013-10-12T13:26:38.48","SerialNumber":"GW000000XXXX","UserName":"YOUR-USERNAME","UserConnectServerId":0,"UserCountryId":0,"Attributes":[{"Name":"deviceRecord.response","Value":"{\"id\":987654321,\"deviceCode\":{\"login\":\"XXXXXXXXXXX\",\"password\":\"XX\"},\"type\":{\"id\":47,\"nativeID\":131},\"version\":{\"major\":1,\"minor\":80,\"revision\":1024}}","UpdatedTime":"1382133086081","MyQDeviceTypeAttributeId":0,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"learnmodestate","Value":"0","UpdatedTime":"1384058789400","MyQDeviceTypeAttributeId":3,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"hwver","Value":"1.0","UpdatedTime":"1384990618614","MyQDeviceTypeAttributeId":34,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"desc","Value":"YOUR-GATEWAY-NAME","UpdatedTime":"1382133367601","MyQDeviceTypeAttributeId":28,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"enumeraterequired","Value":"0","UpdatedTime":"1384925170098","MyQDeviceTypeAttributeId":1,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"devtype","Value":"6","UpdatedTime":"1384058783970","MyQDeviceTypeAttributeId":31,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"fwver","Value":"3.0","UpdatedTime":"1384990618527","MyQDeviceTypeAttributeId":33,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"devicetablechecksum","Value":"0","UpdatedTime":"1382133351232","MyQDeviceTypeAttributeId":5,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"enumeratetimestamp","Value":"10/18/2013 4:51:24 PM","UpdatedTime":"1382133085152","MyQDeviceTypeAttributeId":7,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"removeAllDevices.response","Value":"1","UpdatedTime":"1382133084644","MyQDeviceTypeAttributeId":0,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"blver","Value":"1.0","UpdatedTime":"1384990618699","MyQDeviceTypeAttributeId":35,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"devices","Value":"XXXXXXXXX","UpdatedTime":"1382133351238","MyQDeviceTypeAttributeId":25,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"deviceCount.response","Value":"{\"checkSum\":381,\"deviceCount\":1}","UpdatedTime":"1382133085519","MyQDeviceTypeAttributeId":0,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"desiredlearnmode","Value":"0","UpdatedTime":"1384058789403","MyQDeviceTypeAttributeId":2,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"deviceName","Value":"987654321098","UpdatedTime":"","MyQDeviceTypeAttributeId":104,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"customerName","Value":"987654321098","UpdatedTime":"","MyQDeviceTypeAttributeId":4,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"}],"UpdatedBy":"EXT_API","UpdatedDate":"2013-10-18T21:51:24.68"},{"MyQDeviceId":987654,"ParentMyQDeviceId":87654,"MyQDeviceTypeId":2,"MyQDeviceTypeName":"GarageDoorOpener","DeviceId":"XXXXXXXXX","DeviceName":"987654321098","TypeId":47,"TypeName":"Garage Door Opener","UserName":"YOUR-USERNAME","UserConnectServerId":0,"UserCountryId":0,"Attributes":[{"Name":"learnmode","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":55,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"aclossdetect","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":57,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"flasherconnect","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":58,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"worklightstate","Value":"1","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":51,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"gatewayID","Value":"XXXXXX","UpdatedTime":"1382133351237","MyQDeviceTypeAttributeId":49,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"online","Value":"","UpdatedTime":"1384990647995","MyQDeviceTypeAttributeId":0,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"desireddoorstate","Value":"","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":41,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"desc","Value":"Garage Door Opener","UpdatedTime":"1382133355790","MyQDeviceTypeAttributeId":50,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"doorstate","Value":"2","UpdatedTime":"1385067858624","MyQDeviceTypeAttributeId":56,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"controlledlightfeature","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":43,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"diagnosticerrorstate","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":54,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"addedtime","Value":"2013-10-18 21:55:51","UpdatedTime":"1382133351237","MyQDeviceTypeAttributeId":61,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"vacationmode","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":52,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"radiolearnmode","Value":"0","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":53,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"isunattendedopenallowed","Value":"1","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":77,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"isunattendedcloseallowed","Value":"1","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":78,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"requestdevicestatus","Value":"","UpdatedTime":"1385071490018","MyQDeviceTypeAttributeId":59,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"deviceName","Value":"987654321098","UpdatedTime":"","MyQDeviceTypeAttributeId":103,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"},{"Name":"customerName","Value":"987654321098","UpdatedTime":"","MyQDeviceTypeAttributeId":75,"IsDeviceProperty":false,"IsPersistent":false,"IsTimeSeries":false,"IsGlobal":false,"UpdatedDate":"0001-01-01T00:00:00"}],"UpdatedBy":"EXT_API","UpdatedDate":"2013-10-18T21:55:52.167"}],"ReturnCode":"0","ErrorMessage":""}
37
+
38
+ ## Toggle Device State [/Device/setDeviceAttribute]
39
+ ### Open or close the door (and turn lights on/off?) [PUT]
40
+
41
+ {
42
+ "AttributeName":"requestdevicestatus",
43
+ "DeviceId":"987654321098",
44
+ "ApplicationId":"APPID-FROM-CONSTANTS",
45
+ "AttributeValue":"1",
46
+ "SecurityToken":"YOUR-TOKEN"
47
+ }
48
+
49
+ + Response 200 (application/json)
50
+
51
+ {"UpdatedTime":"1385071721231","ReturnCode":"0"}
52
+
53
+ ## Check Device State [/Device/getDeviceAttribute?appId={appId}&securityToken={securityToken}&devId={deviceId}&name={command}]
54
+ ### Get the status of a particular device attribute [GET]
55
+ This can be used to check to see if a garage door is open, closed, opening, or closing. There are probably more uses that I have not yet needed.
56
+ + Parameters
57
+ + appId (required, string) ... This appears to be a static string associated with the mobile app.
58
+ + securityToken (required, string) ... This appears to be a static string associated with the mobile app.
59
+ + deviceId (required, string) ... This is the id or deviceId returned in the System Detail call to endpoint /api/UserDeviceDetails referenced above.
60
+ + command (required, string) ... I have only tried using 'doorstate'
61
+
62
+ + Response 200 (application/json)
63
+
64
+ {"AttributeValue":"2","UpdatedTime":"1385067858624","ReturnCode":"0","ErrorMessage":""}
65
+
@@ -0,0 +1,14 @@
1
+ require "liftmaster_myq/version"
2
+ require "liftmaster_myq/system"
3
+ require "liftmaster_myq/device"
4
+
5
+ module LiftmasterMyq
6
+ APP_ID = "Vj8pQggXLhLy0WHahglCD4N1nAkkXQtGYpq2HrHD7H1nvmbT55KqtN6RSF4ILB%2Fi"
7
+ LOCALE = "en"
8
+
9
+ HOST_URI = "myqexternal.myqdevice.com"
10
+ LOGIN_ENDPOINT = "Membership/ValidateUserWithCulture"
11
+ DEVICE_LIST_ENDPOINT = "api/UserDeviceDetails"
12
+ DEVICE_SET_ENDPOINT = "Device/setDeviceAttribute"
13
+ DEVICE_STATUS_ENDPOINT = "/Device/getDeviceAttribute"
14
+ end
@@ -0,0 +1,9 @@
1
+ module LiftmasterMyq
2
+ module Device
3
+ end
4
+ end
5
+
6
+ require 'liftmaster_myq/device/base'
7
+ require 'liftmaster_myq/device/garage_door'
8
+ require 'liftmaster_myq/device/gateway'
9
+ require 'liftmaster_myq/device/light_switch'
@@ -0,0 +1,19 @@
1
+ module LiftmasterMyq::Device
2
+ class Base
3
+
4
+ attr_reader :id, :name, :myq_id, :myq_name, :parent_system, :cached_hash
5
+
6
+ def initialize(device_hash, parent_system)
7
+ @cached_hash = device_hash
8
+ @parent_system = parent_system
9
+ @id = device_hash["DeviceId"]
10
+ device_hash["Attributes"].each do |elem|
11
+ @name = elem["Value"] if elem["Name"] == "desc"
12
+ end
13
+ @myq_id = device_hash["MyQDeviceId"]
14
+ @myq_name = device_hash["DeviceName"]
15
+ @device_type = device_hash["MyQDeviceTypeName"]
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,72 @@
1
+ require 'liftmaster_myq/device'
2
+
3
+ module LiftmasterMyq::Device
4
+ class GarageDoor < Base
5
+
6
+ attr_accessor :gateway
7
+
8
+ def initialize(device_hash, parent_system)
9
+ super
10
+ @gateway = device_hash["ParentMyQDeviceId"]
11
+ end
12
+
13
+ def open
14
+ change_door_state("open")
15
+ end
16
+
17
+ def close
18
+ change_door_state("close")
19
+ end
20
+
21
+ def status
22
+ response = check_door_state("doorstate").parsed_response
23
+ state = response["AttributeValue"]
24
+ if state == "1"
25
+ return "open"
26
+ elsif state == "2"
27
+ return "closed"
28
+ elsif state == "4"
29
+ return "opening"
30
+ elsif state == "5"
31
+ return "closing"
32
+ else
33
+ return "#{state} is an unknown state for the door."
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def change_door_state_uri
40
+ uri = "https://#{LiftmasterMyq::HOST_URI}/"
41
+ uri << "#{LiftmasterMyq::DEVICE_SET_ENDPOINT}"
42
+ end
43
+
44
+ def check_door_state_uri(command)
45
+ uri = "https://#{LiftmasterMyq::HOST_URI}/"
46
+ uri << "#{LiftmasterMyq::DEVICE_STATUS_ENDPOINT}"
47
+ uri << "?appId=#{LiftmasterMyq::APP_ID}"
48
+ uri << "&securityToken=#{self.parent_system.security_token}"
49
+ uri << "&devId=#{self.id}"
50
+ uri << "&name=#{command}"
51
+ end
52
+
53
+ def change_door_state(command)
54
+ open_close_state = command.to_s.downcase == "open" ? 1 : 0
55
+ HTTParty.put(change_door_state_uri,
56
+ :body => {
57
+ :AttributeName => "desireddoorstate",
58
+ :DeviceId => self.id,
59
+ :ApplicationId => LiftmasterMyq::APP_ID,
60
+ :AttributeValue => open_close_state,
61
+ :SecurityToken => self.parent_system.security_token
62
+ }
63
+ )
64
+ end
65
+
66
+ def check_door_state(command)
67
+ uri = check_door_state_uri(command)
68
+ HTTParty.get(uri)
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,10 @@
1
+ require 'liftmaster_myq/device'
2
+
3
+ module LiftmasterMyq::Device
4
+ class Gateway < Base
5
+
6
+ def status
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ require 'liftmaster_myq/device'
2
+
3
+ module LiftmasterMyq::Device
4
+ class LightSwitch < Base
5
+
6
+ def on
7
+ end
8
+
9
+ def off
10
+ end
11
+
12
+ def status
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,105 @@
1
+ require 'uri'
2
+ require 'httparty'
3
+
4
+ module LiftmasterMyq
5
+ class System
6
+
7
+ attr_reader :username, :password, :garage_doors, :gateways,
8
+ :lights, :security_token, :userId, :cached_login_response
9
+
10
+ @@failed_endpoint_discovery_count = 0
11
+
12
+ def initialize(user, pass)
13
+ @username = URI.encode(user)
14
+ @password = URI.encode(pass)
15
+ login
16
+ discover_endpoints
17
+ end
18
+
19
+ def discover_endpoints
20
+ empty_device_arrays
21
+ response = request_device_list
22
+ devices = response["Devices"]
23
+ devices.each do |device|
24
+ instantiate_device(device)
25
+ end
26
+ if @gateways.size > 0
27
+ @@failed_endpoint_discovery_count = 0
28
+ return "endpoint discovery complete"
29
+ elsif @@failed_endpoint_discovery_count < 3
30
+ @@failed_endpoint_discovery_count += 1
31
+ sleep 15
32
+ login
33
+ discover_endpoints
34
+ else
35
+ raise RuntimeError, "The Liftmaster MyQ API failed to return any devices under your account"
36
+ end
37
+ end
38
+
39
+ def find_door_by_id(id)
40
+ id = id.to_s
41
+ @garage_doors.each do |door|
42
+ return door if door.id == id
43
+ end
44
+ nil
45
+ end
46
+
47
+ def find_door_by_name(name)
48
+ @garage_doors.each do |door|
49
+ return door if door.name == name
50
+ end
51
+ nil
52
+ end
53
+
54
+ # private
55
+
56
+ def login_uri
57
+ uri = "https://#{LiftmasterMyq::HOST_URI}/"
58
+ uri << "#{LiftmasterMyq::LOGIN_ENDPOINT}"
59
+ uri << "?appId=#{LiftmasterMyq::APP_ID}"
60
+ uri << "&securityToken=null"
61
+ uri << "&username=#{@username}"
62
+ uri << "&password=#{@password}"
63
+ uri << "&culture=#{LiftmasterMyq::LOCALE}"
64
+ end
65
+
66
+ def device_list_uri
67
+ uri = "https://#{LiftmasterMyq::HOST_URI}/"
68
+ uri << "#{LiftmasterMyq::DEVICE_LIST_ENDPOINT}"
69
+ uri << "?appId=#{LiftmasterMyq::APP_ID}"
70
+ uri << "&securityToken=#{@security_token}"
71
+ end
72
+
73
+ def login
74
+ response = HTTParty.get(login_uri)
75
+ puts response
76
+ response = response.parsed_response
77
+ @userId = response["UserId"]
78
+ @security_token = response["SecurityToken"]
79
+ @cached_login_response = response
80
+ "logged in successfully"
81
+ end
82
+
83
+ def request_device_list
84
+ HTTParty.get(device_list_uri).parsed_response
85
+ end
86
+
87
+ def empty_device_arrays
88
+ @gateways = []
89
+ @garage_doors = []
90
+ @lights = []
91
+ end
92
+
93
+ def instantiate_device(device)
94
+ if device["MyQDeviceTypeName"] == "GarageDoorOpener"
95
+ @garage_doors << LiftmasterMyq::Device::GarageDoor.new(device, self)
96
+ elsif device["MyQDeviceTypeName"] == "Gateway"
97
+ @gateways << LiftmasterMyq::Device::Gateway.new(device, self)
98
+ #elsif device["MyQDeviceTypeName"]=="???"
99
+ # I need a MyQ light switch to implement this feature
100
+ #@lights << LiftmasterMyq::Device::LightSwitch.new(device)
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,3 @@
1
+ module LiftmasterMyq
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'liftmaster_myq/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "liftmaster_myq"
8
+ spec.version = LiftmasterMyq::VERSION
9
+ spec.authors = ["David Pfeffer"]
10
+ spec.email = ["david@pfeffer.org"]
11
+ spec.description = %q{Unofficial Liftmaster MyQ Controller}
12
+ spec.summary = %q{Gem to access and control the Liftmaster MyQ garage door system.}
13
+ spec.homepage = "http://github.com/pfeffed/liftmaster_myq"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "httparty", "~> 0.12.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liftmaster_myq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Pfeffer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.12.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Unofficial Liftmaster MyQ Controller
63
+ email:
64
+ - david@pfeffer.org
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - apiary.apib
75
+ - lib/liftmaster_myq.rb
76
+ - lib/liftmaster_myq/device.rb
77
+ - lib/liftmaster_myq/device/base.rb
78
+ - lib/liftmaster_myq/device/garage_door.rb
79
+ - lib/liftmaster_myq/device/gateway.rb
80
+ - lib/liftmaster_myq/device/light_switch.rb
81
+ - lib/liftmaster_myq/system.rb
82
+ - lib/liftmaster_myq/version.rb
83
+ - liftmaster_myq.gemspec
84
+ homepage: http://github.com/pfeffed/liftmaster_myq
85
+ licenses:
86
+ - MIT
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.25
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Gem to access and control the Liftmaster MyQ garage door system.
109
+ test_files: []
110
+ has_rdoc: