Hot Tub Gecko inTouch2

Maybe @kalinrow can help?

Hello,

I guess that is a problem with the geockolib version used. My extension is based on v0.3.20 of the library. Since then a lot changed and my library is compatible with the new versions.
Unfortunately I do not have the time actually to make it working with the actual geockolib. Thus the only solutions for the time being is to install the old version of geckolib.
Please try to use pip install geckolib==0.3.20
BR Frank

Just noticed that both geckolib and paho-mqtt were not installed any longer after upgrade from Ubuntu 20.04 to 22.04. New install of both packages as root was necessary + geckolib fix.

Hi,
I have just uploaded a new version, adapted to heckling 0.4.7. It brings reminders out of the box and reacts on changes instead of polling.
Unluckily there are two issues with geckolib 0.4.7, so you need to adapt it after installation in case you want to fix. See Known Issues section.
BR

… lovin’ it :grinning:
Thank you for your great work, @kalinrow !!

On github you posted:

sudo apt install python3-pip
pip install geckolib==0.4.7
pip install asyncio-paho

I think that everything needs to be installed as root to make it work.

Why not change this to:

sudo apt install python3-pip
sudo pip install geckolib==0.4.7
sudo pip install asyncio-paho

… to make sure other people do not fall into the same trap as I already did with 0.3.20.

I also noticed that geckolib disconnected twice after appr. 2 days geckoclient.log showed “reconnecting…”. Cannot paste the log any longer, since I’m still running in debug mode.
Will do when it happens again.
Did you experience anything similar?

I made 2 enhancements to your code:

  • switch blower on/off
  • set watercare mode

client.py:

        # subscripbe and add callbacks
        await mqtt.subscribe_and_message_callback_async(
            const.TOPIC_BLOWERS + "/cmnd", spaman.set_blowers)
        await mqtt.subscribe_and_message_callback_async(
            const.TOPIC_WATERCARE + "/cmnd", spaman.set_watercare)

mySpa.py

    ################
    #
    # Switch the first blower ON/OFF
    #
    ##############
    async def set_blowers(self, client, userdata, message):
        '''
        Switch blower state
        '''
        topic = str(message.topic)
        msg = str(message.payload.decode("UTF-8"))
        logger.debug(f'msg erhalten: topic: {topic}, payload: {msg}')
        if (msg.startswith("set_blower")) and self.facade.blowers[0] is not None :
            parts = msg.split("=")
            if len(parts) == 2:
                if "ON" == parts[1]:
                    logger.info("Switching blower on")
                    await self._facade.blowers[0].async_turn_on()
                    logger.info("Blower switched on")
                elif "OFF" == parts[1]:
                    logger.info("Switching blower off")
                    await self._facade.blowers[0].async_turn_off()


    ################
    #
    # Sets the the watercare mode
    #
    ##############
                
    async def set_watercare(self, client, userdata, message):
        '''
        Set watercare mode
        '''
        topic = str(message.topic)
        msg = str(message.payload.decode("UTF-8"))
        logger.debug(f'msg erhalten: topic: {topic}, payload: {msg}')
        if (msg.startswith("set_watercare")):
            parts = msg.split("=")
            if len(parts) == 2:
                try:
                    mode = parts[1]
                except:
                    logger.error(f"Wrong mode received: {parts[1]}")
                    return
                await self._facade.water_care.async_set_mode(mode)

Well - all in all it look like a very big improvement

edit 2022 12 20:
geckolib disconnected again after 1d 8h - this time I captured logs…
gecko.service is still running

2022-12-20 13:18:25,215 - mySpa - DEBUG - Refreshing reminder data
2022-12-20 13:18:55,592 - mySpa - DEBUG - on_spa_change: >Reminders: [<geckolib.automation.reminders.GeckoReminders.Reminder object at 0x7fdb9ce594b0>, <geckolib.automation.reminders.GeckoReminders.Reminder object at 0x7fdb9ce59e10>, <geckolib.automation.reminders.GeckoReminders.Reminder object at 0x7fdb9ce599f0>, <geckolib.automation.reminders.GeckoReminders.Reminder object at 0x7fdb9ce5a020>]< changed from None to None
2022-12-20 13:18:55,592 - mySpa - DEBUG - Refreshing reminder data
2022-12-20 13:19:27,053 - geckoclient - INFO - Reconnecting...
2022-12-20 13:19:37,060 - geckoclient - INFO - Reconnecting...
2022-12-20 13:19:40,971 - geckolib.async_spa - ERROR - Exception during spa connection
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 367, in connect
    await self._connect()
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 334, in _connect
    if not await self.struct.get(
  File "/usr/local/lib/python3.10/dist-packages/geckolib/driver/async_spastruct.py", line 63, in get
    request = create_func()
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 337, in <lambda>
    self._protocol.get_and_increment_sequence_counter(False),
AttributeError: 'NoneType' object has no attribute 'get_and_increment_sequence_counter'
2022-12-20 13:19:45,599 - asyncio - ERROR - Task exception was never retrieved
future: <Task finished name='SPAMAN:Sequence Pump' coro=<GeckoAsyncSpaMan._sequence_pump() done, defined at /usr/local/lib/python3.10/dist-packages/geckolib/async_spa_manager.py:483> exception=AttributeError("'NoneType' object has no attribute 'get_and_increment_sequence_counter'")>
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa_manager.py", line 502, in _sequence_pump
    await self.async_connect(self._spa_identifier, self._spa_address)
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa_manager.py", line 302, in async_connect
    return await self.async_connect_to_spa(spa_descriptors[0])
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa_manager.py", line 268, in async_connect_to_spa
    await self._spa.connect()
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 367, in connect
    await self._connect()
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 334, in _connect
    if not await self.struct.get(
  File "/usr/local/lib/python3.10/dist-packages/geckolib/driver/async_spastruct.py", line 63, in get
    request = create_func()
  File "/usr/local/lib/python3.10/dist-packages/geckolib/async_spa.py", line 337, in <lambda>
    self._protocol.get_and_increment_sequence_counter(False),
AttributeError: 'NoneType' object has no attribute 'get_and_increment_sequence_counter'
2022-12-20 13:19:47,070 - geckoclient - INFO - Reconnecting...
2022-12-20 13:19:57,086 - geckoclient - INFO - Reconnecting...
2022-12-20 13:20:07,099 - geckoclient - INFO - Reconnecting...
2022-12-20 13:20:17,112 - geckoclient - INFO - Reconnecting...
2022-12-20 13:20:27,126 - geckoclient - INFO - Reconnecting...
2022-12-20 13:20:37,140 - geckoclient - INFO - Reconnecting...

Hi there,

I tried to gain a rebuilded connection to the Spa. The Gecko Lib is working flawless if i start it via Python3. I can control everything Lights, Blower and Temp.

If I start the gecko Service via python3 /opt/geckoclient/client.py i get an error

Traceback (most recent call last):
  File "/opt/geckoclient/client.py", line 166, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/opt/geckoclient/client.py", line 126, in main
    logger.info("Spa Name       : " + spaman.facade.spa.descriptor.name)
AttributeError: 'NoneType' object has no attribute 'spa'

So i thougth it has a problem with the fix permissions and i copied the files in “drivers” and “automation”.

When i did that I’m getting this error if i try to start it via Python3 → from geckolib import GeckoShell

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/geckolib/__init__.py", line 8, in <module>
    from .automation import (
  File "/usr/local/lib/python3.9/dist-packages/geckolib/automation/__init__.py", line 3, in <module>
    from .base import GeckoAutomationBase
  File "/usr/local/lib/python3.9/dist-packages/geckolib/automation/base.py", line 4, in <module>
    from ..driver import Observable
  File "/usr/local/lib/python3.9/dist-packages/geckolib/driver/__init__.py", line 3, in <module>
    from .protocol import (
  File "/usr/local/lib/python3.9/dist-packages/geckolib/driver/protocol/__init__.py", line 10, in <module>
    from .reminders import GeckoRemindersProtocolHandler, GeckoReminderType
ImportError: cannot import name 'GeckoReminderType' from 'geckolib.driver.protocol.reminders' (/usr/local/lib/python3.9/dist-packages/geckolib/driver/protocol/reminders.py)

Please make sure you install the packages as root:

Hope this will solve your issue.

EDIT:
After activate DEBUG in openhab-cli on MQTT it works. Don’t know why but…

Hi,

I am in despair:
Geckolib is running.
Query via MQTT Explorer is running.
Values are coming in MQTT Explorer.
Openhab shows broker and Whirlpool online.

But I don’t get any data.
I simplified everything for debugging, but I can’t figure it out.

things

Bridge mqtt:broker:mySecureBroker "MQTT OpenHAB Bridge" [ host="192.168.xxx.xxx", port="1883", secure=false, clientid="openhab", username="xxx", password="xxx", qos="1" ]

{

	// Whirlpool
	Thing topic whirlpool "Whirlpool" @ "wirli1" {
	Channels:
		Type number : current_temperature "Aktuelle Temperatur" [stateTopic="whirlpool/water_heater/state", transformationPattern="JSONPATH:$.current_temperature" ] 
		

	}

}```

items

/*
 * Gecko controler from Whirlpool
 */

Number:Temperature Whirlpool_Current_Temp      "Whirlpool Aktuelle Temperatur"   <temperature> (Whirlpool) { channel="mqtt:topic:mySecureBroker:whirlpool:current_temperature" }```

No Information in frontail or logs under var.




Anyone have any idea what I am doing wrong? Thanks

Hi,

it’s me again :slight_smile: .
@kalinrow is it possible to configure two whirlpools (1x Whirlpool + 1x SwimSPA) in the config.py
or did I need two geckoclient services?
Can’t find to configure more than one whirlpool in the documentation.

Thanks.

Hello Klaus,

as you are now asking for a second SPA I assume you solved the first issue and you get the data in OpenHab now.
Regarding a second SPA, I didn’t implement support for multiple SPA’s in the client. But I don’t see a reason, why it should not work but duplication everything. Meaning installing the client in a second folder, installing a second the gecko1.service file pointing to the second location and adapting the config.py to have dedicated BROKER_ID, TOPIC and LOGFILE location.
At least you can give it a try.

EDIT:
Forget about it. Your way, easier way.
I changes async parameter.
CPU now 5% per python.
Install second service.
Everything is working.

Thank you.

Thanks.
Do you think that when I edit the client.py, that I pack the second request into the loop, the geckolib can check two with async mode?

The python draws 25% CPU from me, would not like to start a second as a service.

Otherwise, thank you again for the great work!

Hi Everyone,

possible to control circulation pump(set)?
Can’t find the right set parameter for this pump.

Thanks.

Hello Klaus,

glad to see that it works with using two services. Indeed I wanted to check, if you changed the async parameter, but you found it :wink:

Regarding the circulation pump, no it not possible to control it. I’m even not sure, if the underlying gecko-library is offering this. Or if that is offered at all from gecko as there is no option in the TouchApp as well. Maybe an idea to look at in a future version.

Best regards
Frank

Big thanks to all involved in the project @kalinrow
After my sucessfull transition to OH3 I set up the geckolib and Mqtt acording to kalinrows github documentation.

info for others (or maybe Im a MQTT noob):
For testing the connection I tried to get values into current_temperature with result NULL
After a long search for possible failures I stumbled over the fact, that the topic / string only updates if one of the values changes. :sleepy: Other topics like reminders will be updated every 2 minutes.