Skip to content
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

Suggestion: lock in cat ("indoor cat")/ free cat ("outdoor cat") #16

Open
agreulich opened this issue Jul 14, 2020 · 2 comments
Open

Suggestion: lock in cat ("indoor cat")/ free cat ("outdoor cat") #16

agreulich opened this issue Jul 14, 2020 · 2 comments

Comments

@agreulich
Copy link

agreulich commented Jul 14, 2020

great project - is it still maintained (2 years old)?

My suggestion is to add code that allows to modify a cat to an "indoor cat", which locks them in, and back to an "outdoor cat", e.g. to keep one cat inside while others can leave (because of being sick, pending vet visit, etc). The app and web frontend allows to do this, but unfortunately without a timer; it is not possible in the app to say "modify cat x to indoor cat at 3am", so the cat can still enter and leave freely until then, but after this, needs to stay inside (because, e.g., a vet visit in the morning), while other cats - I have 3 - can enter and leave freely. Moreover, the feature is hidden deep inside the app and I originally had trouble finding it.

Actually I've already written code that works; feel free to add it in a way that you seem fit, if you like. I did not (yet) figure out how to read the status, because my priority was setting it. Of course you might decide against it, because this involves writing data to the server instead of only readin data.

The main modification is to add a method in class SurePetFlapMixin (line 684 of __init__.py) like this:

    def set_pet_profile( self, pet_id = None, name = None, profile = None, household_id = None ):
        """
        Set lock mode of a pet (3 is locked, 2 is free)
        """
        household_id = household_id or self.default_household
        if profile is None or type(profile) != int:
            raise ValueError('Please define a profile int value')
        if pet_id is None and name is None:
            raise ValueError('Please define pet_id or name')
        if pet_id is None:
            pet_id = self.get_pet_id_by_name(name)
        pet_id = int(pet_id)
        try:
            tag_id = self.household['pets'][pet_id]['tag_id']
            pet_name = self.household['pets'][pet_id]['name']
        except KeyError as e:
            raise SPAPIUnknownPet(str(e))
        device_id = self.household['default_flap']

        headers = self._create_header()
        data = {"profile": profile}
        url = '%s/%s/tag/%s' % (_URL_DEV, device_id, tag_id)
        response = self.s.put(url, headers=headers, json=data)
        if response.status_code == 401:
            self.update_authtoken(force=True)
            if 'headers' in kwargs and 'Authorization' in kwargs['headers']:
                kwargs['headers']['Authorization'] = 'Bearer ' + self.cache['AuthToken']
                response = self.s.post(_URL_AUTH, headers=headers, json=data)
            else:
                raise SPAPIException('Auth required but not present in header')

        response_data = response.json()
        return 'data' in response_data and 'profile' in response_data['data'] and \
               response_data['data']['profile'] == profile

And adding to sp_cli.py

@cmd
def cmd_pet_lock( sp: sure_petcare.SurePetFlapMixin, args ):
    """
    For each pet in household, lock it inside
    """
    try:
        name = args.cmd[1]
    except IndexError:
        exit('need pet name (enclose in quotes if necessary)')

    if sp.set_pet_profile( name = name, profile=3 ):
        print("ok")
    else:
        print("fail")

@cmd
def cmd_pet_free( sp: sure_petcare.SurePetFlapMixin, args ):
    """
    For each pet in household, lock it inside
    """
    try:
        name = args.cmd[1]
    except IndexError:
        exit('need pet name (enclose in quotes if necessary)')

    if sp.set_pet_profile( name = name, profile=2 ):
        print("ok")
    else:
        print("fail")

You might want to rename things and/or change code style. It basically PUTs to an URL .../device/<flap-id>/tag/<pet-tag-id> with a json {"profile": 3} to lock in, and {"profile": 2} to free (I don't know if other profile values might have different effects).

PS: It is possible to read the status via URL _URL_DEV and parameters to

        params = (
            ('with[]', 'tags'),
        )

The last record in datalist then has a tagslist (of all pets), each with id== pet tag-id and profile set to 2 or 3 (plus update timestamp in updated_at)

@agreulich
Copy link
Author

agreulich commented Jul 14, 2020

I added reading mode to get_current_status via get_pet_location and modifying update_pet_status plus some constants. I attach __init__.pyand sp_cli.py below and tried to keep your coding stlye, thought it might have failed at places :-)

Example:

$ python sp_cli.py ls_pets
cat1 (111111) is Free to leave (outdoor pet) and currently Outside
cat2 (222222) is Free to leave (outdoor pet) and currently Outside
cat3 (333333) is Free to leave (outdoor pet) and currently Outside

$ python sp_cli.py pet_lock cat3
ok

$ python sp_cli.py --update
$ python sp_cli.py ls_pets
cat1 (111111) is Free to leave (outdoor pet) and currently Outside
cat2 (222222) is Free to leave (outdoor pet) and currently Outside
cat3 (333333) is Locked in (indoor pet) and currently Outside

$ python sp_cli.py pet_free cat3
ok

$ python sp_cli.py --update
$ python sp_cli.py ls_pets
cat1 (111111) is Free to leave (outdoor pet) and currently Outside
cat2 (222222) is Free to leave (outdoor pet) and currently Outside
cat3 (333333) is Free to leave (outdoor pet) and currently Outside

I created a pull request for this.

@rcastberg
Copy link
Owner

Hi,

I havn't done much with this project since family and job changes happened, i will try to look into this soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants