SecKatie / ha-wyzeapi

Home Assistant Integration for Wyze devices.
733 stars 112 forks source link

[Feature Request] Wyze Scale #93

Closed ikrowni closed 10 months ago

ikrowni commented 3 years ago

Possible to add the wyze scale to this component?

SecKatie commented 3 years ago

I do not have one so I cannot capture the data required to integrate it. I would happily accept pull requests!!

ikrowni commented 3 years ago

Okay I just ordered one last night. If you or someone else wants to help me figure out what I need to get for you to add it I'm on board to help.

ikrowni commented 3 years ago

Just received the scale. Not sure what I need to provide for you and how I go about getting it.

SecKatie commented 3 years ago

You will need to use an HTTPS interception application and use it to capture the API requests between the phone app and the server while you are manipulating the scale and utilizing all of its functions. Once you have done that you can send that data to me at josh.mulliken at hey dot com with each request that corresponds to each action labeled. I can use this to understand how the app interacts with the API and can replicate that on the home assistant integration.

Thanks!

ikrowni commented 3 years ago

Thanks I will get to work on that asap. Are there any certain programs you would recommend for capturing the requests?

SecKatie commented 3 years ago

MITMProxy works well or Burp suite

flostingapplesauce commented 3 years ago

Thanks I will get to work on that asap.

If you are not comfortable with the Burp Suite, you might consider attacking this from a different angle. Search out the OpenScale repo, and read the little Wiki that explains how to reverse engineer a Bluetooth scale. This may allow more direct use of the scale, without a need for the cloud to be involved. You would be able to remove the Wyze app, and use the (vastly superior) OpenScale app instead.

Both of these options involve sniffing data, and both might be non-trivial, but there is more than one way to skin this particular cat :)

Another option is to sync the Wyze app with Google Fit, then use one of the Google Fit integrations to pull the data into HA. You could even install the Wyze app and Google Fit on an old phone or Android TV box to offload the app from your phone, if you wanted to.

shauntarves commented 3 years ago

@flostingapplesauce @ikrowni

I have been working with @JoshuaMulliken to reverse-engineer a generic wyze API. I've finally cracked what they're doing in their newer requests and how they hit their own API. We now have full support for the bulbs, plugs/switches, and the new vacuum. I would love to add support for more devices, but I need someone who has these devices to be willing to work with me directly and share some access/data to I can make the code work. If you're interested in helping out, please email shaun <at> tarves <dot> net

lordlala commented 3 years ago

Just in case anyone is still actively working on this, I have actually started writing my own python script to manage my Wyze scale. It pulls the entire scale information down, including all history of all users, then it parses. Currently I only parse my own data and just dump it all into an HA attribute using AppDaemon. Would be glad to share what I've got if it helps this integration.

tggman commented 3 years ago

Just in case anyone is still actively working on this, I have actually started writing my own python script to manage my Wyze scale. It pulls the entire scale information down, including all history of all users, then it parses. Currently I only parse my own data and just dump it all into an HA attribute using AppDaemon. Would be glad to share what I've got if it helps this integration.

I would definitely be interested ... can you share the python code?

terrycarlin commented 3 years ago

I am interested in the code also.

On Aug 12, 2021, at 8:17 PM, tggman @.***> wrote:

Just in case anyone is still actively working on this, I have actually started writing my own python script to manage my Wyze scale. It pulls the entire scale information down, including all history of all users, then it parses. Currently I only parse my own data and just dump it all into an HA attribute using AppDaemon. Would be glad to share what I've got if it helps this integration.

I would definitely be interested ... can you share the python code?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-898157986, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGVNVBDNKY52HLAGOY5EO3T4SFC5ANCNFSM4TESYVUQ. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email.

lordlala commented 3 years ago

Hey all, apologies for the delay. Been out of town. As soon as I get back I'll sanitize and upload it and share it with you all.

It's nothing special but it's a start.

-- Jason Adams

On Fri, Aug 13, 2021 at 2:36 PM Terry Carlin @.***> wrote:

I am interested in the code also.

On Aug 12, 2021, at 8:17 PM, tggman @.***> wrote:

Just in case anyone is still actively working on this, I have actually started writing my own python script to manage my Wyze scale. It pulls the entire scale information down, including all history of all users, then it parses. Currently I only parse my own data and just dump it all into an HA attribute using AppDaemon. Would be glad to share what I've got if it helps this integration.

I would definitely be interested ... can you share the python code?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub < https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-898157986>, or unsubscribe < https://github.com/notifications/unsubscribe-auth/AAGVNVBDNKY52HLAGOY5EO3T4SFC5ANCNFSM4TESYVUQ . Triage notifications on the go with GitHub Mobile for iOS < https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android < https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-898648884, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADLMOLBSAGAAP6ZUZ5ZLHZTT4VQZLANCNFSM4TESYVUQ .

JoeSchubert commented 2 years ago

@lordlala Any luck getting this to where it can be shared?

JoeSchubert commented 2 years ago

@lordlala any chance you've sanitized your script for this?

Or can provide the endpoints/sample data/responses?

lordlala commented 2 years ago

So, the issue I face is that I am still trying to adapt it away from wyze-api which is what I wrote it in. If you want to take a look at what I have as it stands, I can certainly provide that.

Apologies - time has been very limited lately.

-- Jason Adams

On Wed, Nov 10, 2021 at 2:21 PM Joe Schubert @.***> wrote:

@lordlala https://github.com/lordlala any chance you've sanitized your script for this?

Or can provide the endpoints/sample data/responses?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-965664697, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADLMOLGZE4IXYJZQ44HGZFDULLA4LANCNFSM4TESYVUQ .

JoeSchubert commented 2 years ago

Wouldn't really do my much good if it's using a different library without any context/reference of the json coming from the server.

terrycarlin commented 2 years ago

I would like to see your code asis as I have used the same API. I am very interested in seeing how you got the history. I have only figured out to get recent readings.

Thanks

On Nov 10, 2021, at 12:47 PM, Joe Schubert @. @.>> wrote:

Wouldn't really do my much good if it's using a different library without any context/reference of the json coming from the server.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-965686557, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGVNVE3MDVIDWJNZ6FFSBLULLD6XANCNFSM4TESYVUQ. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

lordlala commented 2 years ago

Check this out, I'm not ashamed of it: lol

{'device_members': [{'create_time': 1607293409353, 'device_id': 'JA.SC.2CAA8E436CAB', 'family_member_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'id': 358693, 'share_user_id': None, 'update_time': 1607293409828, 'user_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'user_type': 1}], 'goal_weight': {'created': datetime.datetime(2021, 9, 16, 6, 16, 11, 749000), 'current_weight': 184.88, 'family_member_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'goal_weight': 180.01, 'id': 162828, 'updated': datetime.datetime(2021, 9, 16, 6, 16, 11, 749000), 'user_id': 'c0224228e4864fccf69ee81fcd47e7ae'}, 'latest_records': [{'age': 38, 'bmi': 25.317902, 'bmr': 1626.2402, 'body_fat': 29.1, 'body_type': 6, 'body_vfr': 8, 'body_water': 51.8, 'bone_mineral': 3.6, 'device_id': 'JA.SC.2CAA8E436CAB', 'family_member_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'height': 180.0, 'id': '435714181712662323', 'impedance': [654, 582, 554, 525], 'mac': '2CAA8E436CAB', 'measure_ts': 1636809429005, 'metabolic_age': 36, 'muscle': 54.5, 'protein': 14.6, 'timezone': 'America/New_York', 'user_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'weight': 180.85}, {'age': 38, 'bmi': 25.88889, 'bmr': 1638.2656, 'body_fat': 30.0, 'body_type': 6, 'body_vfr': 8, 'body_water': 51.3, 'bone_mineral': 3.6, 'device_id': 'JA.SC.2CAA8E436CAB', 'family_member_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'height': 180.0, 'id': '7723686143148050945', 'impedance': [633, 565, 537, 508], 'mac': '2CAA8E436CAB', 'measure_ts': 1636207817004, 'metabolic_age': 36, 'muscle': 55.1, 'protein': 14.4, 'timezone': 'America/New_York', 'user_id': 'c0224228e4864fccf69ee81fcd47e7ae', 'weight': 184.92}], 'mac': '2CAA8E436CAB', 'nickname': 'Wyze Scale', 'push_switch': 1, 'type': 'WyzeScale', 'unit': 'lb'}

That is the data.

Here is the code:

import sys, logging, os, yaml from yaml.loader import FullLoader

Load the local source directly

sys.path.insert(1, "./wyze-sdk") import hassapi as hass from wyze_sdk import Client from contextlib import suppress import pprint

Simple little script to grab all entities and print them out in the log

class wyze_api(hass.Hass): update = None scale = {} records = {} theentity = None muscle = None protein = None age = None fat = None type = None bmi = None bmr = None water = None height = None bone_mineral = None persons = { "c0224228e4864fccf69ee81fcd47e7ae": "Jason" } person = None

def initialize(self):
    self.log('Wyze-API App has been intialized.')

self.set_state('input_boolean.wyze_update',state='off')

    self.listen_state(self.get_entities, "input_boolean.wyze_update",

immediate='true') self.log('Script is now listening for triggers.') self.email = self.args["wyzeemail"] self.password = self.args["wyzepass"] self.get_entities(self, None, None, None, None)

def Convert(self, lst):
    self.res_dct = {lst[i]: lst[i + 1] for i in range(0, len(lst), 2)}
    return self.res_dct

def get_entities(self, entity, attribute, old, new, kwargs):
    try:
        if self.get_state('input_boolean.wyze_update') == 'on':
            self.log('Update was triggered via automation.')
        else:
            self.log('Update was triggered from the app starting.')
        #logging.basicConfig(level=logging.DEBUG)
        # Verify it works
        self.client = Client(email=self.email, password=self.password)
        #api_response = client.api_test()
        response = self.client.devices_list()
        #Using 0 for the record gets us the latest one
        self.scale = self.client.scales.info

(device_mac='JA.SC.2CAA8E436CAB').to_dict() self.log(self.scale) self.records = self.scale['latest_records']

self.log(self.Convert(self.records[0]))

        #self.log(self.records[0])
        self.scaleitem = yaml.dump(self.records)
        self.scaledict = yaml.load(self.scaleitem, Loader=FullLoader)
        #Create the entity first, so we dont keep overwriting it
        self.person =

'sensor.wyzescale{0}'.format(self.persons[self.records[0]['family_member_id']]) self.person = self.person.lower()

self.log(self.person)

        #self.set_state(self.person,state=self.records[0]['id'])
        #self.theentity =

'sensor.wyzescale{0}'.format(self.persons[self.records[0]['family_member_id']])

self.set_state(self.theentity, state=weight,

attributes={"bmi": 10, "nested_data": {"more": "data", "to": "add"}}) self.log('Setting our sensor states...')

self.log('Note: All errors when setting the states, have been

suppressed. For some reason, not all the fields in the records always exist.')

The following with supress and set state shit stopped so i put

my original code back in

with suppress(Exception):

        #Now, we know there will be times that not all the fields are

returned due to Wyze being a shithead

It will crash the script when that happens, so we need a way

to handle it a = {} for item in self.records[0]: try:

self.log(self.records[0][item])

                a[item] = self.records[0][item]
            except:
                pass
            #assert

self.set_state(f"sensor.wyze_scalejason{item}",attributes = {

self.log(a.items())

        b = yaml.dump(a)
        c = yaml.load(b, Loader=FullLoader)
        #self.log(c)
        #self.set_state(self.person,state=a['weight'],attributes=c)
        ha_state = self.get_state(self.person, attribute = "all")

first get what HA knows

        #self.log(ha_state)
        if ha_state != None:                                      #

check if HA knows the entity and knows a state attributes = ha_state["attributes"] #fill the attributes dict with info from HA state = ha_state["state"] #fill the state var with info from HA

self.log(f"ha_state is now: {state}")

        else:
            attributes = {}
            self.log("*****Setting state to unavailable*****")
                        #HA has no info, so create an empty dict
            state = "unavailable"                                 #HA

has no info so set state to unavailable

self.log(f"record length: {len(self.records)}")

        #self.log(f"records: {self.records}")
        if len(self.records) > 0:

check if there is any info in self.records

            for item in self.records[0]:
                #self.log(item)                         #loop through

the items if item == 'weight':

check if item is weight

                    state = self.records[0][item]                 #we

found weight, so put the value in state

self.log(f"The weight part:

{self.records[0][item]}") else: attributes[item] = self.records[0][item] #it isnt weight, so its an attribute

self.log(f"The else part. {attributes[item]}")

                    #self.log(f"The else part STATE: {state}")
                self.set_state(self.person, state = state, attributes =

attributes) #set state and attributes

self.set_state("input_boolean.wyze_update", state = 'off')

Turn our switch back off

        self.call_service("state/set",

entity_id="input_boolean.wyze_update", state="off", attributes={"friendly_name" : "Wyze Update Toggle"}, namespace="default") self.log("Current weight:{0}".format(state)) self.log('Update of sensors completed.') except Exception as e: self.log(f"EXCEPTION: {e}")

Best I can do at the moment - we've had a loss in the family, so bare with me.

-- Jason Adams

On Wed, Nov 10, 2021 at 7:06 PM Terry Carlin @.***> wrote:

I would like to see your code asis as I have used the same API. I am very interested in seeing how you got the history. I have only figured out to get recent readings.

Thanks

On Nov 10, 2021, at 12:47 PM, Joe Schubert @. @.>> wrote:

Wouldn't really do my much good if it's using a different library without any context/reference of the json coming from the server.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub < https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-965686557>, or unsubscribe < https://github.com/notifications/unsubscribe-auth/AAGVNVE3MDVIDWJNZ6FFSBLULLD6XANCNFSM4TESYVUQ . Triage notifications on the go with GitHub Mobile for iOS < https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android < https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-965859782, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADLMOLHT7ZNOUEXC7PATLGTULMCH5ANCNFSM4TESYVUQ .

JoeSchubert commented 2 years ago

Sorry to hear about the loss in the family. Hope everything is going as well as it can. I definitely wouldn't stress the stuff here.

I'm posting this reply for whether you get back to it

If that entire response json comes from the server from 1 call, it seems like it would be pretty easy (well, time permitting anyway) to make that work in wyzeapy to pull into ha. I'd need to know what the post data to get it looks like though.

lordlala commented 2 years ago

How could I better facilitate this? Want to just use my wyze account and see what you think? I don't care, to be honest, I trust you two given your history with this project.

-- Jason Adams

On Wed, Nov 17, 2021 at 10:08 PM Joe Schubert @.***> wrote:

Sorry to hear about the loss in the family. Hope everything is going as well as it can. I definitely wouldn't stress the stuff here.

I'm posting this reply for whether you get back to it

If that entire response json comes from the server from 1 call, it seems like it would be pretty easy (well, time permitting anyway) to make that work in wyzeapy to pull into ha. I'd need to know what the post data to get it looks like though.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JoshuaMulliken/ha-wyzeapi/issues/93#issuecomment-972474683, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADLMOLDXNQ24UJMAZ655OX3UMRUZ5ANCNFSM4TESYVUQ .

danielzrob commented 2 years ago

If you guys are still looking for a person with the vacuum hit me up.

SecKatie commented 2 years ago

@danielzrob always looking for new contributors! You can join us on #wyzeapi on Libera.Chat!

tismofied commented 2 years ago

Any success on wyze scale support in this integration?

Geczy commented 2 years ago

any ujpdate?

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

MMachor commented 1 year ago

Would this be of any help... https://wyze-sdk.readthedocs.io/en/latest/wyze_sdk.api.html#scales

github-actions[bot] commented 11 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

Geczy commented 11 months ago

bump

github-actions[bot] commented 10 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] commented 10 months ago

This issue was closed because it has been stalled for 5 days with no activity.