hotzenklotz / picobrew-server

A reverse engineered server for the proprietary PicoBrew Zymatic protocol

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Resurection

colinluthier opened this issue · comments

I am interested in resurrecting this project. Any input would be welcomed.

@colinluthier I am happy to hear it. What are your plans? I could add you as a collaborator if that helps.

Hey! I am willing to help either. However please note that I'm not a developer myself. But I have some coding experience.

As far as I can see there are a few things one could do:

Current Version / Testing / Maintenance

  • Test if the current version of PicoBrew server still works with Zymatic machines
  • Make it easier to do spoofing of www.picobrew.com
  • Test current version of BeerXML recipes from picobrew.com for compatibility

New Features:

  • Port/Extend the server for the other PicoBrew machines
    • record/document HTTP communication of other/newer machine with Wireshark
    • this might not be feasible for all newer PicoBrew machines
    • newer machines use barcodes for Picopacks. As far as I can tell there is no way to fake them/circumvent them
    • the new "brew your own recipes" mode might be able to use this code
  • Extend UI
    • many things are possible :-)
  • Upgrade to Python3

I have a Pico C, PicoFerm and a PicoStill. I have captured various sessions using WireShark. The last time I turned on my Pico C, it did a firmware upgrade. The response to the request was in test/plain, but I don't know how it can be decode. I don't think it is base64 encoded. It starts with #155864.0,72168d866990f8a46228df7113cb82ce|f44e0320717a0120697a01206b7a01206f7a01206d7a01206f7a01200...

Anyway, I am a software developer and I would be happy to help.

Here's everything I've gathered so far on the Pico C / Picostill. Hope it helps!

The Picostill was relatively easy to connect to. Once it's powered on it will emit an AP "Picostill_..." with a password of 12345678. Once connected go to 192.168.4.1 and enter in your network credentials and the Picostill with join your network. After that you can either enter in the Picostill IP address and be brought to the web UI and turn the pump/sensors on, or send GET requests to the following endpoints:

/sensors : turns the sensors on
/fanon : fan on
/fanoff : fan off
/start : turns the pump on
/end : turns the pump off
/stillstate : state of the still
/data : comma separated data stream in the following format "#coil_inlet_temp, coil_outlet_temp, pot_temp, ambient_temp, PSI, 1, 1, 1, None#"

The data updates every 2 seconds (confirmed by listening on the serial pins) once the /sensors route has been requested.

The Pico itself is much more complicated. The DNS spoofing still works (thanks @hotzenklotz !).
When the Pico joins the network it will send a request to '/API/pico/register?uid=yourUIDhere'
Then after it receives the proper response it will send another request to '/API/pico/picoChangeState?picoUID=yourUIDhere&state=2'
Unfortunately this is where I'm stuck, as I discovered the third endpoint:
'/API/pico/error?uid=yourUIDhere&code=4&rfid=

I read these routes from the serial pins and confirmed they were hitting the spoofed DNS.
I haven't looked at the Picoferm yet, but I'll definitely take a look.

I installed today and tried to take it through a run through on OSX and Windows. In both cases, when I loaded the xml, it bit the dust. I can see that the xml uploaded, so it seems to fail at verification. Might be a changed in the export of the recipe on the Piocbrew site, as I grabbed the file today.

I had the same experience firing this up today. It seems to throw a 500 when invoking the validate after upload (which is successful; the recipe ends up in the recipe folder) or any template page, like recipes.html. The results are the same in the heroku image.

  • Running on http://0.0.0.0:5000/
    127.0.0.1 - - [15/Apr/2020 23:44:25] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [15/Apr/2020 23:44:25] "GET /static/img/favicon-32x32.png HTTP/1.1" 200 -
    127.0.0.1 - - [15/Apr/2020 23:44:31] "POST /upload HTTP/1.1" 302 -
    127.0.0.1 - - [15/Apr/2020 23:44:31] "GET /validate HTTP/1.1" 500 -
    #me just manually pointing to /recipes
    127.0.0.1 - - [15/Apr/2020 23:44:58] "GET /recipes HTTP/1.1" 500 -

@vfrdirk @fotoapparat Thanks for letting me now. Do you mind sharing your recipes to see what is going on?

I used a recipe of my own, that recipe with a <PROGRAM></PROGRAM> tag set encapsulating the actual instruction set (as seen in the Wiki FAQ), a sample recipe I found in your pybeerxml repo, and a fake xml file I made consisting only of <FART>FARTFART</FART> and the results were exactly the same each and every time. No parsing error or anything like that, just instant 500 error.

It has me thinking that maybe one of the dependency programs has changed in the intervening years and no longer responds to your code in the same way, but I'm an API and DevOps automation guy and not a Python/Software guy.

EDIT: Never mind, I see the dependencies are pinned at the version originally working.

I'll have a look at the system tomorrow and see what I needs updating / fixing.

Thanks! You're the obvious expert here, but I've been fiddling with it as an exercise to learn more Python. A colleague suggested a logging module, so I added 'import logging' to server.py and was suddenly greeted with an exception error after uploading a (real) recipe file. Maybe this will help. I really appreciate you taking a look. --Dirk

ERROR:main:Exception on /validate [GET]
Traceback (most recent call last):
File "/home/dirk/.local/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/dirk/.local/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/dirk/.local/lib/python2.7/site-packages/flask_cors.py", line 272, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/dirk/.local/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/dirk/.local/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/dirk/.local/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/dirk/picobrew-server/blueprints/frontend.py", line 58, in validate
recipe = get_recipe(file)[0]
File "/home/dirk/picobrew-server/blueprints/frontend.py", line 33, in get_recipe
return parser.parse(file)
File "/home/dirk/picobrew-server/beerxml/picobrew_parser.py", line 11, in parse
recipes = super(PicoBrewParser, self).parse(xml_file)
File "/home/dirk/.local/lib/python2.7/site-packages/pybeerxml/parser.py", line 95, in parse
self.nodes_to_object(mash_node, mash)
File "/home/dirk/.local/lib/python2.7/site-packages/pybeerxml/parser.py", line 18, in nodes_to_object
assert(len(list(node)) > 1)
AssertionError

I looked into it. Looks like PicoBrew made some changes to the BeerXML files. Earlier versions had a PROGRAM tag outlining the heating/timing steps required for the machine operation. This tag was renamed to ZYMATIC in all the recipes that I could find. (Not sure if this is machine dependent or equal for all PicoBrew machines):

<ZYMATIC>
      <MASH_TEMP>67</MASH_TEMP>
      <MASH_TIME>120</MASH_TIME>
      <BOIL_TEMP>97</BOIL_TEMP>
      <STEP>
        <NAME>Heat to Dough In</NAME>
        <TEMP>39</TEMP>
        <TIME>0</TIME>
        <LOCATION>PassThrough</LOCATION>
        <DRAIN>0</DRAIN>
      </STEP>
...

I also update the program to Python 3, updated all dependencies and fixed some bugs. The changes are still on separate branch: py3 See this pull request: #3
@vfrdirk @fotoapparat Do you mind testing this version?

I also created a proper API documentation on Postman:
https://documenter.getpostman.com/view/234053/Szf54VEX?version=93783194-dcee-4bb2-8f19-f25ab6c6d411

I have only done API testing on my laptop yet. I am hoping to do a proper system test with my Zymatic machine over the weekend. (Perhaps see if there are any differences with a more up-to.date firmware)

I've been looking at it since I saw the PR come through. I'm having a few problems with all the Python 3 stuff, since it's new to me. There were some bizarre errors that were popping up for me involving what appeared to be typos in some of the statements. I cleared those up and was able to get the server up on the py3 branch of code, but still getting 500 errors. I'm going to make a new issue and I'll paste the stacktrace.

Many thanks for the work on the updated server! I made some edits to the Wiki pages to clean up some formatting, update a couple of missing bits of information and update for the Python 3 stuff. I think it's all accurate, but won't be offended if you revert. The Readme and the Wiki claim Python 3.6 and 3.7 are required, so I didn't change that since I'm not sure which is accurate.

I'll see if there's an easier way to do the DNS spoofing. I use a Pi-Hole at home, and thought that would be a way to redirect a url, but that's not panning out the way I had hoped.

@vfrdirk Thanks. Feel free to open a pull request with your changes, so that I can have a look at them. It is always good to have the Readme/wiki up-to-date.

You need Python 3.6 or above.

I'm willing to help here too. I'm a Zymatic owner. One question for @hotzenklotz -- the firmware version you list in the README is 1.18. My machine has 1.1.14 and as far as I can tell, that's the newest one available. Is there an undocumented firmware that I'm missing?

Here is, sadly, a very good reason to reverse engineer the server:

https://thespoon.tech/rest-in-peace-picobrew/?fbclid=IwAR3ZdbTnu2PDJ0yLIwaSxT7NKqXhs-_rb_2bbJ92ZBD5IqrsgsyWBxW2ugA

I own a Pico C, PicoStill and a PicoFerm. I am also a software developer and willing to help.

Had anyone captured the Z protocol? Can you give me steps. I am better at writing software than this IT type stuff

commented

I am 100% on board with helping this succeed! I have a C, Still, and Ferm I would love to see still work after the doors close..

I do some captures with a Z in 2-3 weeks, but I won't have any grain, so I would just have to run it empty if that's ok.

@shettich I think you should be fine as long as you don't run it dry - just make sure to put water in your keg as you would a normal recipe. I've done the same on a Zymatic, but with the addition of citric acid for descaling - and that was at Picobrew's instruction.

I've installed Wireshark, but can't figure out how to filter out the picobrew communication. I have a Pico Pro and like to save the communication. Thanks.

This is a little outside my area of expertise, so I could be doing something wrong, but I set up my laptop between the Z and the rest of the network so I could sniff everything going by. As far as I can tell, all communication between the Z and Picobrew is SSL encrypted, so I couldn't really see anything at all.

Well, if true, that sucks. The next step would be to MiTM it and see if they fail to validate the server cert (if that's true, you could have the MiTM proxy record the session). If they do validate the cert, uh, it's either wait to see if they will release the API, or try to hack the firmware :(

I haven't tried the MitM approach yet - if you've got a set up to do that, that'd be awesome.

In the mean time, I was afraid we might have to go the latter route and that route doesn't look trivial either. I popped the cover off of my Z to see if there were any hidden easy-to-access USB connectors inside and it doesn't look like it. It looks like it's still an Arduino chip (esp32-wroom-32d), it's on a custom board. Unlike the USB connector on the Zymatic, there's no immediately obvious way to just plug in a cable and instantly access the Arduino. I did notice there is a jumper block with pins on the board labeled "TX", "RX", and "GND", so all hope may not be lost.

I am willing to develop an instruction manual to help users setup their computers to work locally with their machines. I have both Mac and PC. Just need guidance from the experts here. Just let me know.

mitmproxy appears to work for the Z - I'll probably try to capture some flows today.

mitmproxy appears to work for the Z - I'll probably try to capture some flows today.

That's great news. Does that mean the Z isn't validating the SSL cert? Can you give me an idea of how to reproduce so I can assist in grabbing traffic?

@bendavis It does not appear to validate the SSL cert. Reproducing should be pretty easy - I just installed mitmproxy on my MacbookPro. I connected the laptop my network via ethernet and used the internet sharing feature to create a wifi network, and then use packet filtering to direct all SSL traffic through mitmproxy. It's useful to use the mitmweb or mitmproxy tool to verify things are working, but you'll probably want to use mitmdump when you start doing actual captures. The documentation on the mitmproxy site is pretty good so that's probably the best place to start.

One of my temperature sensors in the Z apparently stopped working correctly a week ago, so I'm not sure I can get any captures that require heating the water because the Z freaks out that the temperature difference of the heating element is 50 degrees lower than the temperatures recorded by the other sensors. No idea how I'll get this sensor replaced at this point.

Another thing someone ought to capture is a firmware download. I discovered that if you press in the knob and turn on the Picobrew, it launches a service menu. One of the menus had a Factory Reset option. That option will trigger resetting the network settings and also a firmware download.

We should definitely get these captures ASAP though, a colleague pointed me at an Auction where someone is liquidating everything in the Picobrew warehouse, so this doesn't give me confidence that whoever bought Picobrew intends to continue operating the services.

One question for @hotzenklotz -- the firmware version you list in the README is 1.18. My machine has 1.1.14 and as far as I can tell, that's the newest one available. Is there an undocumented firmware that I'm missing?

Yes, I meant 1.1.8. Will correct that.

mitmproxy appears to work for the Z - I'll probably try to capture some flows today.
That sounds quite interesting. Thanks for pointing that out. Looking forward to hearing more about this.

@everyone I am happy to add more contributors to the GitHub project. Let me know if you interested and want to help out.

Does anyone have any contacts to employees of the Picobrew engineering team? Perhaps, the could leak some documentation/firmware etc.

I am interested in helping out by testing the uploads to my Zymatic.
I was able to get the cleaning recipe to send to the Zymatic. I am just not able to send any of my PicoBrew recipes.

@hotzenklotz I thought I read in a news article that all support staff got let go last week and I don't really know the state of the remaining staff. I'm not sure how much people will feel like being contacted right now.

It seems as though the temperature sensor for the the heat element in the Pico S is interchangeable with the Z so I have a working Z again now. I'm going to try to capture some flows again today.

@Blackjackbuyer Are you referring to the source or the binaries of the firmware?

I created a video to explain how to capture PicoBrew devices network traffic using Wireshark on a Mac. This method can be used for devices that use unencrypted network traffic like the Pico C:
https://youtu.be/tuVkTUcV6Dw

Thanks @blucey, I got a vm capturing a cleaning session right now on my Z using mitmproxy and arpspoof.

@Blackjackbuyer which firmware bins do you have? For the Z? If so I'd love to disassemble those suckers.

There's a private group of hackers/programmers/etc all trying to do this on FB https://www.facebook.com/groups/PicoBrewingTaskForce. Even some people trying to figure out a replacement part path.

commented

@hotzenklotz - Tom, I emailed you a few years ago about the Pico.. I pushed my repo to GitHub that gives live graphing/session history/manual recipe creating.. feel free to use any of that:
https://github.com/chiefwigms/picobrew_pico

Hi guys, FB was used as a tool to reach out. Everything is stored on shared spaces and available to all. Teams for hw, sw, recipes etc etc. Collaboration via Slack. Weekly meetings on Zoom.
The aim is to secure a future life for our machines, with community servers up and running, supporting the entire range of PB hardware.
Any chance you may want to take part in this?

Hi guys, FB was used as a tool to reach out. Everything is stored on shared spaces and available to all. Teams for hw, sw, recipes etc etc. Collaboration via Slack. Weekly meetings on Zoom.
The aim is to secure a future life for our machines, with community servers up and running, supporting the entire range of PB hardware.
Any chance you may want to take part in this?

I'd like to. :)

Hi guys, FB was used as a tool to reach out. Everything is stored on shared spaces and available to all. Teams for hw, sw, recipes etc etc. Collaboration via Slack. Weekly meetings on Zoom.
The aim is to secure a future life for our machines, with community servers up and running, supporting the entire range of PB hardware.
Any chance you may want to take part in this?

I asked to join a few hrs ago

Hi guys, FB was used as a tool to reach out. Everything is stored on shared spaces and available to all. Teams for hw, sw, recipes etc etc. Collaboration via Slack. Weekly meetings on Zoom.
The aim is to secure a future life for our machines, with community servers up and running, supporting the entire range of PB hardware.
Any chance you may want to take part in this?

@robhercz I put in a request to join the Facebook Group yesterday.

@TomKriek99 Hi Tom, For what it’s worth this is my setup.
Using Win10 PC.
1.
I installed python 3.7.7 with win x86 installer.
Installed custom and kept all defaults, with the following exceptions:
-Install for all users
-update the path.(essentially simplify running from cmd window)

Open cmd as Administrator and from C:\PicoBrew\picobrew-server-master>
pip install -r requirements.txt

Updated server.py last line to:
app.run(host="0.0.0.0", port=80)
Run server with:
python server.py

I changed directly to port 80 as Zymatic will only connect via http port 80.

I added the following to my host file:
192.168.137.1 picobrew.com
I enabled ICS to the network interface, the Zymatic was connected to. This will provide DHCP to the Zymatic (and assigns the address 192.168.137.1 to the NIC). If you ping picobrew.com it will only resolve to 192.168.137.1 after the NIC is up( when the Zymatic is on).

Not sure what the most straightforward way should be. I think a better option would be, to use a simple home router between the Zymatic and the windows PC. This would provide DHCP and not rely on the Zymatic being on.

I opened a few new issues to discuss/focus on certain aspects in more detail:

Feel free to continue the conversation in these threads if appropriate.

Thinking a bit longer term. A possible way to revive the various devices for non-tech users would be to build:

A) a cheap arduino based dongle with ethernet and bluetooth. It could run the server software, and accept commands from...

B) a simple android/ios app to upload beerxml files to the dongle

It would pretty much convert them from ethernet/wifi internet devices to local bluetooth devices.

Danyou-thanks. I have the server up, will try the network tomorrow.

When I run "Flask run --Port 80...…" I get a warning this is a development server....unable to find flask application, use Flask_app=flask.app:name. So unable to test upload for now.

@TomKriek99 The startup instructions and installation have changed in the latest release to make it more streamlined. Here are the instructions again:

// Download and install
pip install picobrew_server

// Start the server in production mode on port 80
// Windows 
set FLASK_APP=picobrew_server
flask run --port 80 --host 0.0.0.0

// OSX / Linux
export FLASK_APP=picobrew_server 
flask run --port 80 --host 0.0.0.0

Here is a detailed set of installation instructions. I am not able to upload them, so however you wish to handle.

Picobrew Zymatic Detailed Server Installation Instructions.pdf