Carrier Infinity

Here's what I've gleaned from nebulous's capture so far.
 
The primary devices are 5001 (AC) ,2001 (Stat), 4201 (Furnace).  1F01 does a lot of interrogation up front, including capturing the furnace model number, but after startup remains silent for the capture (at least for the startup log).  It seemed to interrogate a lot of other addresses that I don't recall on mine, but I'll have to verify that (new ones for me are: 5101, 4202, 6001, 6101, 0E01, 2401, 2501, 2601, 2701, 2801 - none of the devices respond in his capture).  2001 still manages the time of the system using broadcasts, like mine.  2001 also captures the model number like mine.  I don't remember 1F01 on my system, but I'll need to do a startup capture myself again.
 
I also forgot how crappy it is there is no coordination among devices - They all just seem to talk whenever they want and rely on retries and repeating the same thing alot to ensure communication.  This makes it really hard to parse at times, and very difficult to determine when to inject packets into the live comm.  I have yet to see a rhyme or reason to this - I keep dwelling on it because it seems like really poor design, but I've yet to come up with a better theory.
 
====== the following is not related to the capture, but is information I have been referencing and I thought would be worthwhile ======
 
As for the tools for this effort here's what I've thought of, but I don't have a ton of working code.
 
I've been working towards a tool, that can:
1) capture and optionally store raw data
2) interpret data in real time
3) inject packets into the stream
4) watch each register/table for changes, and only show those
5) allow filters to hone on on specific data
 
My hope is that the tool would be able to capture the changes in raw data and store it in a database with a timestamp.  Then, as the mappings are determined you could make trends of data you have been capturing but didn't necessarily know the meaning of at the time.  If it is in a database over time, you could also look back at specific bytes and only focus on ones that change to try to interpret them.  Part of what I have struggled with is how to store the interpretations of data in a way that is useful and forward looking. Right now my file looks like this:
 

2001,SYSTIME ,02,01,13,01,1,19
2001,SYSTIME ,02,02,03,03,1,1,Hours,>B
2001,SYSTIME ,02,02,03,03,2,1,Minutes,>B
2001,SYSTIME ,02,02,03,03,3,1
2001,SYSTIME ,02,03,03,03,1,1,Day,>B
2001,SYSTIME ,02,03,03,03,2,1,Month,>B
2001,SYSTIME ,02,03,03,03,3,1,Year,>B

2001 is the device from which the request comes
SYSTIME is any text, but it refers to the table name
02 is the table address
the next column is the row in the table
the next column is the length of the row (number of bytes in hex)
the next column is a value from the table structure register (generally at a pattern of 0x??01)  I think it relates to the number of values in a row, but it isn't consistent.
Then you have the byte to start, and how many bytes to take, a name to give it, and how to interpret the data (a string that feeds into a python function)
 
The problem is I am expecting values to be within a byte or bytes, where it is completely possible for a byte to contain multiple pieces of data.  I'm considering adding a bitmask and bitwise shift value to deal with this. 
 
I realize I'm getting ahead of myself with my nomenclature and have made alot of assumptions in this post so far.  I'll digress into that for a minute. 
The data in the system is somewhat self describing.  The register as I call it is generally 2 bytes - a table and a row.  The first row defines the table, and the following rows have data.  This table identical in device 5001 (my AC unit), but it is where a broadcast from 2001 (my stat) write the data every minute or so.
 

0x0201 00 21 53 59 53 54 49 4d 45 20 00 19 03 13 01 03 03 03 03
0x0202 0d 36 06
0x0203 05 0c 0a

So 0x02 is the table, and the following byte is the row.  I'll walk across the first row and show how it defines the table.  You can only get this row by asking for it from the device.
I don't recall what 0021 is.
The next 8 bytes are the name of the table = 53595354494d4520 is SYSTIME with a trailing space (ascii)
00 19 relates to the size of the table (25 bytes)
03 is the total number of rows in the table
13 is the bytes of this row (in hex) and 01 is unknown
03 is the bytes in the second row, and 03 is unknown
03 is the bytes in the third row, and 03 is unknown.
 
The second byte of the last three lines of my description might relate to the number of pieces of data in this row, although I haven't confirmed this.  In this case row 2 each byte represents hour, minute, and day of week, and in row 3 each byte is day, month, year.  This was discovered by watching data, and interpreting the table name. This one is a good example to start with and everything is pretty clear, but other tables are more difficult.
 
Whew... that was a little more than I expected to post in one sitting, so forgive the typos or lack of coherency.
 
Screw sleep.  I'll just keep posting...
 
nebulous... I have a couple of files for you but I don't know if you want me to post them here.  I have a parsed file using your log (it basically just added CR/LF and converted HEX to text so you can read it with a text editor).  I also have a file with all the unique commands used during the whole startup.  There are about 170 unique commands, and a lot of those are requests for devices you don't have during the discovery.
 
Also to clarify a previous post, I do not have a 1F01 device on my system at all, so I suspect this is part of the touch device, but I'm not sure what that will gain for us.  The real help with be the capture with the SAM on the line.
 
The second row parameter instead of being #of values could be data type?  01=header data, 02=ascii data, 03=binary data?
 
Cool, thanks 3tones. If you're familiar with git, feel free to fork Infinitude and submit a pull request, but PM/email works fine too. I think the parser on github will do the same thing(it does points #1 & #2 with varying levels of WIP for #3-#5), but it will definitely be nice to compare the output. My thermostat identifies itself as a SAM interestingly enough, and its documentation states that it can't work with a SAM, so my hypothesis is it's a sam and stat in one. I think the stat is the 1f01 device which creates the broadcast storm interrogating devices, then after everyone responds and things settle down, all communications are unicast requests from stat to devices and the device responses. So no collisions after the initial setup phase. 
 
I'm also logging values the stat sends to Infinitude into those JSON files. As soon as I get the tuits I'll correlate the two by timestamp in an sqlite file. Initially I was trying to limit the perl dependencies because people seem to have an irrational fear of installing perl modules, but the cleanup will be easily worth it. Regarding bitshifting: based on the simplicity of the data packing so far, I'd be surprised if everything weren't byte aligned. Any string values are padded with nulls which indicates to me they're fixed width.
 
Hopefully we can at least identify the stream format/data model for most devices and values, ideally that will allow control with a faked sam device, but if not, all it seems it should take is a microcontroller sitting between the thermostat and the rest of the network acting as a bridge. An rPI would do nicely if you wanted to run your own web-based control of it or something, but an avr/msp430/pic should be all it really takes to handle what amounts to a few serial commands once the protocol/values are worked out.
 
nebulous said:
I think the stat is the 1f01 device which creates the broadcast storm interrogating devices, then after everyone responds and things settle down, all communications are unicast requests from stat to devices and the device responses. So no collisions after the initial setup phase.
 
You probably understand this, but I want to clarify this a little - I don't want anyone to think this is like an ethernet switch.  The 485 bus is a half duplex, multi-master network.  There seems to be nothing built into the protocol to prevent two devices from talking at the same time, with the exception that the stat (2001) does most of the requests, and other devices generally respond to that request.  A broadcast packet (which generally comes from 2001) just means that all devices should do something with it, but aside from that, all devices receive all data all the time on their transceivers and ignore packets not addressed to them (think of a half duplex ethernet hub).  There are only a two cases of broadcasts: 3 requests from 1F01 on startup, and date/time.  The Date/Time broadcast does happen on regular intervals.
 
There really isn't a broadcast storm on startup as I see it.  There is a pattern of interrogating each possible device on the network, generally initiated by 2001 and 1F01 (in fact they ask for a lot of the same things).  There are definitely collisions, even after startup.  It generally can be seen when checksums don't match, and bytes are randomly spliced together from the competing transceivers.  Again, this seems like a natural occurrence due to the fact there is little coordination of the conversation.  I suspect this would get worse with more devices on the network.
 
Tom
 
So back up a little bit...
 
There are several message types: 
 
0B = Read Data
0C = Write Data
06 = Response/ACK
15 = Error/NAK
 
Read and Write specify a 3-byte index location (the latter two of which you are calling table # and row index)?  Write is then followed by the data for that location.  Read data is returned in a response following the same 3 index bytes.  Response to a write is a single null byte?
 
You are correct on the message types, and that's all I've seen.
 
The date/time broadcast is a write to all, and has no response.
 
The 3 byte "register" as I call it always has 00 for the first byte.  The second byte is the table, the third byte is the row.  We determined this row/table structure after poking at the registers rather than just listening to data.
 
A read's data only consists of the 3 byte "register".  The response includes the register and the data.
A write consists of the register and data to be written.  An ok write is a response with a single null byte as the data.
I've seen 15 occasionally, and it has a single byte response.  The byte is non-null so it is probably an error code of some kind.
 
And I think I agree with your previous comment:
01=header data, 02=ascii data, 03=binary data?
 
Ok sounds good.
 
So device ID's
 
0E = ??
1F = ??
 
User Interfaces
20 = Thermostat (Touch Control with Wi-Fi)
21 = ??
22 = ??
23 = ??
24 = ??
25 = ??
26 = ??
27 = ??
28 = ??
 
Indoor Units
40 = Gas Heater/Blower?
41 = ?
42 = Variable Speed Fan Coil
 
Outdoor Units
50 = Heat Pump
51 = Air Conditioner?
 
60 = ??
61 = ??
80 = ??
92 = ??
 
Special
F1F1 = Broadcast Address
 
Potential Equipment:
 
?? = Damper Control Module (SYSTXCC4ZC01)
?? = Smart Sensor (SYSTXCCSMS01)
?? = NIM (SYSTXCCNIM01)
?? = Control Zoning User Interface (SYSTXCCUIZ01)
?? = Control User Interface (SYSTXCCUID01)
20 = Touch Control with Wi-Fi
20 = Touch Control
?? = Infinity Remote Access Module
 
If there are multiple of the same type of device presumably the low byte of the ID gets incremented?  Are multiples supported?
 
I can only vouch for 20, 40, and 50.  Where did you come up with guesses for 60 and 61?  I've also seen requests for 41 and  92.  There is also a device called a "NIM" that allows non-communicating devices to be controlled (such as a furnace, heat pump or AC unit)
 
I wouldn't call 1F01 a master.  Mine doesn't have one and 2001 does all the read/write requests, with other devices only responding to that.  The only exception is that 4001 (my ac) sends a read request (0B) to 4101, but there isn't a response.  In nebulus's log, that is also the case, except 1F01 does a few things during startup, then remains silent (at least for the term of the capture).
 
There is support for multiple systems on a SAM (based on SAM ASCII protocol document and the install document for the SAM) but they hang off two physical connectors on the SAM and might not be connected to eachother.  I don't know how many devices a system can have and how they would work together - 2 AC units on one furnace for example.  You can also have up to 8 zones per system, using (2) 4 zone modules.  I speculate that that may increment the lower byte.
 
I've also signed up for github, so I might start adding some of this info in the infinitude wiki.
 
Just guessing, knowing that 2 communicating air purifiers exist.  Not sure of the other possibilities.
 
So 40 and 50 are what models on your system?
 
I think on some of the thermostats it is also possible to connect non-communicating units to legacy type outputs. 
 
Interesting to know the system doesn't need to be initiated by a 1F device.  It doesn't seem like a coincidence that F1 is broadcast and 1F is some type of master or first device, though not in a true master/slave bus style.
 
It would be interesting to see how zones & multiple devices are handled.  For example multiple remote temperature sensors would probably be the most common.  But it does seem that if you have multiple systems w/ separate ductwork you should be able to connect them all to the same bus & assign them to one another.
 
At power up, the system will proceed through its normal auto configuration process, finding and adapting itself to the indoor and outdoor units. All zones with Remote Room Sensors will automatically be learned. Zones with Smart Sensors will need to have zone numbers entered at each Smart Sensor.
 
The 485 bus is a half duplex, multi-master network.  There seems to be nothing built into the protocol to prevent two devices from talking at the same time, with the exception that the stat (2001) does most of the requests, and other devices generally respond to that request.
Sorry, some of the terminology I use is influenced by studying other protocols which probably just adds to my already confusing communication style. I do get that. Startup for me contains a bunch of collisions (evidenced by parser having to resync forward to get the next valid frame). Typical runtime has zero or very close to zero collisions on my network because it's all request/response traffic.

Oh, tangentially I have an sqlite file full of parsed frames now if that helps at all.
 
 
 It doesn't seem like a coincidence that F1 is broadcast and 1F is some type of master or first device, though not in a true master/slave bus style.
I thought so too. My instinct was it's some kind of "mask-y" address, but I haven't looked into it enough, and the protocol hasn't proved to be very complex so far. I'd still love to see a log from lleo to confirm this, but my rather unsubstantiated hypothesis is that 1F is a SAM device id. Does anyone else here have the touch interface and/or one that connects to the Internet?
 
@nebulous
 
Do you have a capture where you are reading/writing data from the web interface?  I thought you said you could edit setpoints from it.  If we are correct in our thinking, I would expect to see traffic from 1F to 20.  I just noticed that 1F is one less an 20, which puts it "next" to the stat in terms of addressing.  I think that is a stronger hypothesis than being related to broadcasts.
 
BTW, I'm exciting others are interested in this.  My wife has been unimpressed with the time and effort spent to "hack the furnace".  When I told her a few people on the internet were helping too, she still wasn't impressed.  Some people don't get it.
 
Dudes. I'm impressed. Thanks 3tonnes for telling me that things are hopping again. Now I'm inspired.
 
Ah I suppose h1F is h20-1.  Well who knows.
 
Anyway, known existing values:
 
Target Device, Operation, Record ID, Length(if known)

0E01,READ,003E01
0E01,READ,003E08
0E01,READ,003E0A
2001,READ,00030A
2101,READ,00041E
2201,READ,00041E
2301,READ,00041E
2401,READ,00041E
2501,READ,00041E
2601,READ,00041E
2701,READ,00041E
2801,READ,00041E
4001,READ,000104
4001,READ,000306
4001,READ,00030A
4001,READ,000402
4001,READ,000403
4001,READ,000409
4201,READ,000104
4201,READ,000302,12
4201,READ,000306,10
4201,READ,00030A,14
4201,READ,00030D,7
4201,READ,00030E,26
4201,READ,000310
4201,READ,000311
4201,READ,000316,15
4201,READ,00031B,1
4201,READ,000402,26
4201,READ,000403,19
4201,READ,000404,34
4201,READ,000405,9
4201,READ,000407,1
4201,READ,00040B
4201,READ,00040C
4201,READ,00040F
4201,READ,000410
4201,READ,000411
4201,READ,000413
4201,READ,000414,22
4201,READ,00041B
4201,WRITE,000305,12
4201,WRITE,000307,4
5001,READ,000104
5001,READ,000304,24
5001,READ,00030A,14
5001,READ,00030D,7
5001,READ,00030E
5001,READ,000311,24
5001,READ,000502,5
5001,READ,000504
5001,READ,003E01,13
5001,READ,003E02,1
5001,READ,003E03,1
5001,READ,003E04,1
5001,READ,003E0A,3
5001,READ,003E0C,15
5001,READ,003E0D,14
5001,READ,003E0E,10
5001,WRITE,00050F,4
5001,WRITE,000510,4
5001,WRITE,003E02,1
5001,WRITE,003E03,1
5001,WRITE,003E0A,3
5101,READ,000104
5101,READ,00030A
5101,READ,00061F
6001,READ,000302
6001,READ,003405
6101,READ,000302
6101,READ,003405
8001,READ,003405
F1F1,WRITE,000202,3
F1F1,WRITE,000203,3
F1F1,WRITE,000305,12
F1F1,WRITE,000605,7
F1F1,WRITE,003E02,1

 
Comparison of what actions are initiated by the two active devices:
 
Code:
1F01,4001,READ,00030A	2001,4001,READ,00030A
			2001,4001,READ,000402
			2001,4001,READ,000403
			2001,4001,READ,000409
1F01,4201,READ,000104	2001,4201,READ,000104
			2001,4201,READ,000302
			2001,4201,READ,000306
1F01,4201,READ,00030A	2001,4201,READ,00030A
1F01,4201,READ,00030D	2001,4201,READ,00030D
			2001,4201,READ,00030E
			2001,4201,READ,000310
			2001,4201,READ,000311
			2001,4201,READ,000316
1F01,4201,READ,00031B	2001,4201,READ,00031B
			2001,4201,READ,000402
1F01,4201,READ,000403	2001,4201,READ,000403
1F01,4201,READ,000404	2001,4201,READ,000404
			2001,4201,READ,000405
			2001,4201,READ,000407
1F01,4201,READ,00040B	2001,4201,READ,00040B
1F01,4201,READ,00040C	2001,4201,READ,00040C
1F01,4201,READ,00040F	2001,4201,READ,00040F
1F01,4201,READ,000410	2001,4201,READ,000410
1F01,4201,READ,000411	2001,4201,READ,000411
1F01,4201,READ,000413   2001,4201,READ,000413
1F01,4201,READ,000414	2001,4201,READ,000414
			2001,4201,READ,00041B
			2001,4201,WRITE,000305
			2001,4201,WRITE,000307
1F01,5001,READ,000104	2001,5001,READ,000104
			2001,5001,READ,000304
1F01,5001,READ,00030A	2001,5001,READ,00030A
			2001,5001,READ,00030D
			2001,5001,READ,00030E
			2001,5001,READ,000311
			2001,5001,READ,000502
			2001,5001,READ,000504
			2001,5001,READ,003E01
			2001,5001,READ,003E02
			2001,5001,READ,003E03
			2001,5001,READ,003E04
			2001,5001,READ,003E0A
			2001,5001,READ,003E0C
			2001,5001,READ,003E0D
			2001,5001,READ,003E0E
			2001,5001,WRITE,00050F
			2001,5001,WRITE,000510
			2001,5001,WRITE,003E02
			2001,5001,WRITE,003E03
			2001,5001,WRITE,003E0A
1F01,5101,READ,000104	2001,5101,READ,000104
1F01,5101,READ,00030A	2001,5101,READ,00030A
1F01,5101,READ,00061F	2001,5101,READ,00061F
1F01,6001,READ,000302	2001,6001,READ,000302
1F01,6001,READ,003405	2001,6001,READ,003405
1F01,6101,READ,000302	2001,6101,READ,000302
1F01,6101,READ,003405	2001,6101,READ,003405
1F01,8001,READ,003405	2001,8001,READ,003405
			2001,F1F1,WRITE,000202
			2001,F1F1,WRITE,000203 
1F01,F1F1,WRITE,000305	
1F01,F1F1,WRITE,000605	
1F01,F1F1,WRITE,003E02
 
Will devices such as 4001,5001 only respond to certain addresses?  Anyone written a tool to brute force dump all possible "table headers"?
 
Back
Top