diff --git a/README.md b/README.md index 62e3969..d0bdacf 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,20 @@ data: water_level: Medium ``` +### Start plan + +To start a plan called `Cuina`, run the `vacuum.send_command` service with the `start_plan` command, and provide the plan as a parameter. The parameter must be created before from the App. + +``` +service: vacuum.send_command +target: + entity_id: vacuum.conga +data: + command: start_plan + params: + plan: Cuina +``` + ## Developers ### Local testing @@ -71,7 +85,14 @@ If you already have a Conga, I encourage you to test it by executing the `test.p 3. Create a `.env` file with the variables `CONGA_USERNAME`, `CONGA_PASSWORD` and `CONGA_SN` (serial number). The serial number is retrieved by the script. 4. Execute `python test.py`. -There is a Makefile target to start a Docker container with this integration installed as a `custom_component`. Execute `make test-local`. +There is a Makefile target to start a Docker container with this integration installed as a `custom_component`. Execute `make test-local`. This will create a local folder `.config`. To set debugging mode add this to `.config/configuration.yaml` file: + +``` +logger: + default: info + logs: + custom_components.cecotec_conga: debug +``` ## Legal notice This is a personal project and isn't in any way affiliated with, sponsored or endorsed by [CECOTEC](https://www.cecotec.es/). diff --git a/custom_components/cecotec_conga/__init__.py b/custom_components/cecotec_conga/__init__.py index 5c89588..216508c 100644 --- a/custom_components/cecotec_conga/__init__.py +++ b/custom_components/cecotec_conga/__init__.py @@ -28,6 +28,8 @@ def __init__(self, username, password): self._username = username self._password = password self._devices = [] + self._shadow = {} + self._tactics = {} self._api_token = None self._iot_client = None self._iot_token_expiration = None @@ -44,41 +46,37 @@ def list_vacuums(self): _LOGGER.warn(self._devices) return self._devices - def list_plans(self, sn): - self._refresh_api_token() - response = requests.post( - f'{CECOTEC_API_BASE_URL}/api/user/file_list', - json={ - "sn": sn, - "file_type": 2, - "sort": -1, - "page_size": 10, - "last_page_key": None - }, - auth=self._api_token - ) - response.raise_for_status() - try: - pages = response.json()["data"]["page_items"] - plans = [] - plan_names = [] - for page in pages: - if "planName" in page["task_cmd"]["cmd"]: - plans.append(page["task_cmd"]["cmd"]) - plan_names.append(page["task_cmd"]["cmd"]["planName"]) - - self._plans = plans - self._plan_names = plan_names - except: - self._plans = [] - self._plan_names = [] - + def list_plans(self): return self._plan_names - def status(self, sn): + def update_shadows(self, sn): self._refresh_iot_client() - r = self._iot_client.get_thing_shadow(thingName=sn) - return json.load(r['payload']) + shadow = self._iot_client.get_thing_shadow(thingName=sn) + shadow_service = self._iot_client.get_thing_shadow( + thingName=sn, shadowName='service') + + shadow = json.load(shadow['payload'])['state']['reported'] + shadow_service = json.load(shadow_service['payload'])[ + 'state']['reported'] + + self._shadow = shadow + self._tactics = shadow_service['getTimeTactics']['body']['timeTactics'] + + # Fill plans variables + plans = [] + plan_names = [] + for tactic in json.loads(self._tactics)['value']: + if "planName" in tactic: + plans.append(tactic) + plan_names.append(tactic['planName']) + + self._plans = plans + self._plan_names = plan_names + + return self._shadow + + def get_status(self): + return self._shadow def start(self, sn, fan_speed): payload = { @@ -146,6 +144,7 @@ def start_plan(self, sn, plan_name): } } } + _LOGGER.warn(payload) self._send_payload(sn, payload) def home(self, sn): diff --git a/custom_components/cecotec_conga/vacuum.py b/custom_components/cecotec_conga/vacuum.py index b066c97..dcb925e 100644 --- a/custom_components/cecotec_conga/vacuum.py +++ b/custom_components/cecotec_conga/vacuum.py @@ -67,8 +67,6 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) -#modes: ["Off", "Eco", "Normal", "Turbo"] - async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Cecotec Conga sensor from a config entry.""" @@ -231,8 +229,7 @@ def send_command(self, command, params=None, **kwargs): if command == "start_plan": plan = params["plan"] if plan in self._plans: - self._conga_client.start_plan( - self._sn, self._plans.index(plan)) + self._conga_client.start_plan(self._sn, plan) self.schedule_update_ha_state() else: _LOGGER.error( @@ -253,12 +250,12 @@ def send_command(self, command, params=None, **kwargs): def update(self): """Get the next bus information.""" try: - response = self._conga_client.status(self._sn) - self._state_all = response["state"]["reported"] + self._conga_client.update_shadows(self._sn) + self._state_all = self._conga_client.get_status() self._battery = self._state_all["elec"] self._state = self._state_all["mode"] - self._plans = self._conga_client.list_plans(self._sn) + self._plans = self._conga_client.list_plans() except HTTPError: _LOGGER.error( "Unable to fetch data from API" diff --git a/test.py b/test.py index b81acc8..7754990 100644 --- a/test.py +++ b/test.py @@ -13,10 +13,11 @@ print(f"\nGetting status for {conga_sn}") print(conga_client.list_vacuums()) -print(conga_client.status(conga_sn)) +conga_client.update_shadows(conga_sn) +print(conga_client.get_status()) -print(f"\nGetting plans for {conga_sn}") -print(conga_client.list_plans(conga_sn)) +print(f"\nGetting plans for") +print(conga_client.list_plans()) # print(f"\nStarting plan for {conga_sn}") # print(conga_client.start_plan(conga_sn, "Quick"))