chicago6061 / in.touch2

https://geckointouch.com/
23 stars 2 forks source link

Attached C# / Mono assemblies #1

Open stealthcopter opened 6 years ago

stealthcopter commented 6 years ago

I was looking to reverse engineer the protocol also and found your project, thanks for sharing!

I copied the Mono/C# source code out of the android apk file. Figured it might be of some use to you for working out the rest of the protocol. I'm looking into it but have little experience with C#.

assemblies.zip

stealthcopter commented 6 years ago

Spent a few hours digging into the code and I've worked out a few things. Managed to get the setting of the watercare and turning on/off of the light. The watercare should work for all devices, however part of the light command is specific to the model / firmware (might work for you, might not).

SetWatercareAwayFromHome = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x00</DATAS></PACKT>'
SetWatercareStandard = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x01</DATAS></PACKT>'
SetWatercareEnergySaving = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x02</DATAS></PACKT>'
SetWatercareSupersaver = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x03</DATAS></PACKT>'
SetWatercareWeekender = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x04</DATAS></PACKT>'

SetLightOn = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x33\x01</DATAS></PACKT>'
SetLightOff = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x33\x00</DATAS></PACKT>'

Let me know if you're still interested in this and I can post details on what else if find.

chicago6061 commented 6 years ago

The SpaPack definition file can be found here: http://intouch.geckoal.com/gecko/prod/SpaPackStruct.xml

stealthcopter commented 6 years ago

Yeah I found that thanks :) I worked out how to set the watercare, jets, temperature units (I use Celcius), and lock mode. I'd commit it as a PR but it's going to be specific to the model I'm using and I've not bothered to write something that dynamically reads SpaPackStruct.xml

    SetWatercareAwayFromHome = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x00</DATAS></PACKT>'
    SetWatercareStandard = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x01</DATAS></PACKT>'
    SetWatercareEnergySaving = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x02</DATAS></PACKT>'
    SetWatercareSupersaver = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x03</DATAS></PACKT>'
    SetWatercareWeekender = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SETWC%d\x04</DATAS></PACKT>'

# The following instructions require information about the SpaPackStructure for a particular model / revision.
# This can be found by inspecting the xml avaliable here:
# http://intouch.geckoal.com/gecko/prod/SpaPackStruct.xml
#
# SPACK Data structure: Starts with "SPACK%d" - %d is the sequence number.
#
#    Byte1: PackTypeNumber # 10
#           This is an enum between 0 - 10 depending on the model of spa. e.g. For inYT this is 10
#           <PackType Type="Enum" Pos="289" Items="Unknown|inXE|MasIBC|MIA|DJS4|inClear|inXM|K600|inTerface|inTouch|inYT" />
#
#    Byte2: 5 + value.length = 6
#           This is 5 plus the length of the data from byte 8 onwards (typically only one or two bytes)
#
#    Byte3: GeckoNETCommandID # 70
#           This is the command type to be sent (I think PACKS is 70 for all)
#
#    Byte4: ConfigurationLibrary # 61
#           Version of the configuration structure used
#
#    Byte5: LogLibrary # 61
#           Version of the log structure used
#
#    Byte6: Floor( POS / 256)
#    Byte7: POS % 256
#           These two bytes are set by looking up the data we are setting in the platform.xml and finding it's POS value.
#           e.g. for the light we lookup UdLi in the xml and find:
#                <UdLi Type="Enum" Pos="307" Items="OFF|HI" RW="ALL" />
#                so POS=301
#                byte 6: Floor(301/256) = 1
#                byte 7: 301 % 256 = 51
#
#    Byte8+: value (MSBFirst)
#
#
#   So for our complete example of turning on the light we would get
#        Decimal:     10   6  70  61  61   1  51   1
#        Hex:       \x0A\x06\x46\x3D\x3D\x01\x33\x01

    SetLightOn = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x33\x01</DATAS></PACKT>'
    SetLightOff = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x33\x00</DATAS></PACKT>'

    SetLockOn = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x36\x02</DATAS></PACKT>'
    SetLockPartial = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x36\x01</DATAS></PACKT>'
    SetLockOff = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x01\x36\x00</DATAS></PACKT>'

    SetTempUnitF = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x00\x21\x00</DATAS></PACKT>'
    SetTempUnitC = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x06\x46\x3D\x3D\x00\x21\x01</DATAS></PACKT>'

    SetTemp38 = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x07\x46\x3D\x3D\x00\x01\x02\xAC</DATAS></PACKT>'
    SetTemp36 = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x07\x46\x3D\x3D\x00\x01\x02\x88</DATAS></PACKT>'

    SetJet1 = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x02\x39\x01</DATAS></PACKT>'
    SetJet2 = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x02\x39\x02</DATAS></PACKT>'
    SetJet3 = '<PACKT><SRCCN>%s</SRCCN><DESCN>%s</DESCN><DATAS>SPACK%d\x0A\x02\x39\x06</DATAS></PACKT>'

Also decode some more of the status message

            if (seq  == 0):
                (junk1, tempUnits, junk2) = unpack('>34sb5s', rest)
            # Some interesting fields are present in the 7th message
            if (seq == 7):
                (f1, f2, f3, setpoint, temp, junk1, PackType, junk2,PackConfigLib, PackStatusLib, YT1, YT2, YT3, config, j1, j2, j3, j4, lights, junk3, lockStatus, junk4) = unpack('>bbbhh10sb5sbbhbbhbbbbb2sbb', rest)
bitlewis commented 5 years ago

Did you ever find out how to push out commands to intouch2?

chicago6061 commented 5 years ago

Here is a quick script that dumps all the values and descriptions of the status messages. The scripts requests a status update. The offset/position of every byte in the response is then looked up in the LogStructure/ConfigStructure and the tagname is printed out. For boolean values, the BitPosition is shown as well.

#!/usr/bin/python
import socket
import struct
from struct import *
import re
import xml.etree.ElementTree as ET

global sock
global server_address
global sqn

#
# Replace xxx with ID
# Replace yyy with MAC
statu = '<PACKT><SRCCN>xxxxxxxxx</SRCCN><DESCN>yyyyy</DESCN><DATAS>STATU#SEQ#\x00\x00\x02\x00</DATAS></PACKT>'

# Download SpaPackStruct.xml from http://intouch.geckoal.com/gecko/prod/SpaPackStruct.xml
# Replace IP address below

def connect():
        global sock
        global sqn
        global server_address

        # Create a UDP socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('', 0))
        localport = sock.getsockname()[1]
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)
        # We'll wait up to 20 second for a response
        sock.settimeout(20)
        connected = True
        server_address = ('192.168.2.231', 10022)
        print "Connected. ", server_address
        sqn = 1

def send(msg):
        global sqn
        buf = msg.replace('#SEQ#', struct.pack('b', sqn))
#       print >>sys.stderr, 'sending "%s"' % buf
        sent = sock.sendto(buf, server_address)
        sqn = sqn + 1

def recv():
    try:
        data, server = sock.recvfrom(4096)
    except:
        print "Timeout! No data received.."
        return None
    return data

def disconnect():
        sock.close();

def getStatusVerbose(log, config):
        send(statu)
        position = 0
        while True:
                data = recv()
                m = re.search(r'<DATAS>STATV(.*)</DATAS>', data, re.DOTALL)
                (seq, next, rest) = unpack('>bb{}s'.format(len(m.group(1))-2), m.group(1))
                #print "Seq: %s. Next: %s. Length: %s" % (seq, next, len(rest))
                #print [hex(ord(c)) for c in rest]
                position = position - 1
                for c in rest:
                        print position, hex(ord(c)), lookup(log, position), lookup(config, position)
                        position=position+1
                if (next == 0): 
                        break;

def lookup(root, index):
        t = root.findall(".//*[@Pos='"+str(index)+"']")
        result = ""
        for e in t:
                if ('BitPos' in e.attrib):
                        result = result + e.tag + "(" + e.attrib['BitPos'] + "),"
                else:
                        result = result + e.tag + ","
        return result

tree = ET.parse('SpaPackStruct.xml')

# Replace 'InYT' with the applicable model
# Hardcoded to use the first structure/version of Log and Config Structures
log = tree.findall(".//*[@Name='InYT']/LogStructures[0]/LogStructure")
config = tree.findall(".//*[@Name='InYT']/ConfigStructures[0]/ConfigStructure")

connect()
getStatusVerbose(log[0], config[0])
disconnect()

From the SpaPackStruct:

<RealSetPointG Type="Word" Pos="275" />
<DisplayedTempG Type="Word" Pos="277" />

And from the output below:

275 0x1 RealSetPointG, 
276 0xe  
277 0x2 DisplayedTempG, 
278 0xa8 

0x10e => 270 => 270/10 + 32 = 59F (RealSetPointG) 0x2a8 => 680 => 680/10 + 32 = 100F (DisplayedTempG)

Output:

0 0x5  ConfigNumber,
1 0x1  SetpointG,
2 0xe  
3 0x2  FiltFreq,
4 0xc  FiltStart,
5 0x0  
6 0x2  FiltDur,
7 0x0  
8 0xc  EconStart,
9 0x0  
10 0x6  EconDur,
11 0x0  
12 0x0  Out1,
13 0x1  Out2,
14 0x0  Out3,
15 0x3  Out4,
16 0x2  Out5,
17 0x0  Out6,
18 0x0  Out7,
19 0x0  Out8,
20 0x0  Out9,
21 0x0  Out10,
22 0x0  Out11,
23 0x0  Out12,
24 0x0  Direct,
25 0x0  Direct2,
26 0xe  OutHtr,
27 0x1  CpUsage,
28 0x0  O3Usage,
29 0x0  O3Pump,
30 0x0  O3Type,
31 0x1  HeaterPump,
32 0x2  FiltInterface,
33 0x0  TempUnits,
34 0x1  TimeFormat,
35 0x1e  CooldownTime,
36 0x0  Out1Cur,
37 0xa  Out2Cur,
38 0x0  Out3Cur,
38 0x27  Out3Cur,
39 0xa  Out4Cur,
40 0x4  Out5Cur,
41 0x0  Out6Cur,
42 0x0  Out7Cur,
43 0x0  Out8Cur,
44 0x0  Out9Cur,
45 0x0  Out10Cur,
46 0x0  Out11Cur,
47 0x0  Out12Cur,
48 0x0  DirectCur,
49 0x0  Direct2Cur,
50 0x11  OutHtRCur,
51 0x0  UL_CE,
52 0x1  NbPhases,
53 0x30  InputCurrent,
54 0x14  PumpTimeOut,
55 0x78  LightTimeOut,
56 0xf0  L120TimeOut,
57 0x2  OtOption,
58 0x14  OTTriggerG,
59 0x2  CpOnTimeDuringOT,
60 0x4  CpOffTimeDuringOT,
61 0x2  FiltOnTimeDuringOT,
62 0x28  FiltSuspendTime,
63 0x28  O3SuspendTime,
64 0x0  AmbiantOHTrigADC,
65 0x73  
66 0x1  MinSetpointG,
67 0xe  
68 0x2  MaxSetpointG,
69 0xd0  
70 0x0  EconType,
71 0x1  EconProgAvailable,
72 0x6  EconControlableManually(2),SoakOnCustomKey(0),OffOnCustomKey(1),CleanupOnCustomKey(3),AuxOnCustomKey(4),QuickOnOffCustomKey(5),
73 0x1  MasterSlave,
74 0x0  InputMenu,
75 0x0  SlaveConfig,
76 0x0  MultiKeyOption,
77 0x0  NoHeatPeriod,
77 0x27  NoHeatPeriod,
78 0x0  DrainMode,
79 0xf  OutLi,
80 0x2  LightInts,
81 0x5  L120Timer(0),PurgeSpeed(2),ProbeLocation(3),Pump1UserAccess(1),SelfCleanMsg(4),BlowerKeyOption(5),HeaterSoftStart(6),HeaterSoftStop(7),
82 0x0  UDProgEcon(0),
83 0x2  Out1Fuse,
84 0x0  Out2Fuse,
85 0x2  Out3Fuse,
86 0x1  Out4Fuse,
87 0x1  Out5Fuse,
88 0x3  Out6Fuse,
89 0x3  Out7Fuse,
90 0x3  Out8Fuse,
91 0x5  Out9Fuse,
92 0x5  Out10Fuse,
93 0x4  Out11Fuse,
94 0x4  Out12Fuse,
95 0x1  Direct1Fuse,
96 0x3  Direct2Fuse,
97 0x6  OutHtrFuse,
98 0x14  F1Current,
99 0xf  F2Current,
100 0xf  F3Current,
101 0xf  F21Current,
102 0xf  F22Current,
103 0xf  F23Current,
104 0x6  F1Line,
105 0x6  F2Line,
106 0x6  F3Line,
107 0x6  F21Line,
108 0x6  F22Line,
109 0x6  F23Line,
110 0x0  KeypadTherapySupport(0),CustomKeyEnabled(1),ConfigChange(2),BreakerChange(3),KeypadBacklightColor(4),KeypadBacklightEdit(7),
111 0x0  CustomerID,
112 0x0  ModeKeyAsInvertDisplayKey(1),InfoMsgConfig(2),LowerSetpointMenu(4),SinglePumpKey(6),
113 0x0  KeypadOptions4,
114 0x0  MaxNumberOfPhases,
115 0x0  CoolZoneMode,
116 0x0  FiltDur2,
116 0x27  FiltDur2,
117 0x0  
118 0x0  WaterfallTimeOut,
119 0x0  WaterfallAsCP(2),AuxAsBubbleGen(1),DealerLockSupport(0),
120 0x0  AuxTimeOut,
121 0x0  LockEnabled,
122 0x0  MinimumInputCurrent,
123 0x0  Zone1Led(0),Zone1Type(1),MapZone1ToOut1(4),MapZone1ToOut2(5),MapZone1ToOut3(6),MapZone1ToOut4(7),
124 0x0  Zone2Led(0),Zone2Type(1),MapZone2ToOut1(4),MapZone2ToOut2(5),MapZone2ToOut3(6),MapZone2ToOut4(7),
125 0x0  Zone3Led(0),Zone3Type(1),MapZone3ToOut1(4),MapZone3ToOut2(5),MapZone3ToOut3(6),MapZone3ToOut4(7),
126 0x0  Zone4Led(0),Zone4Type(1),MapZone4ToOut1(4),MapZone4ToOut2(5),MapZone4ToOut3(6),MapZone4ToOut4(7),
127 0x0  NumberOfZones(0),MappingEnable(7),
128 0x0  OnzenStart,
129 0x0  
130 0x0  OnzenDur,
131 0x0  
132 0x0  OnzenFreq,
133 0x0  ExerciseType,
134 0x0  ExerciseControl,
135 0x0  ExercisePumpsUsed(0),ExerciseDedicatedPumps(7),
136 0x0  ExerciseNumberOfIntensity,
137 0x0  ExercisePumpCombination1,
138 0x0  
139 0x0  ExercisePumpCombination2,
140 0x0  
141 0x0  ExercisePumpCombination3,
142 0x0  
143 0x0  ExercisePumpCombination4,
144 0x0  
145 0x0  ExercisePumpCombination5,
146 0x0  
147 0x0  ExercisePumpCombination6,
148 0x0  
149 0x0  ExercisePumpCombination7,
150 0x0  
151 0x0  ExercisePumpCombination8,
152 0x0  
153 0x0  ExercisePumpCombination9,
154 0x0  
155 0x0  ExercisePumpCombination10,
155 0x27  ExercisePumpCombination10,
156 0x0  
157 0x0  SilentMode,
158 0x0  SilentDuration,
159 0x0  
160 0x0  
161 0x0  
162 0x0  
163 0x0  
164 0x0  
165 0x0  
166 0x0  
167 0x0  
168 0x0  
169 0x0  
170 0x0  
171 0x0  
172 0x0  
173 0x0  
174 0x0  
175 0x0  
176 0x0  
177 0x0  
178 0x0  
179 0x0  
180 0x0  
181 0x0  
182 0x0  
183 0x0  
184 0x0  
185 0x0  
186 0x0  
187 0x0  
188 0x0  
189 0x0  
190 0x0  
191 0x0  
192 0x0  
193 0x0  
194 0x0  
194 0x27  
195 0x0  
196 0x0  
197 0x0  
198 0x0  
199 0x0  
200 0x0  
201 0x0  
202 0x0  
203 0x0  
204 0x0  
205 0x0  
206 0x0  
207 0x0  
208 0x0  
209 0x0  
210 0x0  
211 0x0  
212 0x0  
213 0x0  
214 0x0  
215 0x0  
216 0x0  
217 0x0  
218 0x0  
219 0x0  
220 0x0  
221 0x0  
222 0x0  
223 0x0  
224 0x0  
225 0x0  
226 0x0  
227 0x0  
228 0x0  
229 0x0  
230 0x0  
231 0x0  
232 0x0  
233 0x0  
233 0x27  
234 0x0  
235 0x0  
236 0x0  
237 0x0  
238 0x0  
239 0x0  
240 0x0  
241 0x0  
242 0x0  
243 0x0  
244 0x0  
245 0x0  
246 0x0  
247 0x0  
248 0x0  
249 0x0  
250 0x0  
251 0x0  
252 0x0  
253 0x0  
254 0x0  
255 0x0  
256 0x1 Hours, 
257 0x0 QuietState, 
258 0x0 UdP5(0),UdBL(1), 
259 0x0 UdP1(0),UdP2(2),UdP3(4),UdP4(6), 
260 0x0 P5(0),BL(1),CP(2),O3(3),L120(4),MSTR_HEATER(5),SLV_HEATER(6),Waterfall(7),Heating(5), 
261 0x0 P1(0),P2(2),P3(4),P4(6), 
262 0x5 FilterAccess(0),EconomyAccess(2),OnzenAccess(1), 
263 0x0 RemoteFiltAction, 
264 0x0 RemoteFiltDur, 
265 0x0  
266 0x0 RemoteFiltDurPerDay, 
267 0x4 RemoteEconAction, 
268 0x0 RemoteEconDur, 
269 0x2d  
270 0xff RemoteConfigIndex, 
271 0xff RemoteNbOfPhases, 
272 0xff RemoteBreakerIndex, 
272 0x27 RemoteBreakerIndex, 
273 0x0 Clean(0),Purge(2),FiltSuspendByUD(3),FiltSuspendedByOT(4),FiltSuspendedByErr(5), 
274 0x0 StickDetected(6),CPOT(2),OverTemp(1),ThermFuseErr(3),inFloPressureSwDetected(5), 
275 0x1 RealSetPointG, 
276 0xe  
277 0x2 DisplayedTempG, 
278 0xa8  
279 0x0 TempNotValid(2),ExtProbeDetected(6), 
280 0x0 CheckFlo(2),RhFloDetected(0), 
281 0x6 ProgEconActive(1),EconActive(2), 
282 0x0 SwmPurgeSusp(3),SwmPurge(5),SwmActive(6),ThermistanceErr(0),AmbiantOHLevel2(1), 
283 0x0 KinPumpOff(2),RegOverHeat(3),RhHwHL(0),RhRegProbeErr(1),RhRegSlope(4), 
284 0x0 HtrSuspendByPwrMng(0),Htr2SuspendByPwrMng(1),P1HStuck(3),P2HStuck(4),HeaterStuck(5),RelayStuck(6), 
285 0x0 PackBootID, 
286 0x15  
287 0x6 PackBootRev, 
288 0x0 PackBootRel, 
289 0xa PackType, 
290 0x3 PackMemRange(0),PackRegion(2), 
291 0x0 PackCoreID, 
292 0x14  
293 0x17 PackCoreRev, 
294 0x0 PackCoreRel, 
295 0x35 PackConfigLib, 
296 0x35 PackStatusLib, 
297 0x0 PackConfID, 
298 0xb1  
299 0x3 PackConfRev, 
300 0x0 PackConfRel, 
301 0x0 PackNumberOfConf, 
302 0x5  
303 0x0 UdPumpTime, 
304 0x0 UdQuietTime, 
305 0x0 UdLightTime, 
306 0x0 UdL120Time, 
307 0x0 UdLi, 
308 0x0 UdL120, 
309 0x0 RhHrKinNoFlo(0),RhNoFloXTries(1),FLCErr(3), 
310 0x0 LockMode, 
311 0x15 inTCipDelay, 
311 0x27 inTCipDelay, 
312 0x18  
313 0x0 SwmRisk, 
314 0x0 SlaveFloDetected(0), 
315 0x0 SlaveKinNoFloErr(0),SlaveNoFloErr(1), 
316 0x0 PackLogTrig, 
317 0x2 RhWaterTemp, 
318 0xa5  
319 0x0 Menu, 
320 0x0 SOut1, 
321 0x0 SOut2, 
322 0x0 SOut3, 
323 0x0 SOut4, 
324 0x0 SOut5, 
325 0x0 SOut6, 
326 0x0 SOutHtr,SOut7, 
327 0x0 SOut1Cur,SOut8, 
328 0x0 SOut2Cur,SOut9, 
329 0x0 SOut3Cur,SOut10, 
330 0x0 SOut4Cur,SOut11, 
331 0x0 SOut5Cur,SOut12, 
332 0x0 SDirect, 
333 0x0 SOutHtrCur,SDirect2, 
334 0x0  
335 0x0  
336 0x0  
337 0x0  
338 0x0  
339 0x0  
340 0x0 SOut6Cur, 
341 0x0 SOut7Cur, 
342 0x0 SOut8Cur, 
343 0x0 SOut9Cur, 
344 0x0 SOut10Cur, 
345 0x0 SOut11Cur, 
346 0x0 SOut12Cur, 
347 0x0 SDirectCur, 
348 0x0 SDirect2Cur, 
349 0x0  
350 0x0 SlaveHtrSuspendByPwrMng(0),SlaveHtr2SuspendByPwrMng(1),SlaveP1HStuck(3),SlaveP2HStuck(4),SlaveHtrStuck(5),SlaveRelayStuck(6), 
350 0x27 SlaveHtrSuspendByPwrMng(0),SlaveHtr2SuspendByPwrMng(1),SlaveP1HStuck(3),SlaveP2HStuck(4),SlaveHtrStuck(5),SlaveRelayStuck(6), 
351 0x0 SlaveKinPumpOff(2),SlaveRegOverHeat(3),SlaveHLErr(0),SlaveRegProbeErr(1),SlaveRegSlope(4), 
352 0x0 SlaveOverTemp(1),SlaveThermFuseErr(3), 
353 0x0 SlaveSwmPurge(5),SlaveSwmActive(6),SlaveThermistanceErr(0),SlaveAmbiantOHLevel2(1), 
354 0x0 SlaveMissingErr(0), 
355 0x1 SwmAdc, 
356 0x76  
357 0x1 KeypadType, 
358 0x0 KeypadID, 
359 0x0  
360 0x0 KeypadRev, 
361 0x0 KeypadRel, 
362 0x0 UdWaterFallTime, 
363 0x0 UdWaterfall, 
364 0x0 DealerLockStatus, 
365 0x0 DealerLockSeed, 
366 0x0  
367 0x0 DealerLockKey, 
368 0x0  
369 0x0 UdAuxTime, 
370 0x0 UdAux, 
371 0x0 inFloRatio, 
372 0x0 inFloRatioMinimum, 
373 0x0 inFloRatioMaximum, 
374 0x0 inFloErrorType, 
375 0x0 ForceCheckFlo(0), 
376 0x0 PackReset,inFloJustReset(0), 
377 0x0 SideHeatingDegG, 
378 0x0 CoolZoneDetected(0),HPCResHetaerRequest(4),HPCHeatRequest(5),HPCChillRequest(6),HPCAutoMode(7), 
379 0x0 HPCState, 
380 0x0 RemoteOnzenAction, 
381 0x0 RemoteOnzenDur, 
382 0x0  
383 0x0 SilentModeActive(0), 
384 0x0 InGridDetected(0), 
385 0x0 ExerciseDetectedType, 
386 0x0 ExerciseIntensity, 
387 0x0  
388 0x0  
389 0x0  
389 0x27  
390 0x0  
391 0x0  
392 0x0  
393 0x0  
394 0x0  
395 0x0  
396 0x0  
397 0x0  
398 0x0  
399 0x0  
400 0x0  
401 0x0  
402 0x0  
403 0x0  
404 0x0  
405 0x0  
406 0x0  
407 0x0  
408 0x0  
409 0x0  
410 0x0  
411 0x0  
412 0x0  
413 0x0  
414 0x0  
415 0x0  
416 0x0  
417 0x0  
418 0x0  
419 0x0  
420 0x0  
421 0x0  
422 0x0  
423 0x0  
424 0x0  
425 0x0  
426 0x0  
427 0x0  
428 0x0  
428 0x27  
429 0x0  
430 0x0  
431 0x0  
432 0x0  
433 0x0  
434 0x0  
435 0x0  
436 0x0  
437 0x0  
438 0x0  
439 0x0  
440 0x0  
441 0x0  
442 0x0  
443 0x0  
444 0x0  
445 0x0  
446 0x0  
447 0x0  
448 0x1 CFG0, 
449 0x2 CFG1, 
450 0x3 CFG2, 
451 0x4 CFG3, 
452 0x5 CFG4, 
453 0xff CFG5, 
454 0xff CFG6, 
455 0xff CFG7, 
456 0xff CFG8, 
457 0xff CFG9, 
458 0xff CFG10, 
459 0xff CFG11, 
460 0xff CFG12, 
461 0xff CFG13, 
462 0xff CFG14, 
463 0xff CFG15, 
464 0xff CFG16, 
465 0xff CFG17, 
466 0xff CFG18, 
467 0xff CFG19, 
467 0x27 CFG19, 
468 0xff CFG20, 
469 0xff CFG21, 
470 0xff CFG22, 
471 0xff CFG23, 
472 0xff CFG24, 
473 0xff CFG25, 
474 0xff CFG26, 
475 0xff CFG27, 
476 0xff CFG28, 
477 0xff CFG29, 
478 0xff CFG30, 
479 0xff CFG31, 
480 0x69  
481 0x6e  
482 0x59  
483 0x54  
484 0x5f  
485 0x43  
486 0x35  
487 0x33  
488 0x2e  
489 0x78  
490 0x6d  
491 0x6c  
492 0x0  
493 0x0  
494 0x0  
495 0x0  
496 0x69  
497 0x6e  
498 0x59  
499 0x54  
500 0x5f  
501 0x53  
502 0x35  
503 0x33  
504 0x2e  
505 0x78  
506 0x6d  
506 0x5  
507 0x6c  
508 0x0  
509 0x0  
510 0x0  
511 0x0 
Answer-1 commented 4 years ago

Just got my new spa with the in.touch2 remote and tried the spa.py to get the temperature, using the intouch url does nothing, but using the local IP of the in.touch2 device does work. So anyone wanting to get the water temperature and possibly using it in home automation stuff should be able to. You still need to get the identification string using tcpdump or something, but once you have this, you can query the in.touch2 device as you like.