gazoodle / geckolib

Library to interface with Gecko Alliance spa pack systems via in.touch2 module
GNU General Public License v3.0
60 stars 23 forks source link

Mr Steam/Steamlinx handling #6

Open rct opened 3 years ago

rct commented 3 years ago

Trying GeckoLib shell with only the Mr Steam Steamlinx unit on the local lan. I'm not expecting Geckolib to run at this point, but thought I would collect and report data.

Perhaps a first goal would be to get to the point of recognizing the Mr. Steam unit isn't a spa and should be skipped.

Running GeckoShell hangs at Connecting to spaMy Steamerat 192.168... Since it attempts to auto connect and hangs, I can't go any further in that shell. I wind up having to CTRL-C.

I haven't figured out yet if there is debugging I should be turning on.

With tcpdump I see a bunch of UDP with XML packets go back and forth. Guessing the command might be APING. There is a reference to MrSt_C02.xml. It seems like the shell/library polls every few seconds.

Please let me know what would be good to run in order to collect data.

From the activity/comments, I believe that this repo is now that active one and that we shouldn't be using Chicago6061's in.touch2 repo, is that correct?

I saw a reference to client.py @gazoodle mentioned in the other repo, has that been replaced by GeckoShell?

If I run GeckoShell with both the in.touch2 (spa) and Mr. Steam steamlinx connected, it reports 2 spas found. However, I don't see an obvious command to use to connect to one of them, but maybe I'm being dense.

Let me know if you want to see any data from my in.yt-8 controller. I've done a config dump using GeckoShell. All looks ok as far as I can tell. I haven't gotten Chicago6061's dumpall.py to work yet.

gazoodle commented 3 years ago

Perhaps a first goal would be to get to the point of recognizing the Mr. Steam unit isn't a spa and should be skipped.

Sounds like a good plan. I'll need some diags to help with that. See below

Running GeckoShell hangs at Connecting to spaMy Steamerat 192.168... Since it attempts to auto connect and hangs, I can't go any further in that shell. I wind up having to CTRL-C.

I haven't figured out yet if there is debugging I should be turning on.

From version 0.3.11 onward, the shell can emit logging to a file. Use:

from geckolib import GeckoShell
GeckoShell.run(["logfile client.log"])
 :
 :

After you have the client.log file, you can email it to me at gazoodle at hash dot fyi

From the activity/comments, I believe that this repo is now that active one and that we shouldn't be using Chicago6061's in.touch2 repo, is that correct?

I've been doing a huge amount of work on the library so it's certainly the most recent, but it doesn't handle reminders yet, so there is still use for Chicago6061's in.touch2 repo

I saw a reference to client.py @gazoodle mentioned in the other repo, has that been replaced by GeckoShell?

Yes. After moving to PyPI the test section isn't distributed with the pip install geckolib command and I needed a way to have some diags available when installed that way. All the functionality from client.py has been moved to GeckoShell.

If I run GeckoShell with both the in.touch2 (spa) and Mr. Steam steamlinx connected, it reports 2 spas found. However, I don't see an obvious command to use to connect to one of them, but maybe I'm being dense.

Not being dense, I just hadn't documented it clearly ... which should have been addressed now. Anyway, the command is manage <spanum> where <spanum> can be found by doing list

rct commented 3 years ago

@gazoodle thanks for your work and help with this.

With the latest code from master, I now get an exception Cannot find spa pack for MrSt. I'm guessing that means a source for MrSt_C02.xml is needed, since I saw a reference to that in the packet capture. I'm emailing client.log to you.

Starting discovery process...Found 2 spas
Welcome to the Gecko shell. Type help or ? to list commands.

(Gecko) list
1. My Steamer
2. My Spa
(Gecko) manage 1
Connecting to spa `My Steamer` at 192.168.208.48 ... LOG> ERROR Exception in receive thread func, aborting
Traceback (most recent call last):
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/driver/comms.py", line 143, in _receive_thread_func
    GeckoConstants.MESSAGE_PART_DATAS, self.receive_answer()[0]
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/driver/comms.py", line 157, in _handle_response
    if handler.handle_response_if_matched(self, response):
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/driver/responses.py", line 67, in handle_response_if_matched
    if self.handler(spa, response):
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/driver/responses.py", line 270, in config_handler
    gecko_pack_config[0]
Exception: Cannot find spa pack for MrSt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/utils/shell.py", line 64, in run
    shell.cmdloop()
  File "/usr/lib/python3.7/cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python3.7/cmd.py", line 217, in onecmd
    return func(arg)
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/utils/shell.py", line 138, in do_manage
    self.facade = spa.get_facade()
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 37, in get_facade
    return GeckoFacade(GeckoSpa(self).connect())
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/automation/facade.py", line 27, in __init__
    self._water_heater = GeckoWaterHeater(self)
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/automation/heater.py", line 22, in __init__
    self._temperature_unit_accessor = self._spa.accessors[
AttributeError: 'NoneType' object has no attribute 'accessors'
gazoodle commented 3 years ago

Thanks @rct, those log files will help me understand that. Question: Does the iOS or Android Gecko app discover (and possibly manage) the Mr Steam unit when you have both connected to your LAN, or must you use the Gecko app for your hot tub and the Steamlinx app for your Mr Steam unit?

rct commented 3 years ago

The two devices are managed by two separate apps. I'm using iOS. On start up, with the steamlinx app I've got to choose the right gecko device. The gecko spa app seems like it remembers my choice.

I captured packets while using the steamlinx app, but haven't tried to really dig into it yet. The hosts it looks up are

I see UDP traffic to intouch and intouch2. api-steamlinx is an app running on heroku. It seems to have some login page. but I can't get past the device selection without getting logged out.

I didn't see any fetches of MrSt_C02.xml or MrSt_S02.xml referenced in <DATAS>FILES,MrSt_C02.xml,MrSt_S02.xml</DATAS></PACKT>

gazoodle commented 3 years ago

I didn't see any fetches of MrSt_C02.xml or MrSt_S02.xml referenced in <DATAS>FILES,MrSt_C02.xml,MrSt_S02.xml</DATAS></PACKT>

Those files don't seem to be anywhere, at least that I've found for any of the spas we've tested with. Currently I use the data before the underscore to indicate a key for a <Plateform> node in SpaPackStruct.xml and then go from there. Looks like they've got the old DOS 8.3 filename limit somewhere in their code, so perhaps I'll need to use MrSt and match that start with MrSteam

If I do that, then we can either ignore the steam unit or handle it correctly ... no reason you'd not want your steam shower in HA too!

I'm currently building a spa simulator that I can use to investigate the other side of the conversation and see what the apps do to chat to me.

I've not had this much fun in ages :-)

gazoodle commented 3 years ago

0.3.13 Ought to be able to progress to the next stage of handling your MrSteam unit. When you get a chance, can you try and if possible, once connected drop a snapshot to me...

spa$ snapshot Connected to MrSteam

Maybe also make some changes on the MrSteam control unit, then

spa$ refresh
(wait 10-15 seconds)
spa$ snapshot <Description of what you've changed>

Then email the client.log file to me Thanks!

rct commented 3 years ago

@gazoodle Thanks for working on this. I get an exception KeyError: PackConfID when trying to do manage 1:

(This is with the code in your default branch main, pulled today (2020-12-20)

Starting discovery process...Found 2 spas
Welcome to the Gecko shell. Type help or ? to list commands.

(Gecko) list
1. My Steamer
2. My Spa
(Gecko) manage 1
Connecting to spa `My Steamer` at 192.168.208.48 ... Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/driver/udp_socket.py", line 364, in _thread_func
    self._loop_func()
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 260, in _loop_func
    self._final_connect()
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 267, in _final_connect
    self.accessors[GeckoConstants.KEY_PACK_CONFIG_ID].value,
KeyError: 'PackConfID'

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 282, in _ping_thread_func
    self.refresh()
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 311, in refresh
    if not self.is_connected:
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 306, in is_connected
    raise RuntimeError("Spa took too long to connect ...")
RuntimeError: Spa took too long to connect ...

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/utils/shared_command.py", line 38, in run
    cmd.cmdloop()
  File "/usr/lib/python3.7/cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python3.7/cmd.py", line 217, in onecmd
    return func(arg)
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/utils/shell.py", line 97, in do_manage
    self.facade = spa.get_facade()
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 48, in get_facade
    while not facade.is_connected:
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/automation/facade.py", line 68, in is_connected
    if not self._spa.is_connected:
  File "/home/rct/proj/gecko/gazoodle/geckolib/src/geckolib/spa.py", line 306, in is_connected
    raise RuntimeError("Spa took too long to connect ...")
RuntimeError: Spa took too long to connect ...
rct commented 3 years ago

Coming back to this because of https://github.com/gazoodle/gecko-home-assistant/issues/20:

I believe I have the latest commited Geckolib in the main (default) branch from mid December 2020.

I may have forgotten some stuff about starting Geckolib's shell, currently it does the discovery and then looks like it just returns an object, instead going interactive:

>>> from geckolib import GeckoShell
>>> GeckoShell()

        <Disclaimer>
        ----------------------------- USE AT YOUR OWN RISK -----------------------------

        This code will allow you to make changes to your spa configuration that is
        outside of what the app, top panel and side panel settings allow. I've not
        tested every setting and it might be that you prevent your spa pack from
        operating as it used to do.

        Configuration is declared in the file SpaPackStruct.xml which is downloaded the
        first time you run this program. Settings marked as RW="ALL" seem to indicate
        that any process can write them, so you ought to be able to revert the settings
        to their original ones.

        I strongly suggest dumping the configuration values with the "config" command
        and recording them somewhere safe.

        </Disclaimer>

Starting discovery process...Found 2 spas
<geckolib.utils.shell.GeckoShell object at 0xb66a9b70>
>>> 

At this point both Gecko units are on the network. The in.touch2 spa gecko doesn't have an RF connection because the tub is currently powered down.

Here's the client.log


2021-06-06 14:08:42,845 geckolib.locator INFO Discovery process started
2021-06-06 14:08:42,846 geckolib.locator DEBUG Locator retry thread started
2021-06-06 14:08:42,896 geckolib.driver.udp_socket DEBUG Sending b'<HELLO>1</HELLO>' to ('<broadcast>', 10022)
2021-06-06 14:08:43,851 geckolib.driver.udp_socket DEBUG Sending b'<HELLO>1</HELLO>' to ('<broadcast>', 10022)
2021-06-06 14:08:43,858 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:4c:xx:xx|My Steamer</HELLO>' from ('192.168.1.48', 10022)
2021-06-06 14:08:43,861 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:43:yy:yy|My Spa</HELLO>' from ('192.168.1.49', 10022)
2021-06-06 14:08:44,866 geckolib.driver.udp_socket DEBUG Sending b'<HELLO>1</HELLO>' to ('<broadcast>', 10022)
2021-06-06 14:08:44,873 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:4c:xx:xx|My Steamer</HELLO>' from ('192.168.1.48', 10022)
2021-06-06 14:08:44,876 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:43:yy:yy|My Spa</HELLO>' from ('192.168.1.49', 10022)
2021-06-06 14:08:45,881 geckolib.driver.udp_socket DEBUG Sending b'<HELLO>1</HELLO>' to ('<broadcast>', 10022)
2021-06-06 14:08:45,888 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:4c:xx:xx|My Steamer</HELLO>' from ('192.168.1.48', 10022)
2021-06-06 14:08:45,891 geckolib.driver.udp_socket DEBUG Received b'<HELLO>SPA80:1f:12:43:yy:yy|My Spa</HELLO>' from ('192.168.1.49', 10022)
2021-06-06 14:08:46,852 geckolib.locator INFO Found 2 spas ... [My Steamer(SPA80:1f:12:4c:xx:xx), My Spa(SPA80:1f:12:43:yy:yy)]
2021-06-06 14:08:46,853 geckolib.locator DEBUG Locator retry thread stopped
2021-06-06 14:08:46,897 geckolib.driver.udp_socket INFO GeckoUdpSocket thread finished
rct commented 3 years ago

Updated logs attempting to connect to Mr. Steam. I don't know why my previous attempts to run the GeckoShell exited early, returning a geckolib.utils.shell.GeckoShell object. At the time the spa gecko was connected to the network but the tub was powered off.

Now I get a KeyError: PackConfID when trying to manage the Mr. Steam. From the log it looks like progress is being made, the list of "temperature keys" looks encouraging!

2021-06-14 17:08:34,661 geckolib.driver.spastruct DEBUG Temperature keys to decorate {'Prog2SetpointG', 'Prog1SetpointG', 'MinSetpointG', 'K1000TempG', 'MaxSetpointG', 'RoomTempG', 'UserSetpointG'}
2021-06-14 17:08:34,661 geckolib.driver.accessor DEBUG Accessor PackType @ 285, Enum raw data = d
2021-06-14 17:08:34,662 geckolib.driver.accessor DEBUG Enum accessor PackType adjusted data = MrSteam

Output from GeckoShell trying to manage steamlinx unit:

Starting discovery process...Found 2 spas
Welcome to the Gecko shell. Type help or ? to list commands.

(Gecko) list
1. My Spa
2. My Steamer
(Gecko) 2
*** Unknown syntax: 2
(Gecko) manage 2
Connecting to spa `My Steamer` at 192.168.1.48 ... Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/driver/udp_socket.py", line 364, in _thread_func
    self._loop_func()
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 260, in _loop_func
    self._final_connect()
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 267, in _final_connect
    self.accessors[GeckoConstants.KEY_PACK_CONFIG_ID].value,
KeyError: 'PackConfID'

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 282, in _ping_thread_func
    self.refresh()
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 311, in refresh
    if not self.is_connected:
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 306, in is_connected
    raise RuntimeError("Spa took too long to connect ...")
RuntimeError: Spa took too long to connect ...

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/utils/shared_command.py", line 38, in run
    cmd.cmdloop()
  File "/usr/lib/python3.7/cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python3.7/cmd.py", line 217, in onecmd
    return func(arg)
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/utils/shell.py", line 97, in do_manage
    self.facade = spa.get_facade()
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 48, in get_facade
    while not facade.is_connected:
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/automation/facade.py", line 68, in is_connected
    if not self._spa.is_connected:
  File "/srv/pyvenvs/geckolib/lib/python3.7/site-packages/geckolib/spa.py", line 306, in is_connected
    raise RuntimeError("Spa took too long to connect ...")
RuntimeError: Spa took too long to connect ...
>>>

Here's the log file. mac yy;yy is the steamlinx (mr. steam) unit. mac xx:xx is the in.touch2.

steam1-clean.log

xbmcgotham commented 2 years ago

If I do that, then we can either ignore the steam unit or handle it correctly ... no reason you'd not want your steam shower in HA too!

I'm currently building a spa simulator that I can use to investigate the other side of the conversation and see what the apps do to chat to me.

I've not had this much fun in ages :-)

I love to have my Mr.Steam unit integrated into HA. I am sure @rct does too. :-)

Any way to work with you both getting this setup? Looking forward to any response. :-)

yungeconomist commented 1 year ago

I've been looking into this for my steam generator. Just curious; what would need to be done to correctly integrate the SteamLinx units? I see under geckolib/src/geckolib/driver/packs/ [mrsteam-cfg-1.py], [mrsteam-cfg-2.py] and [mrsteam-cfg-3.py]. Would effort developing those be the next step or what? I am motivated to help push this forward, but a little advice on where to start would be immensely helpful. Thanks!

ChrisRut commented 1 year ago

@gazoodle I'd love to help contribute to this, but not sure where to begin. Would additional debug logs help? Would you be interested in having this issue be sponsored, I found a couple of options for sponsoring this issue:

I'll happily contribute $100 to this issue and time to help you work on this. Would you have a preference on this?

I also researched a couple of other github projects that look to be working on a similar issue with Mr.Steam SteamLinx integrations:

Not sure if anything can be gleaned from these, I tried to get these working with no success.

borisdaenen commented 9 months ago

Happy to contribute $100 to a working HASS integration too!