Skip to content

Commit

Permalink
Merge pull request #12 from hotzenklotz/pypi
Browse files Browse the repository at this point in the history
Bundle Server on PyPi
  • Loading branch information
hotzenklotz authored May 6, 2020
2 parents cd0dca6 + 4ffbebb commit 210ee7f
Show file tree
Hide file tree
Showing 72 changed files with 656 additions and 50 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/publish_pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish to PyPI

on:
release:
types:
- created

jobs:
publish:
runs-on: ubuntu-18.04

steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: 3.7
architecture: 'x64' # (x64 or x86)

- name: Setup venv
run: python -m venv ~/.venv

- name: Publish to PyPI
run: |
source ~/.venv/bin/activate
pip install poetry
poetry install
poetry publish --build --username ${{ secrets.PYPI_USERNAME }} --password ${{ secrets.PYPI_PASSWORD }}
14 changes: 8 additions & 6 deletions .github/workflows/test_lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ name: Test and Lint
on: [push]

jobs:
build_test_deploy:
build_test:
runs-on: ubuntu-18.04
strategy:
max-parallel: 4
matrix:
python-version: [3.6, 3.7]
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v1
Expand All @@ -24,20 +24,22 @@ jobs:
- name: Install dependencies
run: |
source ~/.venv/bin/activate
pip install -r requirements-dev.txt
pip install poetry
poetry install
- name: Check code formatting
run: |
source ~/.venv/bin/activate
python -m black .
python -m black picobrew_server
- name: Lint code
run: |
source ~/.venv/bin/activate
./lint.sh
python -m pylint picobrew_server
- name: Check typing
run: |
source ~/.venv/bin/activate
python -m mypy .
python -m mypy picobrew_server
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ never-returning-functions=sys.exit

# Format style used to check logging format string. `old` means using %
# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings.
logging-format-style=fstr
logging-format-style=old

# Logging modules to check that the string format arguments are in logging
# function parameter format.
Expand Down
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: gunicorn server:app
web: gunicorn server:app
53 changes: 45 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
# picobrew-server
<img src="https://img.shields.io/pypi/v/picobrew_server">
<img src="https://img.shields.io/pypi/pyversions/picobrew_server">
<img src="https://img.shields.io/github/workflow/status/hotzenklotz/picobrew-server/Test and Lint/master">


This project reverse-engineers a server for the proprietary PicoBrew protocol for use with the [PicoBrew Zymatic](http://www.picobrew.com/), a homebrewing machine. It is intended to provide an alternative to run the machine without a connection to the official servers at picobrew.com. Run your own server and sync your recipes offline.

# HTTP API
The PicoBrew Zymatic's built-in Ardunio uses an unencrypted HTTP communication protocol. All request are `GET` requests and are not authenticated. The following documentation is based on Firmware 1.1.8.

- [API Docs on Postman](https://documenter.getpostman.com/view/234053/Szf54VEX?version=latest)
- [API Docs on GitHub](https://github.com/hotzenklotz/picobrew-server/wiki/PicoBrew-API)
- [PicoBrew Zymatic API Docs on Postman](https://documenter.getpostman.com/view/234053/Szf54VEX?version=latest)
- [PicoBrew Zymatic API Docs on GitHub](https://github.com/hotzenklotz/picobrew-server/wiki/PicoBrew-API)

# Installation

- Install Python 3.7
1. Install Python 3.7 or above
2. In a terminal download, install and run the project:
```bash
// Download and install
pip install picobrew_server

```
// Install Python requirements
pip install -r requirements.txt
// Start the server in production mode on port 80

// Start the server
sudo python server.py
// 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
```

- Connect the PicoBrew machine to your computer and enable DNS spoofing. Re-route `www.picobrew.com` to your computer.
[More Details](https://github.com/hotzenklotz/picobrew-server/wiki/Install)

# Development

1. Install Python 3.7+ & [Poetry](https://python-poetry.org/):

```bash
pip install poetry
```

2. Install all dependecies:

```bash
poetry install

// Start the server on http://localhost:5000
FLASK_APP=picobrew_server flask run
```

3. Lint, Format, and Type Check changes:
```
pylint picobrew_server
black picobrew_server
mypy picobrew_server
```


# Demo
You can try out the admin UI for uploading your XML files in this [online demo](https://picobrew.herokuapp.com). Please note, this website is for showcasing only and you should deploy your own version.

Expand All @@ -50,6 +85,8 @@ ToDo
# Disclaimer
This software is provided "as is" and any expressed or implied warranties are disclaimed. This software submits recipes with temperature targets to your PicoBrew machine and will cause it to heat water. Any damage to your PicoBrew machine is at your own risk.

If the Zymatic faults and the screen goes blank, DON'T leave it powered on. The circulating pump will shut off and the heater stays on. A tube in the glycol loop may rupture.

# License

MIT @ Tom Herold
5 changes: 0 additions & 5 deletions lint.sh

This file was deleted.

7 changes: 1 addition & 6 deletions server.py → picobrew_server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# System imports
from flask_cors import CORS
from flask import Flask
from blueprints import frontend, picobrew_api, errors
from picobrew_server.blueprints import frontend, picobrew_api, errors

app = Flask(__name__)
CORS(app)
Expand All @@ -14,8 +14,3 @@
app.register_blueprint(frontend.frontend)
app.register_blueprint(errors.errors)
app.register_blueprint(picobrew_api.picobrew_api)

if __name__ == "__main__":

# Start the Flask app
app.run(host="0.0.0.0", port=5000)
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from pathlib import Path

from pybeerxml import Parser
from beerxml.picobrew_recipe import PicoBrewRecipe
from beerxml.picobrew_program_step import PicoBrewProgramStep
from picobrew_server.beerxml.picobrew_recipe import PicoBrewRecipe
from picobrew_server.beerxml.picobrew_program_step import PicoBrewProgramStep


class PicoBrewRecipeParser(Parser):
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Text, List
from pybeerxml import Recipe
from beerxml.picobrew_program_step import PicoBrewProgramStep
from picobrew_server.beerxml.picobrew_program_step import PicoBrewProgramStep


def get_hash(text: Text) -> Text:
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

from flask import Blueprint, request, flash, redirect, url_for, render_template, session
from werkzeug.utils import secure_filename
from beerxml.picobrew_parser import PicoBrewRecipeParser, PicoBrewRecipe
from picobrew_server.beerxml.picobrew_parser import PicoBrewRecipeParser, PicoBrewRecipe

from utils.constants import ALLOWED_FILE_EXTENSIONS
from picobrew_server.utils.constants import ALLOWED_FILE_EXTENSIONS

logger = logging.getLogger()
frontend = Blueprint("frontend", __name__)
Expand Down Expand Up @@ -44,7 +44,7 @@ def get_recipe(filename: Path) -> List[PicoBrewRecipe]:

# pylint: disable=broad-except
except Exception as error:
logger.error(f"Failed to parse recipe {filename}. {error}")
logger.error("Failed to parse recipe %s. %s", filename, error)
return []


Expand All @@ -56,7 +56,7 @@ def upload_recipe():

file_directory = Path("recipes")
file_directory.mkdir(exist_ok=True)

filename = file_directory.joinpath(secure_filename(file.filename))

if filename.suffix in ALLOWED_FILE_EXTENSIONS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from flask import Blueprint, request, abort
from webargs import fields
from webargs.flaskparser import use_kwargs, parser
from blueprints.frontend import get_recipes, get_recipe
from picobrew_server.blueprints.frontend import get_recipes, get_recipe

from utils.constants import SESSION_PATH, SYSTEM_USER
from picobrew_server.utils.constants import SESSION_PATH, SYSTEM_USER

picobrew_api = Blueprint("picobrew_api", __name__)
logger = logging.getLogger()
Expand Down Expand Up @@ -117,7 +117,7 @@ def create_new_session(recipe_id: Text, _args) -> Text:
json.dump(session_data, out_file, indent=2)

except IOError as error:
logger.error(f"Could create new session storage file. {error}")
logger.error("Could create new session storage file. %s", error)
return "##"

return "#{0}#".format(session_id)
Expand Down Expand Up @@ -162,7 +162,7 @@ def log_to_session(session_id: Text, args) -> Text:
json.dump(session, out_file, indent=2)

except IOError as error:
logging.error(f"Couldn't save heating log to file. {error}")
logging.error("Couldn't save heating log to file. %s", error)

return ""

Expand Down Expand Up @@ -193,7 +193,10 @@ def parse_session_recovery_request(session, code) -> Text:

except IOError as error:
logging.error(
f"Unable to resume session {session}. Recipe {recipe_file}. {error}"
"Unable to resume session %s. Recipe %s. %s",
error,
recipe_file,
session,
)
abort(500)

Expand All @@ -203,7 +206,7 @@ def parse_session_recovery_request(session, code) -> Text:

except IOError as error:
logging.error(
f"Unable to resume session {session}. Recipe {recipe_file}. {error}"
"Unable to resume session %s. Recipe %s. %s", error, recipe_file, session
)
abort(500)

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 210ee7f

Please sign in to comment.