Skip to main content

STIHL iMow unofficial Python API wrapper

PyPI version shields.io Docs on GitHub pages CI PyPI download total PyPI pyversions PyPI license

This unofficial Python API was created to provide an interface to interact with the STIHL iMow mower WebAPI. This wrapper is able to receive the current state from the mowers and to send actions.
I wrote this library to implement an integration for the Home Assistant Smart Home System, which you can find here.

iMOW compatibility

STIHL uses different webapps for their iMOW generations. Currently only the iMOW RMI series are supported by this library, because i'm not able to reverse engineer the newer generation. This is simply because I do not own them.

If you use this webapp, https://app.imow.sithl.com, this library should work for your mower.

Also see here: Issue #13

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

API Documentation is available on: https://chrishapunkt.github.io/stihl-imow-webapi/imow

If you want to
"Buy Me A Coffee"

Prerequisites

Python 3.14+ is required to run this application. Development uses uv for environment and package management.

Installing

For development, clone the repository and let uv create the environment (it will fetch Python 3.14 automatically per .python-version):

uv sync --group dev

Run commands inside the environment with uv run, e.g. uv run pytest. Alternatively, install the published library into your own environment:

pip install imow-webapi

And have fun!

Usage

Python Import and Usage

Import the module and instantiate the IMowApi() constructor with credentials. Afterwards, initiate the get_token() method. Or place credentials in the get_token() method.

from imow.api import IMowApi
from imow.common.actions import IMowActions
import asyncio
import aiohttp


async def main():
    async with aiohttp.ClientSession() as session:
        api = IMowApi(aiohttp_session=session, lang="de")
        # save token for later use if you want to recreate IMowApi(token=my_token) because the created token is valid for
        # 30 days
        token, expire_time = await api.get_token("email@account.stihl", "supersecret", return_expire_time=True)
        
        print(await api.get_token())
        
        mowers = await api.receive_mowers()
        mower = mowers[0]
        
        print(f"{mower.name} @ {mower.coordinateLatitude},{mower.coordinateLongitude}")
        print(f"Currently: {mower.stateMessage['short']}")
        await mower.update_setting("gpsProtectionEnabled", True)
        
        print(mower.stateMessage)
        print(mower.machineState)
        await mower.intent(IMowActions.TO_DOCKING)
        print(await mower.update_from_upstream())
        print(await mower.get_startpoints())
        

if __name__ == "__main__":
    asyncio.run(main())
Selection of outputs from above statements:
> Mährlin @ 54.123456,10.12345
> Currently: Hood blocked
> {'short': 'Hood blocked', 'long': 'The hood is blocked. Please check the hood and press the OK button on your machine (M1120).', 'legacyMessage': 'Abschaltung Automatikmode durch Bumper', 'errorId': '', 'error': False}
> HOOD_BLOCKED
> <imow.common.mowerstate.MowerState object at 0x000001B034C245F8>

Example: Receive startpoints and intent mowing

Save the following as myscript.sh and execute chmod +x myscript.sh. Make sure you install the api via pip3 install imow-webapi
Afterwards you can execute via ./myscript.sh

#!/usr/bin/env python3
from imow.api import IMowApi
from imow.common.actions import IMowActions
import asyncio
import aiohttp
import logging

logger = logging.getLogger("imow")
# Enable DEBUG output
logging.basicConfig(level=logging.DEBUG)

async def main():
    async with aiohttp.ClientSession() as session:
        api = IMowApi(aiohttp_session=session, lang="de")
        # save token for later use if you want to recreate IMowApi(token=my_token) because the created token is valid for
        # 30 days
        token, expire_time = await api.get_token("email@account.stihl", "supersecret", return_expire_time=True)
    
        print(await api.get_token())
    
        mowers = await api.receive_mowers()
        mower = mowers[0]
    
        print(f"{mower.name} @ {mower.coordinateLatitude},{mower.coordinateLongitude}")
        print(f"Currently: {mower.stateMessage['short']}")
    
        startpoints = await mower.get_startpoints()
        for i in range(len(startpoints)):
            print("Startpoint {}: {}".format(i, startpoints[i]))
        
        # if your mower supports the "startMowing" call, use this action (i.e iMow 600 series)
        await mower.intent(IMowActions.START_MOWING, starttime="2023-08-12 20:50")
        # await mower.intent(IMowActions.START_MOWING, endtime="2023-08-12 22:50")
        # await mower.intent(IMowActions.START_MOWING, starttime="2023-08-12 20:50", endtime="2023-08-12 22:50")

        # if your mower supports the "startMowingFromPoint" call, use this action (i.e iMow 400 series)
        await mower.intent(IMowActions.START_MOWING_FROM_POINT, duration=50)
        # await mower.intent(IMowActions.START_MOWING_FROM_POINT, startpoint=2)
        # await mower.intent(IMowActions.START_MOWING_FROM_POINT, duration=50, startpoint=2)


if __name__ == "__main__":
    asyncio.run(main())

Testing

For unit testing run pytest -s tests/test_unit*. For upstream integration testing, provide a /secrets.py with the following contents:

EMAIL = "email@account.stihl"
PASSWORD = "supersecret"
MOWER_NAME = "MyRobot"

and run pytest -s tests/test_integration* or pytest -s.

Built With

  • aiohttp
  • BeautifulSoup
  • asyncio

Versioning

Navigate to tags on this repository to see all available versions.

Authors

Mail Address GitHub Profile
chris@homeset.de ChrisHaPunkt

License

This project is licensed under the MIT License - see the LICENSE.md license file for more details.

Acknowledges

Thanks to

for repo structure inspiration

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

imow_webapi-0.11.0.tar.gz (28.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

imow_webapi-0.11.0-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file imow_webapi-0.11.0.tar.gz.

File metadata

  • Download URL: imow_webapi-0.11.0.tar.gz
  • Upload date:
  • Size: 28.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for imow_webapi-0.11.0.tar.gz
Algorithm Hash digest
SHA256 4d76c465f693d42c232fac83882ab0ada7d8f030b1b028b8166d20086d2e3dba
MD5 1cec2accc2b12819911dec939558be6d
BLAKE2b-256 e9a803976c76d5a348b6d84943508c449eda029481ef1d702f5d56ba4098ce64

See more details on using hashes here.

File details

Details for the file imow_webapi-0.11.0-py3-none-any.whl.

File metadata

  • Download URL: imow_webapi-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for imow_webapi-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 34bf61e5dad2fea872bbe42d3039e270cd955a82bfe8809f72e7b61b942effa1
MD5 d1c5df4b3097e978fad165a400f4a5b7
BLAKE2b-256 fac8e5467092be3761246e304de4f423684adf86543b3bfadb607c8841beb186

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page