New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Liftmaster URI error #136

Closed
shawc opened this Issue Sep 2, 2015 · 15 comments

Comments

Projects
None yet
6 participants
@shawc

shawc commented Sep 2, 2015

I have the wink platform working with several lights so i can say "Hey Siri, turn off front door light" and it works - which is amazing! I added a garage door opener this weekend and i am able to get the wink app to open/close the garage door when i press the button. However, when i say "Hey Sire, open the garage door" i get the following error:

Error 'null' logging in: {"Message":"No HTTP resource was found that matches the request URI 'http://myqexternal.myqdevice.com/api/user/validatewithculture?appId=JVM%2FG9Nwih5BwKgNCjLxiFUQxQijAebyyg8QUHr7JOrP%2BtuPb8iHfRHKwTmDzHOu&culture=en'."}

Also, I only have one garage door.

Config.json
{
"bridge": {
"name": "Homebridge",
"username": "CC:22:3D:E3:CE:30",
"port": 51826,
"pin": "031-45-154"
},

"platforms": [
{
"platform": "Wink",
"name": "Wink",
"client_id": "i deleted this for the post",
"client_secret": "i deleted this for the post",
"username": "i deleted this for the post",
"password": "i deleted this for the post"
}
],

"accessories": [
{
"accessory": "LiftMaster",
"name": "Garage Door",
"description": "MyQ service.",
"username": "I deleted this for the post",
"password" : "I deleted this for the post"
}
]
}

Liftmaster.js
var types = require("HAP-NodeJS/accessories/types.js");
var request = require("request");

// This seems to be the "id" of the official LiftMaster iOS app
var APP_ID = "JVM/G9Nwih5BwKgNCjLxiFUQxQijAebyyg8QUHr7JOrP+tuPb8iHfRHKwTmDzHOu"
//var APP_ID = "Vj8pQggXLhLy0WHahglCD4N1nAkkXQtGYpq2HrHD7H1nvmbT55KqtN6RSF4ILB"

function LiftMasterAccessory(log, config) {
this.log = log;
this.name = config["Garage Door"];
this.username = config["i deleted this for the post"];
this.password = config["i deleted this for the post"];
this.requiredDeviceId = config["i deleted this for the post"];
}

LiftMasterAccessory.prototype = {

setState: function(state) {
this.targetState = state;
this.login();
},

login: function() {
var that = this;

// reset our logged-in state hint until we're logged in
this.deviceId = null;

// querystring params
var query = {
appId: APP_ID,
username: this.username,
password: this.password,
culture: "en"
};

// login to liftmaster
request.get({
url: "https://myqexternal.myqdevice.com/api/user/validatewithculture",
qs: query
}, function(err, response, body) {

if (!err && response.statusCode == 200) {

// parse and interpret the response
var json = JSON.parse(body);
that.userId = json["UserId"];
that.securityToken = json["SecurityToken"];
that.log("Logged in with user ID " + that.userId);
that.getDevice();

}
else {
that.log("Error '"+err+"' logging in: " + body);
}
});
},

// find your garage door ID
getDevice: function() {
var that = this;

// querystring params
var query = {
appId: APP_ID,
SecurityToken: this.securityToken,
filterOn: "true"
};

// some necessary duplicated info in the headers
var headers = {
MyQApplicationId: APP_ID,
SecurityToken: this.securityToken
};

// request details of all your devices
request.get({
url: "https://myqexternal.myqdevice.com/api/v4/userdevicedetails/get",
qs: query,
headers: headers
}, function(err, response, body) {

if (!err && response.statusCode == 200) {

// parse and interpret the response
var json = JSON.parse(body);
var devices = json["Devices"];
var foundDoors = [];

// look through the array of devices for an opener
for (var i=0; i<devices.length; i++) {
  var device = devices[i];

  if (device["MyQDeviceTypeName"] == "GarageDoorOpener") {

    // If we haven't explicity specified a door ID, we'll loop to make sure we don't have multiple openers, which is confusing
    if (!that.requiredDeviceId) {
      var thisDeviceId = device.MyQDeviceId;
      var thisDoorName = "Unknown";
      for (var j = 0; j < device.Attributes.length; j ++) {
        var thisAttributeSet = device.Attributes[j];
        if (thisAttributeSet.AttributeDisplayName == "desc") {
          thisDoorName = thisAttributeSet.Value;
          break;
        }
      }
      foundDoors.push(thisDeviceId + " - " + thisDoorName);
      that.deviceId = thisDeviceId;
    }

    // We specified a door ID, sanity check to make sure it's the one we expected
    else if (that.requiredDeviceId == device.MyQDeviceId) {
      that.deviceId = device.MyQDeviceId;
      break;
    }

  }

}

// If we have multiple found doors, refuse to proceed
if (foundDoors.length > 1) {
  that.log("WARNING: You have multiple doors on your MyQ account.");
  that.log("WARNING: Specify the ID of the door you want to control using the 'requiredDeviceId' property in your config.json file.");
  that.log("WARNING: You can have multiple liftmaster accessories to cover your multiple doors");

  for (var j = 0; j < foundDoors.length; j++) {
    that.log("Found Door: " + foundDoors[j]);
  }

  throw "FATAL: Please specify which specific door this Liftmaster accessory should control - you have multiples on your account";

}

// Did we get a device ID?
if (that.deviceId) {
  that.log("Found an opener with ID " + that.deviceId +". Ready to send command...");
  that.setTargetState();
}
else
{
  that.log("Error: Couldn't find a door device, or the ID you specified isn't associated with your account");
}

}
else {
that.log("Error '"+err+"' getting devices: " + body);
}
});
},

setTargetState: function() {

var that = this;
var liftmasterState = (this.targetState + "") == "1" ? "0" : "1";

// querystring params
var query = {
appId: APP_ID,
SecurityToken: this.securityToken,
filterOn: "true"
};

// some necessary duplicated info in the headers
var headers = {
MyQApplicationId: APP_ID,
SecurityToken: this.securityToken
};

// PUT request body
var body = {
AttributeName: "desireddoorstate",
AttributeValue: liftmasterState,
ApplicationId: APP_ID,
SecurityToken: this.securityToken,
MyQDeviceId: this.deviceId
};

// send the state request to liftmaster
request.put({
url: "https://myqexternal.myqdevice.com/api/v4/DeviceAttribute/PutDeviceAttribute",
qs: query,
headers: headers,
body: body,
json: true
}, function(err, response, json) {

if (!err && response.statusCode == 200) {

if (json["ReturnCode"] == "0")
  that.log("State was successfully set.");
else
  that.log("Bad return code: " + json["ReturnCode"]);
  that.log("Raw response " + JSON.stringify(json));

}
else {
that.log("Error '"+err+"' setting door state: " + JSON.stringify(json));
}
});
},

getServices: function() {
var that = this;
return [{
sType: types.ACCESSORY_INFORMATION_STYPE,
characteristics: [{
cType: types.NAME_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: this.name,
supportEvents: false,
supportBonjour: false,
manfDescription: "Name of the accessory",
designedMaxLength: 255
},{
cType: types.MANUFACTURER_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "LiftMaster",
supportEvents: false,
supportBonjour: false,
manfDescription: "Manufacturer",
designedMaxLength: 255
},{
cType: types.MODEL_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "Rev-1",
supportEvents: false,
supportBonjour: false,
manfDescription: "Model",
designedMaxLength: 255
},{
cType: types.SERIAL_NUMBER_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "A1S2NASF88EW",
supportEvents: false,
supportBonjour: false,
manfDescription: "SN",
designedMaxLength: 255
},{
cType: types.IDENTIFY_CTYPE,
onUpdate: null,
perms: ["pw"],
format: "bool",
initialValue: false,
supportEvents: false,
supportBonjour: false,
manfDescription: "Identify Accessory",
designedMaxLength: 1
}]
},{
sType: types.GARAGE_DOOR_OPENER_STYPE,
characteristics: [{
cType: types.NAME_CTYPE,
onUpdate: null,
perms: ["pr"],
format: "string",
initialValue: "Garage Door Opener Control",
supportEvents: false,
supportBonjour: false,
manfDescription: "Name of service",
designedMaxLength: 255
},{
cType: types.CURRENT_DOOR_STATE_CTYPE,
onUpdate: function(value) { that.log("Update current state to " + value); },
perms: ["pr","ev"],
format: "int",
initialValue: 0,
supportEvents: false,
supportBonjour: false,
manfDescription: "BlaBla",
designedMinValue: 0,
designedMaxValue: 4,
designedMinStep: 1,
designedMaxLength: 1
},{
cType: types.TARGET_DOORSTATE_CTYPE,
onUpdate: function(value) { that.setState(value); },
perms: ["pr","pw","ev"],
format: "int",
initialValue: 0,
supportEvents: false,
supportBonjour: false,
manfDescription: "BlaBla",
designedMinValue: 0,
designedMaxValue: 1,
designedMinStep: 1,
designedMaxLength: 1
},{
cType: types.OBSTRUCTION_DETECTED_CTYPE,
onUpdate: function(value) { that.log("Obstruction detected: " + value); },
perms: ["pr","ev"],
format: "bool",
initialValue: false,
supportEvents: false,
supportBonjour: false,
manfDescription: "BlaBla"
}]
}];
}
};

module.exports.accessory = LiftMasterAccessory;

@nfarina

This comment has been minimized.

Show comment
Hide comment
@nfarina

nfarina Sep 6, 2015

Owner

That is strange ... the version in master works fine for me? Have you made any modifications to this file? I notice the extra APP_ID parameter in your pasted source. Also the error complains about a URI that begins with http:// instead of the correct https://.

Owner

nfarina commented Sep 6, 2015

That is strange ... the version in master works fine for me? Have you made any modifications to this file? I notice the extra APP_ID parameter in your pasted source. Also the error complains about a URI that begins with http:// instead of the correct https://.

@shawc

This comment has been minimized.

Show comment
Hide comment
@shawc

shawc Sep 7, 2015

Thanks for the response. I checked the liftmaster.js file and all 3 URI references have https:// prefix. I thought that the appID was bad so I tried replacing that variable with another string that I was manually able to create and get an XML response that provided me with my garage door device ID.

Can you include your liftmaster.js file without your username, password and other specifics? I will replace what I have and see if that works.

Sent from my iPhone

On Sep 6, 2015, at 6:38 PM, Nick Farina <notifications@github.commailto:notifications@github.com> wrote:

That is strange ... the version in master works fine for me? Have you made any modifications to this file? I notice the extra APP_ID parameter in your pasted source. Also the error complains about a URI that begins with http:// instead of the correct https://.

Reply to this email directly or view it on GitHubhttps://github.com/nfarina/homebridge/issues/136#issuecomment-138137131.

Confidentiality Notice: This e-mail communication and any
attachments may contain confidential and privileged information for
the use of the designated recipients named above. If you are not
the intended recipient, you are hereby notified that you have
received this communication in error and that any review,
disclosure, dissemination, distribution or copying of it or its
contents is prohibited. If you have received this communication in
error, please notify me immediately by replying to this message and
deleting it from your computer. Thank you.

shawc commented Sep 7, 2015

Thanks for the response. I checked the liftmaster.js file and all 3 URI references have https:// prefix. I thought that the appID was bad so I tried replacing that variable with another string that I was manually able to create and get an XML response that provided me with my garage door device ID.

Can you include your liftmaster.js file without your username, password and other specifics? I will replace what I have and see if that works.

Sent from my iPhone

On Sep 6, 2015, at 6:38 PM, Nick Farina <notifications@github.commailto:notifications@github.com> wrote:

That is strange ... the version in master works fine for me? Have you made any modifications to this file? I notice the extra APP_ID parameter in your pasted source. Also the error complains about a URI that begins with http:// instead of the correct https://.

Reply to this email directly or view it on GitHubhttps://github.com/nfarina/homebridge/issues/136#issuecomment-138137131.

Confidentiality Notice: This e-mail communication and any
attachments may contain confidential and privileged information for
the use of the designated recipients named above. If you are not
the intended recipient, you are hereby notified that you have
received this communication in error and that any review,
disclosure, dissemination, distribution or copying of it or its
contents is prohibited. If you have received this communication in
error, please notify me immediately by replying to this message and
deleting it from your computer. Thank you.

@SphtKr

This comment has been minimized.

Show comment
Hide comment
@SphtKr

SphtKr Sep 13, 2015

Contributor

A thought, do you have a garage door opener with wifi built in, or their ~2014 bridge device? I have the bridge device, and I found that I still needed to find and specify my garage door ID (I only have one opener also) because it counts the bridge as a device...so I had two device IDs. I don't recall getting the error you have, but it might have been.

Contributor

SphtKr commented Sep 13, 2015

A thought, do you have a garage door opener with wifi built in, or their ~2014 bridge device? I have the bridge device, and I found that I still needed to find and specify my garage door ID (I only have one opener also) because it counts the bridge as a device...so I had two device IDs. I don't recall getting the error you have, but it might have been.

@spock888

This comment has been minimized.

Show comment
Hide comment
@spock888

spock888 Oct 5, 2015

I just got it to work... I don't think you need to modify the accessories/LiftMaster.js file, just add the blocks under accessories to the config.json file. I could not figure out my requiredDevice ID, so I used an empty value for the requiredDeviceID. The log of npm gave me these along with the descriptions. I plugged them in config.son file under two separate blocks. Siri is able to open and close them now.

However, the status in Insteon+(I am using this as the HomeKit DB) is incorrectly showing as open always. MyQ shows correctly and I have cameras in my garage to confirm the state of the garage doors!

Hope this helps (and someone can help me with the incorrect state of these doors in Insteon+)

spock888 commented Oct 5, 2015

I just got it to work... I don't think you need to modify the accessories/LiftMaster.js file, just add the blocks under accessories to the config.json file. I could not figure out my requiredDevice ID, so I used an empty value for the requiredDeviceID. The log of npm gave me these along with the descriptions. I plugged them in config.son file under two separate blocks. Siri is able to open and close them now.

However, the status in Insteon+(I am using this as the HomeKit DB) is incorrectly showing as open always. MyQ shows correctly and I have cameras in my garage to confirm the state of the garage doors!

Hope this helps (and someone can help me with the incorrect state of these doors in Insteon+)

@SphtKr

This comment has been minimized.

Show comment
Hide comment
@SphtKr

SphtKr Oct 6, 2015

Contributor

Yeah--currently it only reports status right (at best) if you only open and close it via Homebridge...kindof annoying. It's on the list of things I want to write a pull request for. To do anything different it'll have to poll MyQ's services every few seconds...which hopefully won't annoy the MyQ servers... :-\

Contributor

SphtKr commented Oct 6, 2015

Yeah--currently it only reports status right (at best) if you only open and close it via Homebridge...kindof annoying. It's on the list of things I want to write a pull request for. To do anything different it'll have to poll MyQ's services every few seconds...which hopefully won't annoy the MyQ servers... :-\

@spock888

This comment has been minimized.

Show comment
Hide comment
@spock888

spock888 Oct 6, 2015

I cannot do anything via the Insteon+ app (neither open nor close my two garage doors). Siri works, and that is huge for me. Thanks to the developers for making this possible :-)

spock888 commented Oct 6, 2015

I cannot do anything via the Insteon+ app (neither open nor close my two garage doors). Siri works, and that is huge for me. Thanks to the developers for making this possible :-)

@u2jrmw

This comment has been minimized.

Show comment
Hide comment
@u2jrmw

u2jrmw Oct 16, 2015

Man I'm glad I found this thread. I have been going nuts trying to get it to report the right open/closed status. I guess that just doesn't work right now. Pretty cool anyway, but the status would really make it sweet. So Liftmaster have said they are not going to make the "bridged" MyQ devices Homekit compatible, but it seems like this proves it is totally doable! Annoying.

u2jrmw commented Oct 16, 2015

Man I'm glad I found this thread. I have been going nuts trying to get it to report the right open/closed status. I guess that just doesn't work right now. Pretty cool anyway, but the status would really make it sweet. So Liftmaster have said they are not going to make the "bridged" MyQ devices Homekit compatible, but it seems like this proves it is totally doable! Annoying.

@nfarina

This comment has been minimized.

Show comment
Hide comment
@nfarina

nfarina Oct 16, 2015

Owner

It shouldn't be too hard to support "reading" status on demand similar to the Lockitron accessory - this way when you ask Siri or visit it in the app, the correct open/close state will be queried "on demand". Also it would be nice to upgrade this accessory to the "new API". I would welcome a PR if anyone wants to tackle it :)

Owner

nfarina commented Oct 16, 2015

It shouldn't be too hard to support "reading" status on demand similar to the Lockitron accessory - this way when you ask Siri or visit it in the app, the correct open/close state will be queried "on demand". Also it would be nice to upgrade this accessory to the "new API". I would welcome a PR if anyone wants to tackle it :)

@SphtKr

This comment has been minimized.

Show comment
Hide comment
@SphtKr

SphtKr Oct 16, 2015

Contributor

It's on my list...other ideas for ZWayServer or YamahaAVR keep coming up 😄

Contributor

SphtKr commented Oct 16, 2015

It's on my list...other ideas for ZWayServer or YamahaAVR keep coming up 😄

@u2jrmw

This comment has been minimized.

Show comment
Hide comment
@u2jrmw

u2jrmw Oct 16, 2015

I'd certainly appreciate the on demand status working. Another question. Does the "obstruction detected" work? Not sure how I even expect that to behave.

u2jrmw commented Oct 16, 2015

I'd certainly appreciate the on demand status working. Another question. Does the "obstruction detected" work? Not sure how I even expect that to behave.

@SphtKr

This comment has been minimized.

Show comment
Hide comment
@SphtKr

SphtKr Oct 17, 2015

Contributor

I don't think it currently works. It should work with the IR safety sensors you can buy and attach to your opener near the bottom of the door track, to disable the door closing if someone or something is standing in the way. I have the sensors but I don't have them hooked up yet...another thing on my to-do list.

Contributor

SphtKr commented Oct 17, 2015

I don't think it currently works. It should work with the IR safety sensors you can buy and attach to your opener near the bottom of the door track, to disable the door closing if someone or something is standing in the way. I have the sensors but I don't have them hooked up yet...another thing on my to-do list.

@jerle69

This comment has been minimized.

Show comment
Hide comment
@jerle69

jerle69 Oct 26, 2015

Not sure where to put this, but I copied the LiftMaster.js and altered it for Craftsman Assurelink, updating the URLS and the APP_ID variables to work. Get the same issues with Insteon+ App not not reporting the correct garage door state, but Siri works :)

jerle69 commented Oct 26, 2015

Not sure where to put this, but I copied the LiftMaster.js and altered it for Craftsman Assurelink, updating the URLS and the APP_ID variables to work. Get the same issues with Insteon+ App not not reporting the correct garage door state, but Siri works :)

@nfarina

This comment has been minimized.

Show comment
Hide comment
@nfarina

nfarina Oct 26, 2015

Owner

Hey that's cool! Could you post the values you changed to make it work? Perhaps we could enhance the shim to support both.

Owner

nfarina commented Oct 26, 2015

Hey that's cool! Could you post the values you changed to make it work? Perhaps we could enhance the shim to support both.

@jerle69

This comment has been minimized.

Show comment
Hide comment
@jerle69

jerle69 Oct 26, 2015

Sure thing... the value for the Craftsman Assurelink (basically the same as the MyQ Liftmaster, but different APP_ID and URL)...

APP_ID = "eU97d99kMG4t3STJZO/Mu2wt69yTQwM0WXZA5oZ74/ascQ2xQrLD/yjeVhEQccBZ"

... for the URLs, they need to start with "https://craftexternal.myqdevice.com/"..

That URL is hard-coded in 3 function calls in the existing Liftmaster.js accessory shim.

It'd be nice if we can get it working with Insteon+ :) As others say in the thread, my door seems always open in the app and the buttons don't work. Siri does tho, which is what I wanted it for.

jerle69 commented Oct 26, 2015

Sure thing... the value for the Craftsman Assurelink (basically the same as the MyQ Liftmaster, but different APP_ID and URL)...

APP_ID = "eU97d99kMG4t3STJZO/Mu2wt69yTQwM0WXZA5oZ74/ascQ2xQrLD/yjeVhEQccBZ"

... for the URLs, they need to start with "https://craftexternal.myqdevice.com/"..

That URL is hard-coded in 3 function calls in the existing Liftmaster.js accessory shim.

It'd be nice if we can get it working with Insteon+ :) As others say in the thread, my door seems always open in the app and the buttons don't work. Siri does tho, which is what I wanted it for.

@u2jrmw

This comment has been minimized.

Show comment
Hide comment
@u2jrmw

u2jrmw Oct 26, 2015

In case anyone is interested I use an app called iDevices. It does not accurately reflect the door status, but it can open and close the door. It also works out of your home network which I've found other apps struggle with.

u2jrmw commented Oct 26, 2015

In case anyone is interested I use an app called iDevices. It does not accurately reflect the door status, but it can open and close the door. It also works out of your home network which I've found other apps struggle with.

@nfarina nfarina closed this Dec 10, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment