Skip to content

Commit

Permalink
Merge pull request #124 from sander1988/master
Browse files Browse the repository at this point in the history
Fix/workaround for #204
  • Loading branch information
Rosi2143 authored May 18, 2024
2 parents 0f4e867 + 199f6d2 commit c817b7e
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 33 deletions.
62 changes: 41 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ For use in Home Assistant: https://github.com/jm-73/Indego

## Basic information needed

The library requires python 3.7 or above.
The library requires python 3.8 or above.

Required information | Description
-----------------------|------------
Expand Down Expand Up @@ -100,7 +100,7 @@ Calendar(cal=3, days=[CalendarDay(day=0, day_name='monday', slots=[CalendarSlot(
```

### indego.update_config()
Updates indego.config with settings for region, border cut, pin lock, id for the wire, bump and alarm mode. This call doesnt work on some Indegos, this function gives an error on Indego 1000, while it works on newer models (e.g., Indego S+ 400).
Updates indego.config with settings for region, border cut, pin lock, id for the wire, bump and alarm mode. This call doesn't work on some Indegos, this function gives an error on Indego 1000, while it works on newer models (e.g., Indego S+ 400).

```python
Config(region=0, language=1, border_cut=0, is_pin_set=True, wire_id=4, bump_sensitivity=0, alarm_mode=True)
Expand Down Expand Up @@ -174,7 +174,7 @@ Security(enabled=True, autolock=False)
```

### indego.update_setup()
Updates the indego.setup with information if the Indego is set up, has pincode and wome other unknown values.
Updates the indego.setup with information if the Indego is set up, has pincode and some other unknown values.

```python
Setup(hasOwner=True, hasPin=True, hasMap=True, hasAutoCal=False, hasIntegrityCheckPassed=True)
Expand All @@ -197,7 +197,7 @@ State(state=64513, map_update_available=True, mowed=78, mowmode=0, xPos=162, yPo
### indego.update_state(force=False, longpoll=True, longpoll_timeout=120)
Updates the indego.state with state of mower, % lawn mowed, position, runtime, map coordinates.

When longpoll is set to True, the indego.state must contain a value. It should contain the current state of the mower (you must run a "regular" update.state first). You send the current value to the API, and the API answers back when the state chenges.
When longpoll is set to True, the indego.state must contain a value. It should contain the current state of the mower (you must run a "regular" update.state first). You send the current value to the API, and the API answers back when the state changes.

This function can be used instead of polling the status every couple of seconds: place one longpoll status request with a timeout of max. 300 seconds and the function will provide its return value when the status has been updated. As soon as an answer is received, the next longpoll status request can be placed. This should save traffic on both ends.

Expand Down Expand Up @@ -237,19 +237,19 @@ Set all alerts to read, the function loops through the alert_id's from indego.al
### indego.put_command(command)
Send commands.

Command |Description
Command |Description
------------|--------------------
put_command('mow') |Start mowing
put_command('pause') |Pause mower
put_command('mow') |Start mowing
put_command('pause') |Pause mower
put_command('returnToDock') |Return mower to dock

### indego.put_mow_mode(command)
Send command. Accepted commands:

Command |Description
Command |Description
------------|--------------------
put_mow_mode('true') |Smart Mow enabled
put_mow_mode('false') |Smart Mow disabled
put_mow_mode('true') |Smart Mow enabled
put_mow_mode('false') |Smart Mow disabled


## Not implemented yet
Expand Down Expand Up @@ -311,7 +311,7 @@ Response:


## Attributes for reading data from locally cached API data
All functions that doesnt contain "update" first in name is collecting data from locally stored variables in the function. No API calls to Bosch or mower.
All functions that doesn't contain "update" first in name is collecting data from locally stored variables in the function. No API calls to Bosch or mower.

attributes | Description
-------------------------|-----------------------------
Expand All @@ -324,7 +324,7 @@ AlmName | Show name.
BareToolNumber | Show the model number.
Battery | Show battery information.
BatteryAmbientTemp | Show the ambient temp of the battery.
BatteryCycles | Dont know what this value is?
BatteryCycles | Don't know what this value is?
BatteryDischarge | Show the current drawn in Ah.
BatteryPercent | Show the raw value for percentage left. For Gen 1 this seems to be the battery voltage. For Gen 2 it seems to be the actual percentage left in the battery.
BatteryPercentAdjusted | Show the adjusted value for percentage left. Calculated for Gen 1, and the actual percentage value for Gen 2.
Expand All @@ -333,13 +333,13 @@ BatteryVoltage | Show voltage for the battery. For Gen 1 mowers this value seems
ConvertBoschDateTime | Convert Bosch abbreviation for time to std 24h time
Country | Show country for the account.
Displayname | Show name for the account.
Email | Show email adress for the account.
Email | Show email address for the account.
FirmwareAvailable | Show if there are any firmware updates available.
FriendlyAlertErrorCode | Show user friendly alert error code description to be shown in HA GUI.
Garden | Dont know what this is?
HmiKeysn | Dont know what this is?
Garden | Don't know what this is?
HmiKeysn | Don't know what this is?
Language | Show language for the account.
MapSvgCacheTs | Dont know what this is...
MapSvgCacheTs | Don't know what this is...
MapUpdateAvailable | Show if there is an update of the map image.
ModelDescription | Show user friendly model name.
ModelVoltage | Show the predefined voltage limits in order to calculate battery percentage.
Expand All @@ -351,11 +351,11 @@ MowerState | Show current state
MowerStateDescription | Show simple description of current state. States available are Docked, Mowing, Stuck, Diagnostics mode, End of life, Software update.
MowerStateDescriptionDetailed | Show description in detail of current state.
MowingModeDescription | Show the user friendly mow mode description.
NeedsService | Show needs service flag. Dont know when it is used.
NeedsService | Show needs service flag. Don't know when it is used.
NextMow | Show next planned mow session.
OptIn | Dont know what this are for?
OptInApp | Dont know what this are for?
Runtime | Show session and total rutime and charge time in minutes.
OptIn | Don't know what this are for?
OptInApp | Don't know what this are for?
Runtime | Show session and total runtime and charge time in minutes.
RuntimeSession | show session runtime and charge time in minutes
RuntimeTotal | Show total runtime and charge time in hours
Serial | Show serial number
Expand All @@ -369,7 +369,7 @@ YPos | Show y-position of mower.

### Not properly implemented yet

update_predicitive_calendar()
update_predictive_calendar()
Get the calender for predicted mow sessions

update_user_adjustment()
Expand Down Expand Up @@ -419,3 +419,23 @@ put
delete
/alerts/<alertid>
```
# Contributing
The project development is done in a poetry virtual environment.

## setup your environment
To start development please install [poetry](https://python-poetry.org/docs/).

* Install all dependency by running `poetry install`.
* activate the virtual environment by running `poetry shell`
* Run `python test_new.py` to test your setup.

## setup your personal info

Open [config.json](./config.json) and type in the information for your `indego`.

```javascript
{
"token": "mytoken",
"serial": "myserial"
}
```
14 changes: 8 additions & 6 deletions pyIndego/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Constants for pyIndego."""
from enum import Enum
import random
import string
from pyIndego.version import __version__


class Methods(Enum):
"""Enum with HTTP methods."""
Expand All @@ -20,12 +20,14 @@ class Methods(Enum):
CONTENT_TYPE = "Content-Type"
COMMANDS = ("mow", "pause", "returnToDock")

DEFAULT_HEADER = {
DEFAULT_HEADERS = {
CONTENT_TYPE: CONTENT_TYPE_JSON,
# We need to change the user-agent!
# The Microsoft Azure proxy seems to block all requests (HTTP 403) for the default 'python-requests' user-agent.
# We also need to use a random agent for each client: https://github.com/jm-73/pyIndego/issues/119
"User-Agent": ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
# The Microsoft Azure proxy WAF seems to block all requests (HTTP 403) for the default 'python-requests' user-agent.
# See issues:
# - https://github.com/jm-73/pyIndego/issues/119
# - https://github.com/jm-73/Indego/issues/204
'User-Agent': "HomeAssistant/Indego (%s)" % __version__
}
DEFAULT_LOOKUP_VALUE = "Not in database."

Expand Down
4 changes: 2 additions & 2 deletions pyIndego/indego_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
COMMANDS,
CONTENT_TYPE_JSON,
DEFAULT_CALENDAR,
DEFAULT_HEADER,
DEFAULT_HEADERS,
DEFAULT_URL,
Methods,
)
Expand Down Expand Up @@ -490,7 +490,7 @@ async def _request( # noqa: C901
url = f"{self._api_url}{path}"

if not headers:
headers = DEFAULT_HEADER.copy()
headers = self._default_headers.copy()
headers["Authorization"] = "Bearer %s" % self._token

try:
Expand Down
8 changes: 8 additions & 0 deletions pyIndego/indego_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import requests

from .const import (
DEFAULT_HEADERS,
DEFAULT_CALENDAR,
DEFAULT_LOOKUP_VALUE,
DEFAULT_URL,
Expand Down Expand Up @@ -55,6 +56,7 @@ def __init__(
api_url (str, optional): url for the api, defaults to DEFAULT_URL.
raise_request_exceptions (bool): Should unexpected API request exception be raised or not. Default False to keep things backwards compatible.
"""
self._default_headers = DEFAULT_HEADERS.copy()
self._token = token
self._token_refresh_method = token_refresh_method
self._serial = serial
Expand Down Expand Up @@ -470,6 +472,12 @@ def _update_battery_percentage_adjusted(self):
self.generic_data.model_voltage
)

def set_default_header(self, key: str, value: str):
if value is None or value == "":
return
self._default_headers[key] = value
_LOGGER.debug("Default request headers updated: '%s'", self._default_headers)

def __repr__(self):
"""Create a string representing the mower."""
str1 = (
Expand Down
4 changes: 2 additions & 2 deletions pyIndego/indego_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
CONTENT_TYPE,
CONTENT_TYPE_JSON,
DEFAULT_CALENDAR,
DEFAULT_HEADER,
DEFAULT_HEADERS,
Methods,
)
from .indego_base_client import IndegoBaseClient
Expand Down Expand Up @@ -405,7 +405,7 @@ def _request( # noqa: C901
url = f"{self._api_url}{path}"

if not headers:
headers = DEFAULT_HEADER.copy()
headers = self._default_headers.copy()
headers["Authorization"] = "Bearer %s" % self._token

try:
Expand Down
1 change: 1 addition & 0 deletions pyIndego/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "3.1.3"
13 changes: 11 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
"""Setup for pyIndego."""
import os
from setuptools import find_packages, setup

with open("README.md", "r") as fh:
current_dir = os.path.dirname(os.path.realpath(__file__))

# Little hack to load the version.py file without loading the __init__.py.
# As that would fail (when deps are not yet installed).
__version__ = None
with open(os.path.join(current_dir, "pyIndego", "version.py"), "r") as fh:
exec(fh.read())

with open(os.path.join(current_dir, "README.md"), "r") as fh:
long_description = fh.read()

setup(
name="pyIndego",
version="3.1.1",
version=__version__,
author="jm-73, sander1988",
author_email="[email protected]",
description="API for Bosch Indego mower",
Expand Down

0 comments on commit c817b7e

Please sign in to comment.