Git Product home page Git Product logo

Comments (3)

bytespider avatar bytespider commented on June 23, 2024 1

Does this work for you? #57 (comment)

from meross.

boar24 avatar boar24 commented on June 23, 2024

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

  • SET instead of PUSH
  • another value in the "from" field

The plug only reacts on the message

  • many minutes after the messageId had been generated in the first place (I guess i.e. after the plug will have forgotten that the messageId had been used recently, clearly it can only have limited memory) and
  • after unplugging and replugging the plug (apparently, i.e. erasing its memory). :-)

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.

from meross.

lechercheur123 avatar lechercheur123 commented on June 23, 2024

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))

from meross.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.