diff --git a/README.md b/README.md
index e034336..740ff63 100644
--- a/README.md
+++ b/README.md
@@ -23,9 +23,15 @@ vacuum=[robot id]@126.ecorobot.net
I got these values by using xmppeek to do a man-in-the-middle attack on
the android app. I suspect that the Android app re-keys the connection
on a regular basis, as the secret was changing regularly up until I
-cleared the Android app's data from my phone. It should be possible to
-give this tool a command something like "login" that would create the config
-file automatically.
+cleared the Android app's data from my phone.
+
+If you're curious about the protocol, I have [a very rough
+doc](protocol.md) started. I'll happily accept pull requests for it.
+
+Why the project name? Well, a) it's ridiculous that I needed to MITM
+my own vacuum. This is not the future I signed up for. There should
+be a nice, tidy RESTful API. That would be easy enough to make. And b),
+it's a vacuum.
## To Do
diff --git a/log_clean.py b/log_clean.py
new file mode 100644
index 0000000..7230b79
--- /dev/null
+++ b/log_clean.py
@@ -0,0 +1,63 @@
+import sys
+import re
+
+# a script to take an xmpppeek log of a Ecovacs app session with a Deebot N79 and strip out some of the nonsense,
+# including any private identifiers
+
+source_ip = None
+userid = None
+resourceid = None
+robotid = None
+auth_glob = None
+
+for line in sys.stdin:
+ # remove the garbage
+ line = line.rstrip()
+ line = re.sub("\[\\d{4}-\\d{2}-\\d{2} ", '', line)
+ line = re.sub("\.\\d{6}-\\d{2}:\\d{2}\] \[", ' ', line)
+ line = re.sub("]$", ' ', line)
+ line = re.sub("\(([SC])2[SC]\) [.0-9]+:\\d+ -> [.0-9]+:\d+\]", '\\1', line)
+ line = re.sub("\}\}\}", '', line)
+ line = re.sub("\{\{\{", '', line)
+
+ # find the private bits and remove them
+ if not source_ip:
+ match = re.search('Client connect from ([.0-9]+)', line)
+ if match:
+ source_ip = match.group(1)
+ if not userid:
+ match = re.search('(20\d{6}[0-9a-f]{13})@ecouser.net/([0-9a-f]{8})', line)
+ if match:
+ userid = match.group(1)
+ resourceid = match.group(2)
+ if not robotid:
+ match = re.search('(E\d{8,})@126.ecorobot.net/atom', line)
+ if match:
+ robotid = match.group(1)
+ if not auth_glob:
+ match = re.search('([-A-Za-z0-9+/=]+)', line)
+ if match:
+ auth_glob = match.group(1)
+ if source_ip:
+ line = re.sub(source_ip, 'SOURCEIP', line)
+ if userid:
+ line = re.sub(userid, 'USERID', line)
+ if resourceid:
+ line = re.sub(resourceid, 'RESOURCEID', line)
+ if robotid:
+ line = re.sub(robotid, 'ROBOTID', line)
+ if auth_glob:
+ line = re.sub(auth_glob, 'AUTHGLOB', line)
+
+ # translate client commmands
+
+ line = re.sub('()', 'id=\\1 command=\\2', line)
+
+ # translate server responses
+
+ line = re.sub('', 'id=\\1 result =empty', line)
+ line = re.sub('', 'id=\\1 id=\\2 result=\\3', line)
+ line = re.sub('(', 'id=\\1 response=\\2', line)
+
+ print(line)
+
diff --git a/protocol.md b/protocol.md
index c724690..64b68e9 100644
--- a/protocol.md
+++ b/protocol.md
@@ -1,3 +1,8 @@
+The core protocol is XMPP. The Android app establishes a connection to an XMPP server and logs in using
+a secret that the android app appears to change from time to time. It then sends XMPP IQ commands. It describes
+them as queries, but they all contain "ctl" elements that appear to be commands. Here are a couple of full
+examples with the private information removed:
+
A clean command:
```
@@ -8,4 +13,59 @@ A clean command:
A charge command:
```
-```
\ No newline at end of file
+```
+
+Focusing on the core ctl elements, this is a sampling of commands seen on the wire after punching all the app buttons:
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+It appears that it adds an extra id when it cares to receive a specific response. This is a little odd in that
+the iq blocks already contain ids, but perhaps one is more a server id and the other is used by the robot itself.
+
+Here are some assorted responses from that session:
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+I don't totally get the relationship between the duplicate-ish items here, like the various clean reports,
+or the charge type differences, but I'll try to come back after rummaging through the logs further.