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.10.0.tar.gz (28.3 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.10.0-py3-none-any.whl (25.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: imow_webapi-0.10.0.tar.gz
  • Upload date:
  • Size: 28.3 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.10.0.tar.gz
Algorithm Hash digest
SHA256 8438126256c3b3fa7fe9110bf99a1f33daaaf8fb530d037b6c8f3180121b889d
MD5 843bb137b9809f56b75420f56b903b17
BLAKE2b-256 1a838d44e0ee1ad87977cd43a2a72734ea0df80afafaced68d3e3ed476eb1ddd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: imow_webapi-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 25.4 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.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6827045badef599f1c70e15ca333602879c603618c437d29bae7e01fac96236f
MD5 6ab6d78837b2902dd6f0736a05d4c929
BLAKE2b-256 2da539f59e9e9ec1b6f0b546785e2037fea96b583ab8f54fb8328fd719ce4522

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