bytespider / Meross

Investigating the Meross/Refoss MSS310 Smart Plug and getting these devices to communicate with our private MQTT brokers
113 stars 19 forks source link

Plug keeps blinking green forever #64

Closed boar24 closed 1 year ago

boar24 commented 1 year ago

Dear all,

after spending many hours I still have no success in connecting my new smart WiFi plugs Refoss MSS210W to Mosquitto. I am following the procedure by Rob Griffiths, but am stuck at where the meross-setup utility is used. After I try to bind the plug to my Mosquitto broker at 192.168.188.30 with the command ./meross-setup --gateway 10.10.10.1 --wifi-ssid assid162 --wifi-pass 3438XXXXXXXXXXXX7725 --mqtt mqtts://192.168.188.30 --mqtt mqtts://192.168.188.30 the plug

The plug remains in this state forever. I have no clue on how to proceed and would highly appreciate any suggestions. The plugs work correctly when connected to the Meross cloud / eHomeLife-App.

The Mosquitto server was installed from mosquitto-2.0.15-install-windows-x64.exe on a Windows10 machine with IP 192.168.188.30. The instance uses the following mosquitto.conf, which corresponds to that of Rob Griffiths:

listener 8883
allow_anonymous true
require_certificate false
cafile   ssl/ca.crt
certfile ssl/broker.crt
keyfile  ssl/broker.key

The three certificate files have been created on WSL/Ubuntu with this script makeCerts.sh, based on the one from ElBobo:

# !/usr/bin/env bash
mkdir ssl 
ssldir=./ssl 

# CA: certification authority
openssl genrsa                                           -out $ssldir/ca.key     2048 
openssl req    -new -x509 -days 1826 -key $ssldir/ca.key -out $ssldir/ca.crt     -subj "/C=CH/ST=BE/L=BE/O=Private/OU=Dep0/CN=stdifferent.30" 

# certificate 
openssl genrsa                                           -out $ssldir/broker.key 2048 
openssl req    -new             -out $ssldir/broker.csr  -key $ssldir/broker.key -subj "/C=CH/ST=BE/L=BE/O=Private/OU=Dep1/CN=192.168.188.30"

openssl x509   -req -in $ssldir/broker.csr -CA $ssldir/ca.crt -CAkey $ssldir/ca.key -CAcreateserial -out $ssldir/broker.crt -days 1826 

cp makeCerts.sh $ssldir/.

Note that it does not use the -des3 option which Rob uses. I also made sure that the Organisational Names are not identical, as pointed out by sheran29.

I have opened a second commandline window on the PC and successfully attached a subscriber to the running Mosquitto broker: mosquitto_sub -h 192.168.188.30 -t "#" -t "/#" --cafile ssl/ca.crt

It successfully receives messages that I send from a third commandline window, e.g.: mosquitto_pub -h 192.168.188.30 -p 8883 -t "test7" -m "message7" --cafile ssl/ca.crt

Here is a screenshot of the broker with three blocks:

grafik From this I would say that Mosquitto and the certificates are OK.

Now, as I said in the beginning, after the plug is reconfigured with ./meross-setup --gateway 10.10.10.1 --wifi-ssid assid162 --wifi-pass 3438XXXXXXXXXXXX7725 --mqtt mqtts://192.168.188.30 --mqtt mqtts://192.168.188.30 it behaves as stated above. The Mosquitto broker and hence the subscriber see messages of types Appliance.Control.Bind and Appliance.System.Report, and this continues forever. What can I do?

Output from the broker:

1690725142: New connection from 192.168.188.31:52884 on port 8883.
1690725143: New client connected from 192.168.188.31:52884 as fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (p1, c1, k120, u'48:XX:XX:XX:XX:17').
1690725143: No will message specified.
1690725143: Sending CONNACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (0, 0)
1690725143: Received SUBSCRIBE from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725143:     /appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe (QoS 1)
1690725143: fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA 1 /appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe
1690725143: Sending SUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725143: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m227, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (388 bytes))
1690725143: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (388 bytes))
1690725143: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m227, rc0)
1690725143: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m228, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725143: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725143: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m228, rc0)
1690725148: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m229, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725148: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725148: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m229, rc0)
1690725153: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m230, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725153: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725153: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m230, rc0)
1690725158: Received DISCONNECT from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725158: Client fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA disconnected.
1690725167: New connection from 192.168.188.31:52885 on port 8883.
1690725167: New client connected from 192.168.188.31:52885 as fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (p1, c1, k120, u'48:XX:XX:XX:XX:17').
1690725167: No will message specified.
1690725167: Sending CONNACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (0, 0)
1690725167: Received SUBSCRIBE from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725167:     /appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe (QoS 1)
1690725167: fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA 1 /appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe
1690725167: Sending SUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725167: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m232, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (389 bytes))
1690725167: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (389 bytes))
1690725167: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m232, rc0)
1690725167: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m233, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725167: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725167: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m233, rc0)
1690725172: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m234, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725172: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725172: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m234, rc0)
1690725177: Received PUBLISH from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (d0, q1, r0, m235, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725177: Sending PUBLISH to auto-4899B759-2D01-9D43-97C8-918DF0A9A65A (d0, q0, r0, m0, '/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish', ... (766 bytes))
1690725177: Sending PUBACK to fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA (m235, rc0)
1690725182: Received DISCONNECT from fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA
1690725182: Client fmware:2211XXXXXXXXXXXXXXXXXXXXXXXX7317_qqocyGoCpeCzBsXA disconnected.

Output from the subscriber:

{"header":{"messageId":"f81cXXXXXXXXXXXXXXXXXXXXXXXX5bc1","namespace":"Appliance.System.Report","method":"PUSH","payloadVersion":1,"from":"/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish","uuid":"2211XXXXXXXXXXXXXXXXXXXXXXXX7317","timestamp":1690724715,"timestampMs":338,"sign":"c435XXXXXXXXXXXXXXXXXXXXXXXX918a"},"payload":{"report":[{"type":"1","value":"1","timestamp":1690724715}]}}
{"header":{"messageId":"4ddbXXXXXXXXXXXXXXXXXXXXXXXX10b5","namespace":"Appliance.Control.Bind","method":"SET","payloadVersion":1,"from":"/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe","uuid":"2211XXXXXXXXXXXXXXXXXXXXXXXX7317","timestamp":1690724715,"timestampMs":372,"sign":"df58XXXXXXXXXXXXXXXXXXXXXXXX9b67"},"payload":{"bind":{"bindTime":1690724715,"time":{"timestamp":1690724715,"timezone":"","timeRule":[]},"hardware":{"type":"mss210","subType":"un","version":"6.0.0","chipType":"rtl8710cf","uuid":"2211XXXXXXXXXXXXXXXXXXXXXXXX7317","macAddress":"48:XX:XX:XX:XX:17"},"firmware":{"version":"6.2.3","compileTime":"2021/10/22-11:13:43","encrypt":1,"wifiMac":"5c:XX:XX:XX:XX:03","innerIp":"192.168.188.31","server":"192.168.188.30","port":8883,"userId":0}}}}

The same in prettyfied form:

{
  "header": {
    "messageId": "f81cXXXXXXXXXXXXXXXXXXXXXXXX5bc1",
    "namespace": "Appliance.System.Report",
    "method": "PUSH",
    "payloadVersion": 1,
    "from": "/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish",
    "uuid": "2211XXXXXXXXXXXXXXXXXXXXXXXX7317",
    "timestamp": 1690724715,
    "timestampMs": 338,
    "sign": "c435XXXXXXXXXXXXXXXXXXXXXXXX918a"
  },
  "payload": {
    "report": [
      {
        "type": "1",
        "value": "1",
        "timestamp": 1690724715
      }
    ]
  }
}

{
  "header": {
    "messageId": "4ddbXXXXXXXXXXXXXXXXXXXXXXXX10b5",
    "namespace": "Appliance.Control.Bind",
    "method": "SET",
    "payloadVersion": 1,
    "from": "/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe",
    "uuid": "2211XXXXXXXXXXXXXXXXXXXXXXXX7317",
    "timestamp": 1690724715,
    "timestampMs": 372,
    "sign": "df58XXXXXXXXXXXXXXXXXXXXXXXX9b67"
  },
  "payload": {
    "bind": {
      "bindTime": 1690724715,
      "time": {
        "timestamp": 1690724715,
        "timezone": "",
        "timeRule": []
      },
      "hardware": {
        "type": "mss210",
        "subType": "un",
        "version": "6.0.0",
        "chipType": "rtl8710cf",
        "uuid": "2211XXXXXXXXXXXXXXXXXXXXXXXX7317",
        "macAddress": "48:XX:XX:XX:XX:17"
      },
      "firmware": {
        "version": "6.2.3",
        "compileTime": "2021/10/22-11:13:43",
        "encrypt": 1,
        "wifiMac": "5c:XX:XX:XX:XX:03",
        "innerIp": "192.168.188.31",
        "server": "192.168.188.30",
        "port": 8883,
        "userId": 0
      }
    }
  }
}

What can I do?

bytespider commented 1 year ago

Does this work for you? https://github.com/bytespider/Meross/issues/57#issuecomment-1416789185

boar24 commented 1 year ago

Wow, in deed! I sent mosquitto_pub -h 192.168.188.30 -p 8883 --cafile ssl/ca.crt -t "/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe" -m "{""header"":{""messageId"":""2960cfeef370338255f669525209abca"",""namespace"":""Appliance.Control.Bind"",""timestamp"":""1690744475"",""method"":""SETACK"",""sign"":""a246aa1f28f1a1d7b4a4cdc46ba6ad40"",""from"":""/cloud/hook/subscribe""},""payload"":{}}" where I reused the messageId, timestamp and sign of an incoming message. And I had to convert the quotes to double quotes - as I am on Windows. And this stopped the blinking. Hooray! Thanks a lot for nudging me onto the solution!

Now, when I press the plug's button, I can see in the broker and the attached subscriber that an Appliance.Control.ToggleX message comes in: {"header":{"messageId":"690a3f909feba1ef9852c0403024783f","namespace":"Appliance.Control.ToggleX","method":"PUSH","payloadVersion":1,"from":"/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/publish","uuid":"2211XXXXXXXXXXXXXXXXXXXXXXXX7317","timestamp":1690752350,"timestampMs":967,"sign":"9ee7114ec23b648e3ac2f391a58fd3ed"},"payload":{"togglex":[{"channel":0,"onoff":1,"lmTime":1690752350}]}} Looks good!

Now, for the other way around, i.e. controlling the plug, I tried to send a similar message towards the plug: mosquitto_pub -h 192.168.188.30 -p 8883 --cafile ssl/ca.crt -t "/appliance/2211XXXXXXXXXXXXXXXXXXXXXXXX7317/subscribe" -m "{""header"":{""messageId"":""690a3f909feba1ef9852c0403024783f"",""namespace"":""Appliance.Control.ToggleX"",""method"":""SET"",""payloadVersion"":1,""from"":""mosquitto_pub"",""uuid"":""2211XXXXXXXXXXXXXXXXXXXXXXXX7317"",""timestamp"":1690752350,""sign"":""9ee7114ec23b648e3ac2f391a58fd3ed""},""payload"":{""togglex"":[{""channel"":0,""onoff"":0,""lmTime"":1690752350}]}}" It has

The plug only reacts on the message

So far so good. I understand that to do it properly, I must use a random messageId, a correct timestamp, the correct key and a signing value equal to md5(messageId + key + timestamp). This should be doable without too much programming effort, analogue to the code fragment which is posted here for Symcon. However, I would assume that there is tool or library around to do this, just couldn't find something. Could you possibly point me into the right direction? I am looking for a simple plain command line tool, without an integration in HomeAssistant or the like.

lechercheur123 commented 1 year ago

If you want to do this with python 3, here are some tips:

To generate random messageId:

messageId = str(random.randbytes(16).hex())

To calculate the timestamp:

timestamp = int(datetime.now(timezone.utc).timestamp())

To calculate the sign:

key = "customkey"
stringToHash = messageId+ key + str(timestamp)
hash = hashlib.md5(stringToHash.encode())
sign = hash.hexdigest()

As an example here is how I generate the JSON for my use cases (unfortunately I don't use ToggleX, so I added a short section at the end that should help you):

def generateMqttMessage(uuid, key, messageType, namespace, messageId=None, onoff=1):
        data={}
        data["header"]={}
        data["header"]["from"]="/app/0-"+uuid+"/subscribe"
        if(messageId == None):
                data["header"]["messageId"]=str(random.randbytes(16).hex())
        else:
                data["header"]["messageId"]=messageId
        data["header"]["method"]=messageType
        data["header"]["namespace"]=namespace
        data["header"]["payloadVersion"]=1
        data["header"]["sign"]="0"
        data["header"]["timestamp"]=int(datetime.now(timezone.utc).timestamp())
        stringToHash = data["header"]["messageId"] + key + str(data["header"]["timestamp"])
        hash=hashlib.md5(stringToHash.encode())
        data["header"]["sign"]=hash.hexdigest()

        data["payload"]={}
        if(namespace == "Appliance.System.Clock"):
                data["payload"]["clock"]={}
                data["payload"]["clock"]["timestamp"]=data["header"]["timestamp"]
        elif(namespace == "Appliance.System.Time"):
                data["payload"]["time"]={}
                data["payload"]["time"]["timestamp"]=data["header"]["timestamp"]
                data["payload"]["time"]["timezone"] = "Europe/Paris"
                data["payload"]["time"]["timeRule"] = []

                tm = tz.gettz(data["payload"]["time"]["timezone"])
                now=datetime.now(tm)
                # Previous end or debut of DST
                if(datetime.dst(now) != timedelta()):
                        dst1 = now + relativedelta(month=3, day=31, weekday=SU(-1), second=0, minute=0, hour=3, microsecond=0)
                        dst2 = now + relativedelta(month=10, day=31, weekday=SU(-1), second=59, minute=59, hour=2, microsecond=0)
                        dst3 = now + relativedelta(years=1, month=3, day=31, weekday=SU(-1), second=0, minute=0, hour=3, microsecond=0)
                        dst1on = 1
                        dst2on = 0
                        dst3on = 1
                else:
                        dst2 = now + relativedelta(month=3, day=31,  weekday=SU(-1), second=0, minute=0, hour=3)
                        if(now < dst2):
                                dst1 = now + relativedelta(years=-1, month=10, day=31, weekday=SU(-1), second=59, minute=59, hour=2)
                                dst3 = now + relativedelta(month=10, day=31, weekday=SU(-1), second=59, minute=59, hour=2)
                        else:
                                dst1 = now + relativedelta(month=10, day=31, weekday=SU(-1), second=59, minute=59, hour=2, microsecond=0)
                                dst2 = now + relativedelta(years=1, month=3, day=31, weekday=SU(-1), second=0, minute=0, hour=3, microsecond=0)
                                dst3 = now + relativedelta(years=1, month=10, day=31, weekday=SU(-1), second=59, minute=59, hour=2, microsecond=0)
                        dst1on = 0
                        dst2on = 1
                        dst3on = 0

                data["payload"]["time"]["timeRule"].append([int(dst1.timestamp()) + dst2on, 3600 + (dst1on*3600), dst1on])
                data["payload"]["time"]["timeRule"].append([int(dst2.timestamp()) + dst1on, 3600 + (dst2on*3600), dst2on])
                data["payload"]["time"]["timeRule"].append([int(dst3.timestamp()) + dst2on, 3600 + (dst3on*3600), dst3on])

        elif(namespace == "Appliance.Control.Electricity"):
                data["payload"]["channel"] = 0
        elif(namespace == "Appliance.Control.ConsumptionX"):
                pass
        elif(namespace == "Appliance.Control.Bind"):
                pass
        elif(namespace == "Appliance.System.Report"):
                pass
        # Just added right now for @Traveler4 but not tested
        elif(namespace == "Appliance.Control.ToggleX"):
                item = {}
                item["channel"] = 0
                item["onoff"] = onoff
                item["lmTime"] = data["header"]["timestamp"]
                data["payload"]["togglex"] = []
                data["payload"]["togglex"].append(item)

        else:
                return None

        return(json.dumps(data))