Skip to content

Commit

Permalink
Merge pull request #10 from RobertD502/fresh_element_support
Browse files Browse the repository at this point in the history
Add Fresh element support
  • Loading branch information
RobertD502 authored Jul 6, 2023
2 parents 8a90b86 + 876556d commit d994bba
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This is PetKit's undocumented API. With that said, future changes made by PetKit
## **Currently Supported Devices**:

`Feeders`
- [Fresh Element](https://petkit.us/products/petkit-element-wi-fi-enabled-smart-pet-food-container-feeder)
- [D3 (Fresh Element Infinity)](https://www.amazon.com/PETKIT-Automatic-Stainless-Programmable-Dispenser/dp/B09JFK8BCQ)
- [D4 (Fresh Element Solo)](https://www.amazon.com/PETKIT-Automatic-Dispenser-Compatible-Freeze-Dried/dp/B09158J9PF/)
- [D4s (Fresh Element Gemini)](https://www.amazon.com/PETKIT-Automatic-Combination-Dispenser-Stainless/dp/B0BF56RTQH)
Expand Down
3 changes: 2 additions & 1 deletion petkitaio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
BLE_HEADER,
BLUETOOTH_ERRORS,
CLIENT_DICT,
FeederCommand,
FEEDER_LIST,
FeederSetting,
LB_CMD_TO_KEY,
Expand Down Expand Up @@ -41,7 +42,7 @@
from .model import (Feeder, LitterBox, Pet, PetKitData, Purifier, W5Fountain, )
from .str_enum import StrEnum

__all__ = ['AuthError', 'AUTH_ERROR_CODES', 'BLE_HEADER', 'BluetoothError', 'BLUETOOTH_ERRORS', 'CLIENT_DICT', 'Feeder', 'Endpoint',
__all__ = ['AuthError', 'AUTH_ERROR_CODES', 'BLE_HEADER', 'BluetoothError', 'BLUETOOTH_ERRORS', 'CLIENT_DICT', 'Feeder', 'Endpoint', 'FeederCommand',
'FEEDER_LIST', 'FeederSetting', 'Header', 'LB_CMD_TO_KEY', 'LB_CMD_TO_TYPE', 'LB_CMD_TO_VALUE', 'LitterBox', 'LitterBoxCommand', 'LitterBoxCommandKey',
'LitterBoxCommandType', 'LitterBoxSetting', 'LITTER_LIST', 'LOGGER', 'Pet', 'PetKitClient', 'PetKitData', 'PetKitError', 'PetSetting', 'Purifier',
'PurifierCommand', 'PurifierCommandKey', 'PurifierCommandType', 'PUR_CMD_TO_KEY', 'PUR_CMD_TO_TYPE', 'PUR_CMD_TO_VALUE', 'PURIFIER_LIST', 'PurifierSetting', 'Region',
Expand Down
14 changes: 13 additions & 1 deletion petkitaio/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class Endpoint(StrEnum):
DEVICE_RECORD = '/getDeviceRecord'
DEVICE_ROSTER = '/discovery/device_roster'
FEEDER_DESICCANT_RESET = '/desiccantReset'
FRESH_ELEMENT_CALIBRATION = '/food_reset'
FRESH_ELEMENT_CANCEL_FEED = '/cancel_realtime_feed'
FRESH_ELEMENT_DESICCANT_RESET = '/feeder/desiccant_reset'
FRESH_ELEMENT_MANUAL_FEED = '/feeder/save_dailyfeed'
FRESH_ELEMENT_SETTING = '/feeder/update'
LOGIN = '/user/login'
MANUAL_FEED = '/saveDailyFeed'
MAX_ODOR_RESET = '/deodorantReset'
Expand All @@ -44,6 +49,8 @@ class FeederSetting(StrEnum):
DISPENSE_TONE = 'feedSound'
DO_NOT_DISTURB = 'disturbMode'
FEED_TONE = 'feedTone'
FRESH_ELEMENT_CHILD_LOCK = 'settings.manualLock'
FRESH_ELEMENT_INDICATOR_LIGHT = 'settings.lightMode'
INDICATOR_LIGHT = 'lightMode'
MIN_EAT_DURATION = 'shortest'
MINI_CHILD_LOCK = 'settings.manualLock'
Expand Down Expand Up @@ -71,6 +78,11 @@ class Header(StrEnum):
LOCALE = 'en_US'


class FeederCommand(StrEnum):

START_CALIBRATION = 'Start calibration'
STOP_CALIBRATION = 'Stop calibration'

class LitterBoxCommand(StrEnum):

LIGHT_ON = 'light_on'
Expand Down Expand Up @@ -252,7 +264,7 @@ class W5Command(StrEnum):
}

BLE_HEADER = [-6, -4, -3]
FEEDER_LIST = ['D3', 'D4', 'D4s', 'FeederMini']
FEEDER_LIST = ['D3', 'D4', 'D4s', 'Feeder', 'FeederMini']
LITTER_LIST = ['T3', 'T4']
PURIFIER_LIST = ['K2']
WATER_FOUNTAIN_LIST = ['W5']
Expand Down
35 changes: 34 additions & 1 deletion petkitaio/petkit_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
BLUETOOTH_ERRORS,
CLIENT_DICT,
Endpoint,
FeederCommand,
FEEDER_LIST,
FeederSetting,
Header,
Expand Down Expand Up @@ -769,6 +770,8 @@ async def manual_feeding(self, feeder: Feeder, amount: int) -> None:

if feeder.type == 'feedermini':
url = f'{self.base_url}{Endpoint.MINI_MANUAL_FEED}'
elif feeder.type == 'feeder':
url = f'{self.base_url}{Endpoint.FRESH_ELEMENT_MANUAL_FEED}'
else:
url = f'{self.base_url}/{feeder.type}{Endpoint.MANUAL_FEED}'
header = await self.create_header()
Expand Down Expand Up @@ -809,6 +812,9 @@ async def update_feeder_settings(self, feeder: Feeder, setting: FeederSetting, v

if feeder.type == 'feedermini':
url = f'{self.base_url}{Endpoint.MINI_SETTING}'
# Fresh Element Feeder
elif feeder.type == 'feeder':
url = f'{self.base_url}{Endpoint.FRESH_ELEMENT_SETTING}'
# D3 and D4 Feeders
else:
url = f'{self.base_url}/{feeder.type}{Endpoint.UPDATE_SETTING}'
Expand Down Expand Up @@ -867,7 +873,11 @@ async def update_purifier_settings(self, purifier: Purifier, setting: PurifierSe
async def cancel_manual_feed(self, feeder: Feeder) -> None:
"""Cancel a manual feed that is currently in progress. Not available for mini feeders"""

url = f'{self.base_url}/{feeder.type}{Endpoint.CANCEL_FEED}'
# Fresh Element feeder
if feeder.type == 'feeder':
url = f'{self.base_url}/{feeder.type}{Endpoint.FRESH_ELEMENT_CANCEL_FEED}'
else:
url = f'{self.base_url}/{feeder.type}{Endpoint.CANCEL_FEED}'
header = await self.create_header()
if feeder.type == 'd4s':
if feeder.last_manual_feed_id is None:
Expand All @@ -893,6 +903,9 @@ async def reset_feeder_desiccant(self, feeder: Feeder) -> None:

if feeder.type == 'feedermini':
url = f'{self.base_url}{Endpoint.MINI_DESICCANT_RESET}'
# Fresh Element Feeder
elif feeder.type == 'feeder':
url = f'{self.base_url}{Endpoint.FRESH_ELEMENT_DESICCANT_RESET}'
else:
url = f'{self.base_url}/{feeder.type}{Endpoint.FEEDER_DESICCANT_RESET}'
header = await self.create_header()
Expand Down Expand Up @@ -930,3 +943,23 @@ async def food_replenished(self, feeder: Feeder) -> None:
'noRemind': 3
}
await self._post(url, header, data)

async def fresh_element_calibration(self, feeder: Feeder, command: FeederCommand) -> None:
"""Start/stop calibration command to Fresh Element feeder.
This needs to be done whenever batteries are added or removed.
"""

if feeder.type != 'feeder':
raise PetKitError('Calibration is only used for Fresh Element feeders.')
else:
url = f'{self.base_url}/{feeder.type}{Endpoint.FRESH_ELEMENT_CALIBRATION}'
header = await self.create_header()
if command == FeederCommand.START_CALIBRATION:
value = 1
else:
value = 0
data = {
'action': value,
'deviceId': feeder.id
}
await self._post(url, header, data)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="petkitaio",
version="0.1.5",
version="0.1.6",
author="Robert Drinovac",
author_email="unlisted@gmail.com",
description="Asynchronous Python library for PetKit's API",
Expand Down

0 comments on commit d994bba

Please sign in to comment.