lennyby93 / node-mmcontrol

MMcontrol provides an easy way to control Mitsubishi heat pumps that use the MAC-558 WiFi adaptor
MIT License
15 stars 2 forks source link

Help with setup #3

Closed NovaGL closed 7 years ago

NovaGL commented 7 years ago

Thanks for this.

I can login but anything beyond that doesn't work.

I get can't get modeldata of undefined. The tmp files show it's there

"capabilities": [{ "unitid": 0, "offset": 0 }], "state": [{ "unitid": 0 }]

So I don't know what to do

lennyby93 commented 7 years ago

Do you pass the bunyan logger to the constructor? If so - please run your script in the foreground and pipe it to bunyan with -l trace to see what's going on.

If you log in via the original app - can you see and control your heatpump?

lennyby93 commented 7 years ago

that's what the initialisation should look like:

[2017-06-10T08:29:46.933Z] TRACE: controller/10838 on aircon: connect (module=MMcontrol)
[2017-06-10T08:29:46.937Z] TRACE: controller/10838 on aircon: login (module=MMcontrol)
[2017-06-10T08:29:46.939Z] TRACE: controller/10838 on aircon: callAPI - login (module=MMcontrol)
[2017-06-10T08:29:47.139Z] TRACE: controller/10838 on aircon: storeSessionData (module=MMcontrol)
[2017-06-10T08:29:47.140Z] TRACE: controller/10838 on aircon: storeState (module=MMcontrol)
[2017-06-10T08:29:47.141Z] TRACE: controller/10838 on aircon: initialise (module=MMcontrol)
[2017-06-10T08:29:47.144Z] TRACE: controller/10838 on aircon: getting capabilties for: 0 (module=MMcontrol)
[2017-06-10T08:29:47.144Z] TRACE: controller/10838 on aircon: callUnitCapabilites unitid:0 (module=MMcontrol)
[2017-06-10T08:29:47.144Z] TRACE: controller/10838 on aircon: callAPI - unitcapabilities (module=MMcontrol)
[2017-06-10T08:29:47.212Z] TRACE: controller/10838 on aircon: storeSessionData (module=MMcontrol)
[2017-06-10T08:29:47.212Z] TRACE: controller/10838 on aircon: storeState (module=MMcontrol)
[2017-06-10T08:29:47.214Z] TRACE: controller/10838 on aircon: getting model data for 0 (module=MMcontrol)
[2017-06-10T08:29:47.215Z] TRACE: controller/10838 on aircon: parseCapabilities unitid: 0 (module=MMcontrol)
[2017-06-10T08:29:47.217Z] TRACE: controller/10838 on aircon: (module=MMcontrol)
    {
     "action": {
      "setmode": "MD",
      "setfan": "FS",
      "power": "PW",
      "settemp": "TS"
     },
     "setmode": {
      "heat": "1",
      "dry": "2",
      "cool": "3",
      "fan": "7",
      "auto": "8"
     },
     "power": {
      "on": "1",
      "off": "0"
     },
     "setfan": {
      "1": "2",
      "2": "3",
      "3": "5"
     },
     "airdirh": {},
     "airdir": {
      "auto": "0"
     }
    }
[2017-06-10T08:29:47.219Z] TRACE: controller/10838 on aircon: getting state for: 0 (module=MMcontrol)
[2017-06-10T08:29:47.220Z] TRACE: controller/10838 on aircon: callUnitState unitid:0 (module=MMcontrol)
[2017-06-10T08:29:47.220Z] TRACE: controller/10838 on aircon: callAPI - unitcommand (module=MMcontrol)
[2017-06-10T08:29:47.241Z] TRACE: controller/10838 on aircon: storeSessionData (module=MMcontrol)
[2017-06-10T08:29:47.241Z] TRACE: controller/10838 on aircon: storeState (module=MMcontrol)
[2017-06-10T08:29:47.242Z] TRACE: controller/10838 on aircon: compareStates (module=MMcontrol)
[2017-06-10T08:29:47.243Z] TRACE: controller/10838 on aircon: storeState (module=MMcontrol)
[2017-06-10T08:29:47.251Z] TRACE: controller/10838 on aircon: setTemperatureOffset (unitid:0) to 0 (module=MMcontrol)

when using this (log is a bunyan logger):

var controller = new MMcontrol({
    "username": "xxxx",
    "password": "xxx",
    "log": log,
    "trackState": true,
    "minRefresh": 45,
    "persistance": false
});

controller.connect(true, function (err) {
    if (err) {
        log.error("couldn't connect: " + err);
    } else {
       controller.setTemperatureOffset(0, 0, function (err) { 
....
NovaGL commented 7 years ago

Well first of one of my problems was a newbie error.

Maybe posting a full example would help me.

Now I get

getUnitList returns [null]

getCurrentState returns couldn't get the current state: API error: no unitid

Also If I set controller.connect(false, function (err)

I always get unauthorised but setting it to true works which is weird.

lennyby93 commented 7 years ago

are you actually running a 'connect' at the beginning of your script? getUnitList basically parses the data obtained during connect to get you the list. Something like this should work fine:

controller.connect(true, function (err) {
    if (err) {
        log.error("couldn't connect: " + err);
    } else {
        controller.getUnitList(function (err, data) {
            if (err) {
                log.error("can't get the list: %s", err)
            }
            log.debug("unitlist: %s", JSON.stringify(data, null, 1))
        });
    }
});

gives me this (with /tmp/state.txt removed):

$ node ./test.js | bunyan -l trace
[2017-06-10T09:13:56.391Z] TRACE: controller/63874 on testcontroller: connect (module=MMcontrol)
[2017-06-10T09:13:56.393Z] TRACE: controller/63874 on testcontroller: loadState (module=MMcontrol)
[2017-06-10T09:13:56.393Z] TRACE: controller/63874 on testcontroller: loadJSONFile (module=MMcontrol)
[2017-06-10T09:13:56.394Z] TRACE: controller/63874 on testcontroller: can't load JSON file (/tmp/state.txt): Error: ENOENT: no such file or directory, open '/tmp/state.txt' (module=MMcontrol)
[2017-06-10T09:13:56.394Z] TRACE: controller/63874 on testcontroller: login (module=MMcontrol)
[2017-06-10T09:13:56.395Z] TRACE: controller/63874 on testcontroller: callAPI - login (module=MMcontrol)
[2017-06-10T09:13:56.549Z] TRACE: controller/63874 on testcontroller: storeSessionData (module=MMcontrol)
[2017-06-10T09:13:56.550Z] TRACE: controller/63874 on testcontroller: storeState (module=MMcontrol)
[2017-06-10T09:13:56.550Z] TRACE: controller/63874 on testcontroller: storeJSONFile (module=MMcontrol)
[2017-06-10T09:13:56.552Z] TRACE: controller/63874 on testcontroller: initialise (module=MMcontrol)
[2017-06-10T09:13:56.553Z] TRACE: controller/63874 on testcontroller: getting capabilties for: 0 (module=MMcontrol)
[2017-06-10T09:13:56.553Z] TRACE: controller/63874 on testcontroller: callUnitCapabilites unitid:0 (module=MMcontrol)
[2017-06-10T09:13:56.553Z] TRACE: controller/63874 on testcontroller: callAPI - unitcapabilities (module=MMcontrol)
[2017-06-10T09:13:56.577Z] TRACE: controller/63874 on testcontroller: storeSessionData (module=MMcontrol)
[2017-06-10T09:13:56.577Z] TRACE: controller/63874 on testcontroller: storeState (module=MMcontrol)
[2017-06-10T09:13:56.577Z] TRACE: controller/63874 on testcontroller: storeJSONFile (module=MMcontrol)
[2017-06-10T09:13:56.578Z] TRACE: controller/63874 on testcontroller: getting model data for 0 (module=MMcontrol)
[2017-06-10T09:13:56.579Z] TRACE: controller/63874 on testcontroller: parseCapabilities unitid: 0 (module=MMcontrol)
[2017-06-10T09:13:56.579Z] TRACE: controller/63874 on testcontroller: (module=MMcontrol)
    {
     "action": {
      "setmode": "MD",
      "setfan": "FS",
      "power": "PW",
      "settemp": "TS"
     },
     "setmode": {
      "heat": "1",
      "dry": "2",
      "cool": "3",
      "fan": "7",
      "auto": "8"
     },
     "power": {
      "on": "1",
      "off": "0"
     },
     "setfan": {
      "1": "2",
      "2": "3",
      "3": "5"
     },
     "airdirh": {},
     "airdir": {
      "auto": "0"
     }
    }
[2017-06-10T09:13:56.580Z] TRACE: controller/63874 on testcontroller: getting state for: 0 (module=MMcontrol)
[2017-06-10T09:13:56.580Z] TRACE: controller/63874 on testcontroller: callUnitState unitid:0 (module=MMcontrol)
[2017-06-10T09:13:56.580Z] TRACE: controller/63874 on testcontroller: callAPI - unitcommand (module=MMcontrol)
[2017-06-10T09:13:56.599Z] TRACE: controller/63874 on testcontroller: storeSessionData (module=MMcontrol)
[2017-06-10T09:13:56.599Z] TRACE: controller/63874 on testcontroller: storeState (module=MMcontrol)
[2017-06-10T09:13:56.599Z] TRACE: controller/63874 on testcontroller: storeJSONFile (module=MMcontrol)
[2017-06-10T09:13:56.600Z] TRACE: controller/63874 on testcontroller: compareStates (module=MMcontrol)
[2017-06-10T09:13:56.600Z] TRACE: controller/63874 on testcontroller: storeState (module=MMcontrol)
[2017-06-10T09:13:56.600Z] TRACE: controller/63874 on testcontroller: storeJSONFile (module=MMcontrol)
[2017-06-10T09:13:56.601Z] TRACE: controller/63874 on testcontroller: getUnitList (module=MMcontrol)
[2017-06-10T09:13:56.601Z] DEBUG: controller/63874 on testcontroller:
    unitlist: [
     "Main unit"
    ]

(I called my unit 'Main unit')

NovaGL commented 7 years ago

Deleting the state.txt I get couldn't connect: API error: unauthorised

I does create a state.txt with the correct amount of units.

Your code does exactly the same that mine does.

Just returns null.

It looks like an authentication problem but I can't figure out why.

Here is my full code

var MMcontrol = require('mmcontrol');

var controller = new MMcontrol({
    'username': 'abc@def.com',
    'password': '12345',
    'tmpDir':'C:\\Temp'
});

controller.connect(true, function (err) {
    if (err) {
        console.log("couldn't connect: " + err);
    } else {
        controller.getUnitList(function (err, data) {
            if (err) {
                console.error("can't get the list: %s", err)
            }
            console.log("unitlist: %s", JSON.stringify(data, null, 1))
        });
    }
});
NovaGL commented 7 years ago

Any ideas?

{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"connect","time":"2017-06-08T21:35:02.064Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"login","time":"2017-06-08T21:35:02.065Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"callAPI - login","time":"2017-06-08T21:35:02.065Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"storeSessionData","time":"2017-06-08T21:35:02.410Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"storeState","time":"2017-06-08T21:35:02.410Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"storeJSONFile","time":"2017-06-08T21:35:02.410Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"initialise","time":"2017-06-08T21:35:02.412Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"getting capabilties for: 0","time":"2017-06-08T21:35:02.413Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"callUnitCapabilites unitid:0","time":"2017-06-08T21:35:02.413Z","v":0}
{"name":"MMcontrol","hostname":"PI","pid":16814,"module":"MMcontrol","level":10,"msg":"callAPI - unitcapabilities","time":"2017-06-08T21:35:02.413Z","v":0}
lennyby93 commented 7 years ago

Try using curl directly and see if you can get details that way:

curl -H "Accept: application/json" -X POST -v -d "{user: 'xxxx@xxx.xxx', pass: 'xxxxx', appversion: '3.0.513'}" https://api.melview.net/api/login.aspx

Response should look like this:

*   Trying 202.36.76.34...
* TCP_NODELAY set
* Connected to api.melview.net (202.36.76.34) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
* Server certificate: *.melview.net
* Server certificate: RapidSSL SHA256 CA
* Server certificate: GeoTrust Global CA
> POST /api/login.aspx HTTP/1.1
> Host: api.melview.net
> User-Agent: curl/7.51.0
> Accept: application/json
> Content-Length: 70
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 70 out of 70 bytes
< HTTP/1.1 200 OK
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< Content-Type: application/json; charset=utf-8
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 4.0.30319
< Set-Cookie: auth=A58E7013BE93F71BFD905C91DB9D3C98F5B6312323CF58013E1D457F6615221D4C471B2CF151EA692D70A805F5FE06ECFE94BDD555AC14006481214EE3A7D7E9D1041E18AC1C6C2C1A08A158431A584EB1444E5BA15FDF5A6731197EDFE1AC18463244B7D3110DD9C3421AC62BA7EE3694F21B02FDEC8E227XXXXXXXXXXXX; domain=.melview.net; expires=Sat, 09-Sep-2017 09:50:03 GMT; path=/
< X-Powered-By: ASP.NET
< Date: Sun, 11 Jun 2017 09:50:03 GMT
< Content-Length: 711
<
* Curl_http_done: called premature == 0
* Connection #0 to host api.melview.net left intact
{"id":1234,"country":"New Zealand","fullname":"Your Name","confirmcode":0,"userunits":1,"countryinfo":[{"country":"Australia","companyname":"Mitsubishi Electric Australia","supportphone":"1300 728 119","supporturl":"http://www.mitsubishielectric.com.au/wifi","addunitnote":"Find your MAC and ID on page 6 of interface install manual or the back of the Wi-Fi Adaptor."},{"country":"New Zealand","companyname":"Mitsubishi Electric New Zealand","supportphone":"0800 639 434","supporturl":"http://www.mitsubishi-electric.co.nz/wifi#support","addunitnote":"Find your MAC and ID on page 2 of installation guide or the back of the Wi-Fi Adaptor."}],"features":{"groupcontrol":1,"zonerules":1,"halfdegcontrol":1}}

The important header is the one with 'Set-Cookie', as the cookie is later used for all other operations

Can you log in using the original app?

NovaGL commented 7 years ago

Curl works.

I can get unit ids via HTTP POST to https://api.melview.net/api/rooms.aspx

I think I might just do it manually

lennyby93 commented 7 years ago

This library doesn't use the /api/rooms.aspx get the unit list. Do you have multiple units or multiple rooms in your setup?

NovaGL commented 7 years ago

I do have multiple units. I didn't want to post the full list.

Just don't understand why your app returns null but the app returns the correct info

lennyby93 commented 7 years ago

I only have a single unit to test with. In a single unit scenario all the details are returned in the first login call (you can see that in curl output above). I get unit id (1234) directly from login. That's obviously is not the case in your setup.

I can add that to the library but I'd like to know what you get as a result from login and from the rooms.aspx as well (you can obfuscate any ids)

NovaGL commented 7 years ago

Hmm, it seems the ID in the login isn't an ID for any of my rooms

Rooms.aspx the request passes an id but I think its just a random session id so not really needed. You can just use the cookie and that's all.

Here is the response.

[{
        "buildingid": "9999",
        "building": "Building",
        "bschedule": "0",
        "units": [{
                "room": "ROOM1",
                "unitid": "1234",
                "power": "q",
                "wifi": "3",
                "mode": "1",
                "temp": "19",
                "settemp": "24",
                "status": "",
                "schedule1": 0
            }, {
                "room": "ROOM2",
                "unitid": "456",
                "power": "q",
                "wifi": "3",
                "mode": "3",
                "temp": "18",
                "settemp": "19",
                "status": "",
                "schedule1": 0
            }
        ]
    }
]
NovaGL commented 7 years ago

If you are interested my aim is to integrate with Alexa,

Here is how my flow goes - http://imgur.com/e9hYcWA

It loops through all the rooms and stores them in a variable with that room name.

Eg Room 1 is saved in variable ROOM1 room2 in ROOM2 etc.

Now I can just say "Alexa, what's the temperature in Room 1" she pulls the data from that variable and speaks it out.

Works great. Next job turning on and off and temperature control.

NovaGL commented 7 years ago

Made my own custom app.

So I can do turn on\off, set lower set higher. Set specific temp and ask for current temp all via Alexa

so i wont be using your app, but if you would like me to test something out just open this issue up again

lennyby93 commented 7 years ago

Thx for the offer.

Wob76 commented 7 years ago

@NovaGL Any chance you have published your app, I would like to do something similar with Google Home, and maybe look at integrating with some separate temp sensors in my rooms to turn on\off the zones. Are you using nodered to create your flows?

NovaGL commented 7 years ago

@Wob76 Hi.

Sure am using Nide-Red.

If I get time I will create a repo with the flow in it.

Basically three steps

Login Save Room Data Room action

Mine is setup with Alexa. So I just say " Alexa, what is the temperature in my room" or "Alexa turn on my room"

Wob76 commented 7 years ago

@NovaGL That would be great, thanks.

Are you controlling zones or separate split systems? Just wondering from a control and temp angle, as my unit seems to only give me a global average temp, not a per room temp.

NovaGL commented 7 years ago

@Wob76

Ducted, one unit per room. See above for the output I get.

NovaGL commented 7 years ago

@Wob76 See here https://github.com/NovaGL/diy-melview