| @@ -9,6 +9,11 @@ modules/plugins/* | |||||
| !modules/plugins/__init__.py | !modules/plugins/__init__.py | ||||
| *.pyc | *.pyc | ||||
| *.js | *.js | ||||
| *.css | |||||
| modules/ui/package.json | modules/ui/package.json | ||||
| modules/ui/.babelrc | modules/ui/.babelrc | ||||
| yarn.lock | |||||
| modules/ui/package-lock.json | |||||
| @@ -21,7 +21,7 @@ class MashStep(StepBase): | |||||
| def init(self): | def init(self): | ||||
| ''' | ''' | ||||
| Initialize Step. This method is called once at the beginning of the step | Initialize Step. This method is called once at the beginning of the step | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # set target tep | # set target tep | ||||
| self.set_target_temp(self.temp, self.kettle) | self.set_target_temp(self.temp, self.kettle) | ||||
| @@ -31,7 +31,7 @@ class MashStep(StepBase): | |||||
| ''' | ''' | ||||
| Custom Action which can be execute form the brewing dashboard. | Custom Action which can be execute form the brewing dashboard. | ||||
| All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface | All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| if self.is_timer_finished() is None: | if self.is_timer_finished() is None: | ||||
| self.start_timer(int(self.timer) * 60) | self.start_timer(int(self.timer) * 60) | ||||
| @@ -46,7 +46,7 @@ class MashStep(StepBase): | |||||
| def execute(self): | def execute(self): | ||||
| ''' | ''' | ||||
| This method is execute in an interval | This method is execute in an interval | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # Check if Target Temp is reached | # Check if Target Temp is reached | ||||
| @@ -57,6 +57,7 @@ class MashStep(StepBase): | |||||
| # Check if timer finished and go to next step | # Check if timer finished and go to next step | ||||
| if self.is_timer_finished() == True: | if self.is_timer_finished() == True: | ||||
| self.notify("Mash Step Completed!", "Starting the next step", timeout=None) | |||||
| self.next() | self.next() | ||||
| @@ -77,7 +78,7 @@ class MashInStep(StepBase): | |||||
| def init(self): | def init(self): | ||||
| ''' | ''' | ||||
| Initialize Step. This method is called once at the beginning of the step | Initialize Step. This method is called once at the beginning of the step | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # set target tep | # set target tep | ||||
| self.s = False | self.s = False | ||||
| @@ -88,7 +89,7 @@ class MashInStep(StepBase): | |||||
| def execute(self): | def execute(self): | ||||
| ''' | ''' | ||||
| This method is execute in an interval | This method is execute in an interval | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # Check if Target Temp is reached | # Check if Target Temp is reached | ||||
| @@ -169,7 +170,7 @@ class BoilStep(StepBase): | |||||
| def init(self): | def init(self): | ||||
| ''' | ''' | ||||
| Initialize Step. This method is called once at the beginning of the step | Initialize Step. This method is called once at the beginning of the step | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # set target tep | # set target tep | ||||
| self.set_target_temp(self.temp, self.kettle) | self.set_target_temp(self.temp, self.kettle) | ||||
| @@ -182,7 +183,7 @@ class BoilStep(StepBase): | |||||
| ''' | ''' | ||||
| Custom Action which can be execute form the brewing dashboard. | Custom Action which can be execute form the brewing dashboard. | ||||
| All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface | All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| if self.is_timer_finished() is None: | if self.is_timer_finished() is None: | ||||
| self.start_timer(int(self.timer) * 60) | self.start_timer(int(self.timer) * 60) | ||||
| @@ -205,7 +206,7 @@ class BoilStep(StepBase): | |||||
| def execute(self): | def execute(self): | ||||
| ''' | ''' | ||||
| This method is execute in an interval | This method is execute in an interval | ||||
| :return: | |||||
| :return: | |||||
| ''' | ''' | ||||
| # Check if Target Temp is reached | # Check if Target Temp is reached | ||||
| if self.get_kettle_temp(self.kettle) >= float(self.temp): | if self.get_kettle_temp(self.kettle) >= float(self.temp): | ||||
| @@ -218,4 +219,5 @@ class BoilStep(StepBase): | |||||
| self.check_hop_timer(3, self.hop_3) | self.check_hop_timer(3, self.hop_3) | ||||
| # Check if timer finished and go to next step | # Check if timer finished and go to next step | ||||
| if self.is_timer_finished() == True: | if self.is_timer_finished() == True: | ||||
| self.notify("Boil Step Completed!", "Starting the next step", timeout=None) | |||||
| self.next() | self.next() | ||||
| @@ -9,7 +9,7 @@ except Exception as e: | |||||
| class Buzzer(object): | class Buzzer(object): | ||||
| sound = ["H", 0.1, "L"] | |||||
| sound = ["H", 0.1, "L", 0.1, "H", 0.1, "L", 0.1, "H", 0.1, "L"] | |||||
| def __init__(self, gpio): | def __init__(self, gpio): | ||||
| try: | try: | ||||
| cbpi.app.logger.info("INIT BUZZER NOW GPIO%s" % gpio) | cbpi.app.logger.info("INIT BUZZER NOW GPIO%s" % gpio) | ||||
| @@ -74,6 +74,14 @@ class ControllerBase(object): | |||||
| class KettleController(ControllerBase, ActorController, SensorController): | class KettleController(ControllerBase, ActorController, SensorController): | ||||
| @staticmethod | |||||
| def chart(kettle): | |||||
| result = [] | |||||
| result.append({"name": "Temp", "data_type": "sensor", "data_id": kettle.sensor}) | |||||
| result.append({"name": "Target Temp", "data_type": "kettle", "data_id": kettle.id}) | |||||
| return result | |||||
| def __init__(self, *args, **kwds): | def __init__(self, *args, **kwds): | ||||
| ControllerBase.__init__(self, *args, **kwds) | ControllerBase.__init__(self, *args, **kwds) | ||||
| self.kettle_id = kwds.get("kettle_id") | self.kettle_id = kwds.get("kettle_id") | ||||
| @@ -107,6 +115,13 @@ class KettleController(ControllerBase, ActorController, SensorController): | |||||
| class FermenterController(ControllerBase, ActorController, SensorController): | class FermenterController(ControllerBase, ActorController, SensorController): | ||||
| @staticmethod | |||||
| def chart(fermenter): | |||||
| result = [] | |||||
| result.append({"name": "Temp", "data_type": "sensor", "data_id": fermenter.sensor}) | |||||
| result.append({"name": "Target Temp", "data_type": "fermenter", "data_id": fermenter.id}) | |||||
| return result | |||||
| def __init__(self, *args, **kwds): | def __init__(self, *args, **kwds): | ||||
| ControllerBase.__init__(self, *args, **kwds) | ControllerBase.__init__(self, *args, **kwds) | ||||
| self.fermenter_id = kwds.get("fermenter_id") | self.fermenter_id = kwds.get("fermenter_id") | ||||
| @@ -65,6 +65,8 @@ class LogView(FlaskView): | |||||
| pass | pass | ||||
| return array | return array | ||||
| def convert_chart_data_to_json(self, chart_data): | |||||
| return {"name": chart_data["name"], "data": self.read_log_as_json(chart_data["data_type"], chart_data["data_id"])} | |||||
| @route('/<t>/<int:id>', methods=["POST"]) | @route('/<t>/<int:id>', methods=["POST"]) | ||||
| def get_logs_as_json(self, t, id): | def get_logs_as_json(self, t, id): | ||||
| @@ -76,13 +78,12 @@ class LogView(FlaskView): | |||||
| if t == "k": | if t == "k": | ||||
| kettle = cbpi.cache.get("kettle").get(id) | kettle = cbpi.cache.get("kettle").get(id) | ||||
| result.append({"name": "Temp", "data": self.read_log_as_json("sensor", kettle.sensor)}) | |||||
| result.append({"name": "Target Temp", "data": self.read_log_as_json("kettle", kettle.id)}) | |||||
| result = map(self.convert_chart_data_to_json, cbpi.get_controller(kettle.logic).get("class").chart(kettle)) | |||||
| if t == "f": | if t == "f": | ||||
| fermenter = cbpi.cache.get("fermenter").get(id) | fermenter = cbpi.cache.get("fermenter").get(id) | ||||
| result.append({"name": "Temp", "data": self.read_log_as_json("sensor", fermenter.sensor)}) | |||||
| result.append({"name": "Target Temp", "data": self.read_log_as_json("fermenter", fermenter.id)}) | |||||
| result = map(self.convert_chart_data_to_json, cbpi.get_fermentation_controller(fermenter.logic).get("class").chart(fermenter)) | |||||
| return json.dumps(result) | return json.dumps(result) | ||||
| @route('/download/<file>') | @route('/download/<file>') | ||||
| @@ -1,5 +1,6 @@ | |||||
| from flask import Blueprint, render_template, request | |||||
| from modules import cbpi | |||||
| from flask import Blueprint | |||||
| from modules import cbpi | |||||
| react = Blueprint('react', __name__, template_folder='templates', static_folder='static') | react = Blueprint('react', __name__, template_folder='templates', static_folder='static') | ||||
| @@ -1,6 +1,3 @@ | |||||
| .App { | |||||
| } | |||||
| .container { | .container { | ||||
| padding-right: 5px; | padding-right: 5px; | ||||
| @@ -10,7 +7,27 @@ | |||||
| } | } | ||||
| .container-fluid { | .container-fluid { | ||||
| padding-right: 5px; | |||||
| padding-left: 5px; | |||||
| padding-right: 5px; | |||||
| padding-left: 5px; | |||||
| } | } | ||||
| .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { | |||||
| position: relative; | |||||
| min-height: 1px; | |||||
| padding-right: 8px; | |||||
| padding-left: 8px; | |||||
| } | |||||
| .panel-heading { | |||||
| padding: 5px 5px; | |||||
| } | |||||
| .panel-footer { | |||||
| padding: 2px 2px; | |||||
| } | |||||
| .modal-footer { | |||||
| padding: 5px; | |||||
| } | |||||
| @@ -1,5 +1,5 @@ | |||||
| body { | body { | ||||
| margin: 0; | |||||
| padding: 0; | |||||
| font-family: sans-serif; | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| font-family: sans-serif; | |||||
| } | } | ||||
| @@ -10,67 +10,12 @@ | |||||
| <link rel="stylesheet" href="static/bootstrap.dark.css"> | <link rel="stylesheet" href="static/bootstrap.dark.css"> | ||||
| <style> | |||||
| .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { | |||||
| position: relative; | |||||
| min-height: 1px; | |||||
| padding-right: 8px; | |||||
| padding-left: 8px; | |||||
| } | |||||
| .panel-heading { | |||||
| padding: 5px 5px; | |||||
| } | |||||
| .panel-footer { | |||||
| padding: 2px 2px; | |||||
| } | |||||
| .modal-footer { | |||||
| padding: 5px; | |||||
| } | |||||
| .row { | |||||
| display: -webkit-box; | |||||
| display: -webkit-flex; | |||||
| display: -ms-flexbox; | |||||
| display: flex !important; | |||||
| flex-wrap: wrap; | |||||
| } | |||||
| .row > [class*='col-'] { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| } | |||||
| /* Einschränken des sichtbaren Ausschnitts */ | |||||
| </style> | |||||
| <title>CraftBeerPi 3.0</title> | <title>CraftBeerPi 3.0</title> | ||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| <div id="root" ></div> | <div id="root" ></div> | ||||
| <script src="static/bundle.js" type="text/javascript"></script> | <script src="static/bundle.js" type="text/javascript"></script> | ||||
| <!-- | |||||
| This HTML file is a template. | |||||
| If you open it directly in the browser, you will see an empty page. | |||||
| You can add webfonts, meta tags, or analytics to this file. | |||||
| The build step will place the bundled scripts into the <body> tag. | |||||
| To begin the development, run `npm start`. | |||||
| To create a production bundle, use `npm run build`. | |||||
| --> | |||||
| </body> | </body> | ||||
| </html> | </html> | ||||
| @@ -1,6 +1,11 @@ | |||||
| #!/usr/bin/env python | #!/usr/bin/env python | ||||
| from modules import socketio, app | |||||
| from modules import socketio, app, cbpi | |||||
| socketio.run(app, host='0.0.0.0') | |||||
| try: | |||||
| port = int(cbpi.get_config_parameter('port', '5000')) | |||||
| except ValueError: | |||||
| port = 5000 | |||||
| socketio.run(app, host='0.0.0.0', port=port) | |||||
| @@ -0,0 +1 @@ | |||||
| INSERT OR IGNORE INTO config VALUES ('port', 5000, 'number', 'Port to run server (requires restart)', NULL ); | |||||