| @@ -17,3 +17,8 @@ yarn.lock | |||
| modules/ui/package-lock.json | |||
| .python-version | |||
| upload/* | |||
| *.bak | |||
| .vscode | |||
| @@ -0,0 +1,16 @@ | |||
| # See https://pre-commit.com for more information | |||
| # See https://pre-commit.com/hooks.html for more hooks | |||
| repos: | |||
| - repo: https://github.com/pre-commit/pre-commit-hooks | |||
| rev: v2.4.0 | |||
| hooks: | |||
| - id: trailing-whitespace | |||
| - id: end-of-file-fixer | |||
| - id: check-yaml | |||
| - id: check-added-large-files | |||
| - repo: https://github.com/pycqa/pylint | |||
| rev: pylint-2.5.3 | |||
| hooks: | |||
| - id: pylint | |||
| stages: [commit] | |||
| additional_dependencies: [pylint-flask] | |||
| @@ -1,5 +1,5 @@ | |||
| # Dockerfile for development on a pc/mac | |||
| FROM python:2 | |||
| FROM python:3.8 | |||
| EXPOSE 5000 | |||
| @@ -11,4 +11,4 @@ RUN pip install --no-cache-dir -r requirements.txt | |||
| COPY . . | |||
| CMD ["python", "run.py"] | |||
| CMD ["python", "run.py"] | |||
| @@ -1,72 +1,72 @@ | |||
| import json | |||
| import pprint | |||
| import sys, os | |||
| from flask import Flask, render_template, redirect | |||
| from flask_socketio import SocketIO, emit | |||
| import logging | |||
| # Define the WSGI application object | |||
| from app_config import * | |||
| import pprint | |||
| from modules.core.db import get_db | |||
| @app.route('/') | |||
| def index(): | |||
| return redirect('ui') | |||
| # Define the database object which is imported | |||
| # by modules and controllers | |||
| import modules.steps | |||
| import modules.config | |||
| import modules.logs | |||
| import modules.sensors | |||
| import modules.actor | |||
| import modules.notification | |||
| import modules.fermenter | |||
| from modules.addon.endpoints import initPlugins | |||
| import modules.ui | |||
| import modules.system | |||
| import modules.buzzer | |||
| import modules.stats | |||
| import modules.kettle | |||
| import modules.recipe_import | |||
| import modules.core.db_mirgrate | |||
| from app_config import cbpi | |||
| # Build the database: | |||
| # This will create the database file using SQLAlchemy | |||
| pp = pprint.PrettyPrinter(indent=6) | |||
| def init_db(): | |||
| print "INIT DB" | |||
| with app.app_context(): | |||
| db = get_db() | |||
| try: | |||
| with app.open_resource('../config/schema.sql', mode='r') as f: | |||
| db.cursor().executescript(f.read()) | |||
| db.commit() | |||
| except Exception as e: | |||
| pass | |||
| init_db() | |||
| initPlugins() | |||
| cbpi.run_init() | |||
| cbpi.run_background_processes() | |||
| app.logger.info("##########################################") | |||
| app.logger.info("### STARTUP COMPLETE") | |||
| import json | |||
| import pprint | |||
| import sys, os | |||
| from flask import Flask, render_template, redirect | |||
| from flask_socketio import SocketIO, emit | |||
| import logging | |||
| # Define the WSGI application object | |||
| from modules.app_config import * | |||
| import pprint | |||
| from modules.core.db import get_db | |||
| @app.route('/') | |||
| def index(): | |||
| return redirect('ui') | |||
| # Define the database object which is imported | |||
| # by modules and controllers | |||
| import modules.steps | |||
| import modules.config | |||
| import modules.logs | |||
| import modules.sensors | |||
| import modules.actor | |||
| import modules.notification | |||
| import modules.fermenter | |||
| from modules.addon.endpoints import initPlugins | |||
| import modules.ui | |||
| import modules.system | |||
| import modules.buzzer | |||
| import modules.stats | |||
| import modules.kettle | |||
| import modules.recipe_import | |||
| import modules.core.db_mirgrate | |||
| from .app_config import cbpi | |||
| # Build the database: | |||
| # This will create the database file using SQLAlchemy | |||
| pp = pprint.PrettyPrinter(indent=6) | |||
| def init_db(): | |||
| print("INIT DB") | |||
| with app.app_context(): | |||
| db = get_db() | |||
| try: | |||
| with app.open_resource('../config/schema.sql', mode='r') as f: | |||
| db.cursor().executescript(f.read()) | |||
| db.commit() | |||
| except Exception as e: | |||
| pass | |||
| init_db() | |||
| initPlugins() | |||
| cbpi.run_init() | |||
| cbpi.run_background_processes() | |||
| app.logger.info("##########################################") | |||
| app.logger.info("### STARTUP COMPLETE") | |||
| app.logger.info("##########################################") | |||
| @@ -1 +1 @@ | |||
| import endpoints | |||
| import modules.addon.endpoints | |||
| @@ -11,6 +11,7 @@ import os | |||
| import requests | |||
| import yaml | |||
| import shutil | |||
| import imp | |||
| blueprint = Blueprint('addon', __name__) | |||
| @@ -24,7 +25,7 @@ def merge(source, destination): | |||
| :param destination: | |||
| :return: | |||
| """ | |||
| for key, value in source.items(): | |||
| for key, value in list(source.items()): | |||
| if isinstance(value, dict): | |||
| # get node or create one | |||
| node = destination.setdefault(key, {}) | |||
| @@ -115,7 +116,7 @@ def reload(name): | |||
| """ | |||
| try: | |||
| if name in cache["modules"]: | |||
| reload(cache["modules"][name]) | |||
| imp.reload(cache["modules"][name]) | |||
| cbpi.emit_message("REALOD OF PLUGIN %s SUCCESSFUL" % (name)) | |||
| return ('', 204) | |||
| else: | |||
| @@ -132,9 +133,9 @@ def plugins(): | |||
| Read the central plugin yaml to get a list of all official plugins | |||
| :return: | |||
| """ | |||
| response = requests.get("https://raw.githubusercontent.com/Manuel83/craftbeerpi-plugins/master/plugins.yaml") | |||
| cbpi.cache["plugins"] = merge(yaml.load(response.text), cbpi.cache["plugins"]) | |||
| for key, value in cbpi.cache["plugins"].iteritems(): | |||
| response = requests.get("https://raw.githubusercontent.com/jpgimenez/craftbeerpi-plugins/master/plugins.yaml") | |||
| cbpi.cache["plugins"] = merge(yaml.safe_load(response.text), cbpi.cache["plugins"]) | |||
| for key, value in cbpi.cache["plugins"].items(): | |||
| value["installed"] = os.path.isdir("./modules/plugins/%s/" % (key)) | |||
| return json.dumps(cbpi.cache["plugins"]) | |||
| @@ -58,7 +58,7 @@ class MashStep(StepBase): | |||
| # Check if timer finished and go to next step | |||
| if self.is_timer_finished() == True: | |||
| self.notify("Mash Step Completed!", "Starting the next step", timeout=None) | |||
| self.next() | |||
| next(self) | |||
| @cbpi.step | |||
| @@ -121,7 +121,7 @@ class ChilStep(StepBase): | |||
| self.start_timer(int(self.timer) * 60) | |||
| if self.is_timer_finished() == True: | |||
| self.next() | |||
| next(self) | |||
| @cbpi.step | |||
| class PumpStep(StepBase): | |||
| @@ -149,7 +149,7 @@ class PumpStep(StepBase): | |||
| self.start_timer(int(self.timer) * 60) | |||
| if self.is_timer_finished() == True: | |||
| self.next() | |||
| next(self) | |||
| @cbpi.step | |||
| class BoilStep(StepBase): | |||
| @@ -201,8 +201,8 @@ class BoilStep(StepBase): | |||
| def check_hop_timer(self, number, value): | |||
| if self.__getattribute__("hop_%s_added" % number) is not True and time.time() > ( | |||
| if isinstance(value, int) and \ | |||
| self.__getattribute__("hop_%s_added" % number) is not True and time.time() > ( | |||
| self.timer_end - (int(self.timer) * 60 - int(value) * 60)): | |||
| self.__setattr__("hop_%s_added" % number, True) | |||
| self.notify("Hop Alert", "Please add Hop %s" % number, timeout=None) | |||
| @@ -226,4 +226,4 @@ class BoilStep(StepBase): | |||
| # Check if timer finished and go to next step | |||
| if self.is_timer_finished() == True: | |||
| self.notify("Boil Step Completed!", "Starting the next step", timeout=None) | |||
| self.next() | |||
| next(self) | |||
| @@ -15,7 +15,7 @@ class DummyTempSensor(SensorActive): | |||
| @cbpi.action("My Custom Action") | |||
| def my_action(self): | |||
| print "HELLO WORLD" | |||
| print("HELLO WORLD") | |||
| pass | |||
| def get_unit(self): | |||
| @@ -1,4 +1,5 @@ | |||
| # -*- coding: utf-8 -*- | |||
| """ base gpio actors """ | |||
| import time | |||
| from modules import cbpi | |||
| @@ -6,46 +7,60 @@ from modules.core.hardware import ActorBase, SensorPassive, SensorActive | |||
| from modules.core.props import Property | |||
| try: | |||
| import RPi.GPIO as GPIO | |||
| import RPi.GPIO as GPIO # pylint: disable=import-error | |||
| GPIO.setmode(GPIO.BCM) | |||
| except Exception as e: | |||
| print e | |||
| pass | |||
| except ModuleNotFoundError as exp: | |||
| print(exp) | |||
| @cbpi.actor | |||
| class GPIOSimple(ActorBase): | |||
| gpio = Property.Select("GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], description="GPIO to which the actor is connected") | |||
| """ | |||
| Simple GPIO Actor | |||
| """ | |||
| gpio = Property.Select("GPIO", | |||
| options=[ | |||
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | |||
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | |||
| 26, 27 | |||
| ], | |||
| description="GPIO to which the actor is connected") | |||
| def init(self): | |||
| GPIO.setup(int(self.gpio), GPIO.OUT) | |||
| GPIO.output(int(self.gpio), 0) | |||
| def on(self, power=0): | |||
| print "GPIO ON %s" % str(self.gpio) | |||
| print(("GPIO ON %s" % str(self.gpio))) | |||
| GPIO.output(int(self.gpio), 1) | |||
| def off(self): | |||
| print "GPIO OFF" | |||
| print("GPIO OFF") | |||
| GPIO.output(int(self.gpio), 0) | |||
| @cbpi.actor | |||
| class GPIOPWM(ActorBase): | |||
| gpio = Property.Select("GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], description="GPIO to which the actor is connected") | |||
| """ | |||
| GPIO Actor with PWM support | |||
| """ | |||
| gpio = Property.Select("GPIO", | |||
| options=[ | |||
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | |||
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | |||
| 26, 27 | |||
| ], | |||
| description="GPIO to which the actor is connected") | |||
| frequency = Property.Number("Frequency (Hz)", configurable=True) | |||
| p = None | |||
| gpio_inst = None | |||
| power = 100 # duty cycle | |||
| def init(self): | |||
| GPIO.setup(int(self.gpio), GPIO.OUT) | |||
| GPIO.output(int(self.gpio), 0) | |||
| def on(self, power=None): | |||
| if power is not None: | |||
| self.power = int(power) | |||
| @@ -53,28 +68,37 @@ class GPIOPWM(ActorBase): | |||
| if self.frequency is None: | |||
| self.frequency = 0.5 # 2 sec | |||
| self.p = GPIO.PWM(int(self.gpio), float(self.frequency)) | |||
| self.p.start(int(self.power)) | |||
| self.gpio_inst = GPIO.PWM(int(self.gpio), float(self.frequency)) | |||
| self.gpio_inst.start(int(self.power)) | |||
| def set_power(self, power): | |||
| ''' | |||
| Optional: Set the power of your actor | |||
| :param power: int value between 0 - 100 | |||
| :return: | |||
| :return: | |||
| ''' | |||
| if power is not None: | |||
| self.power = int(power) | |||
| self.p.ChangeDutyCycle(self.power) | |||
| if self.gpio_inst: | |||
| if power is not None: | |||
| self.power = int(power) | |||
| self.gpio_inst.ChangeDutyCycle(self.power) | |||
| def off(self): | |||
| print "GPIO OFF" | |||
| self.p.stop() | |||
| print("GPIO OFF") | |||
| self.gpio_inst.stop() | |||
| @cbpi.actor | |||
| class RelayBoard(ActorBase): | |||
| gpio = Property.Select("GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], description="GPIO to which the actor is connected") | |||
| """ | |||
| Relay board Actor | |||
| """ | |||
| gpio = Property.Select("GPIO", | |||
| options=[ | |||
| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | |||
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | |||
| 26, 27 | |||
| ], | |||
| description="GPIO to which the actor is connected") | |||
| def init(self): | |||
| GPIO.setup(int(self.gpio), GPIO.OUT) | |||
| @@ -88,20 +112,45 @@ class RelayBoard(ActorBase): | |||
| GPIO.output(int(self.gpio), 1) | |||
| @cbpi.actor | |||
| class Dummy(ActorBase): | |||
| """ | |||
| Simple Dummy Actor | |||
| """ | |||
| def on(self, power=100): | |||
| ''' | |||
| Code to switch on the actor | |||
| :param power: int value between 0 - 100 | |||
| :return: | |||
| :return: | |||
| ''' | |||
| print "ON" | |||
| print("ON") | |||
| def off(self): | |||
| print "OFF" | |||
| print("OFF") | |||
| @cbpi.actor | |||
| class DummyPWM(ActorBase): | |||
| """ | |||
| Dummy Actor with PWM support | |||
| """ | |||
| power = 100 | |||
| def on(self, power=100): | |||
| ''' | |||
| Code to switch on the actor | |||
| :param power: int value between 0 - 100 | |||
| :return: | |||
| ''' | |||
| self.power = int(power) if power is not None else 100 | |||
| print("DummyPWM ON %s" % self.power) | |||
| def off(self): | |||
| self.power = 100 | |||
| print("OFF") | |||
| def set_power(self, power): | |||
| self.power = int(power) | |||
| print("DummyPWM POWER %s" % self.power) | |||
| @@ -1,5 +1,5 @@ | |||
| import time | |||
| from thread import start_new_thread | |||
| from _thread import start_new_thread | |||
| from modules import cbpi | |||
| try: | |||
| @@ -46,7 +46,7 @@ class ConfigView(BaseView): | |||
| with cls.api.app.app_context(): | |||
| cls.api.cache[cls.cache_key] = {} | |||
| for key, value in cls.model.get_all().iteritems(): | |||
| for key, value in cls.model.get_all().items(): | |||
| cls.post_init_callback(value) | |||
| cls.api.cache[cls.cache_key][value.name] = value | |||
| @@ -104,6 +104,6 @@ class BaseView(FlaskView): | |||
| cls.api.cache[cls.cache_key].append(value) | |||
| else: | |||
| cls.api.cache[cls.cache_key] = {} | |||
| for key, value in cls.model.get_all().iteritems(): | |||
| for key, value in list(cls.model.get_all().items()): | |||
| cls.post_init_callback(value) | |||
| cls.api.cache[cls.cache_key][key] = value | |||
| @@ -42,7 +42,7 @@ class ControllerBase(object): | |||
| @staticmethod | |||
| def init_global(): | |||
| print "GLOBAL CONTROLLER INIT" | |||
| print("GLOBAL CONTROLLER INIT") | |||
| def notify(self, headline, message, type="success", timeout=5000): | |||
| self.api.notify(headline, message, type, timeout) | |||
| @@ -12,9 +12,9 @@ from time import localtime, strftime | |||
| from functools import wraps, update_wrapper | |||
| from props import * | |||
| from modules.core.props import * | |||
| from hardware import * | |||
| from modules.core.hardware import * | |||
| import time | |||
| import uuid | |||
| @@ -28,7 +28,7 @@ class ActorAPI(object): | |||
| def init_actors(self): | |||
| self.app.logger.info("Init Actors") | |||
| t = self.cache.get("actor_types") | |||
| for key, value in t.iteritems(): | |||
| for key, value in list(t.items()): | |||
| value.get("class").api = self | |||
| value.get("class").init_global() | |||
| @@ -89,7 +89,7 @@ class SensorAPI(object): | |||
| self.app.logger.info("Init Sensors") | |||
| t = self.cache.get("sensor_types") | |||
| for key, value in t.iteritems(): | |||
| for key, value in list(t.items()): | |||
| value.get("class").init_global() | |||
| for key in self.cache.get("sensors"): | |||
| @@ -292,7 +292,7 @@ class CraftBeerPi(ActorAPI, SensorAPI): | |||
| t = tmpObj.__getattribute__(m) | |||
| self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description}) | |||
| for name, method in cls.__dict__.iteritems(): | |||
| for name, method in list(cls.__dict__.items()): | |||
| if hasattr(method, "action"): | |||
| label = method.__getattribute__("label") | |||
| self.cache[key][cls.__name__]["actions"].append({"method": name, "label": label}) | |||
| @@ -309,10 +309,10 @@ class CraftBeerPi(ActorAPI, SensorAPI): | |||
| def actor2(self, description="", power=True, **options): | |||
| def decorator(f): | |||
| print f() | |||
| print f | |||
| print options | |||
| print description | |||
| print((f())) | |||
| print(f) | |||
| print(options) | |||
| print(description) | |||
| return f | |||
| return decorator | |||
| @@ -369,7 +369,7 @@ class CraftBeerPi(ActorAPI, SensorAPI): | |||
| t = tmpObj.__getattribute__(m) | |||
| self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description}) | |||
| for name, method in cls.__dict__.iteritems(): | |||
| for name, method in list(cls.__dict__.items()): | |||
| if hasattr(method, "action"): | |||
| label = method.__getattribute__("label") | |||
| self.cache[key][cls.__name__]["actions"].append({"method": name, "label": label}) | |||
| @@ -378,12 +378,12 @@ class CraftBeerPi(ActorAPI, SensorAPI): | |||
| # Event Bus | |||
| def event(self, name, async=False): | |||
| def event(self, name, use_async=False): | |||
| def real_decorator(function): | |||
| if self.eventbus.get(name) is None: | |||
| self.eventbus[name] = [] | |||
| self.eventbus[name].append({"function": function, "async": async}) | |||
| self.eventbus[name].append({"function": function, "async": use_async}) | |||
| def wrapper(*args, **kwargs): | |||
| return function(*args, **kwargs) | |||
| return wrapper | |||
| @@ -485,7 +485,7 @@ class CraftBeerPi(ActorAPI, SensorAPI): | |||
| try: | |||
| method(self) | |||
| except Exception as e: | |||
| self.app.logger.error("Exception" + method.__name__ + ": " + str(e)) | |||
| self.app.logger.error("Exception " + method.__name__ + ": " + str(e)) | |||
| self.socketio.sleep(interval) | |||
| @@ -79,7 +79,7 @@ class DBModel(object): | |||
| cur = get_db().cursor() | |||
| if cls.__priamry_key__ is not None and kwargs.has_key(cls.__priamry_key__): | |||
| if cls.__priamry_key__ is not None and cls.__priamry_key__ in kwargs: | |||
| query = "INSERT INTO %s (%s, %s) VALUES (?, %s)" % ( | |||
| cls.__table_name__, | |||
| cls.__priamry_key__, | |||
| @@ -1,10 +1,11 @@ | |||
| import sqlite3 | |||
| import os | |||
| from modules import cbpi | |||
| from db import get_db | |||
| from .db import get_db | |||
| def execute_file(curernt_version, data): | |||
| if curernt_version >= data["version"]: | |||
| def execute_file(current_version, data): | |||
| if current_version >= data["version"]: | |||
| cbpi.app.logger.info("SKIP DB FILE: %s" % data["file"]) | |||
| return | |||
| try: | |||
| @@ -19,8 +20,9 @@ def execute_file(curernt_version, data): | |||
| conn.commit() | |||
| except sqlite3.OperationalError as err: | |||
| print "EXCEPT" | |||
| print err | |||
| print("EXCEPT") | |||
| print(err) | |||
| @cbpi.initalizer(order=-9999) | |||
| def init(app=None): | |||
| @@ -28,7 +30,7 @@ def init(app=None): | |||
| with cbpi.app.app_context(): | |||
| conn = get_db() | |||
| cur = conn.cursor() | |||
| current_version = None | |||
| current_version = 0 | |||
| try: | |||
| cur.execute("SELECT max(version) as m FROM schema_info") | |||
| m = cur.fetchone() | |||
| @@ -41,7 +43,3 @@ def init(app=None): | |||
| d = {"version": int(filename[:filename.index('_')]), "file": filename} | |||
| result.append(d) | |||
| execute_file(current_version, d) | |||
| @@ -44,10 +44,10 @@ class SensorBase(Base): | |||
| last_value = 0 | |||
| def init(self): | |||
| print "INIT Base SENSOR" | |||
| print("INIT Base SENSOR") | |||
| def stop(self): | |||
| print "STOP SENSOR" | |||
| print("STOP SENSOR") | |||
| def data_received(self, data): | |||
| @@ -86,7 +86,7 @@ class SensorActive(SensorBase): | |||
| class SensorPassive(SensorBase): | |||
| def init(self): | |||
| print "INIT PASSIV SENSOR" | |||
| print("INIT PASSIV SENSOR") | |||
| pass | |||
| def read(self): | |||
| @@ -96,7 +96,7 @@ class StepBase(Timer, ActorAPI, SensorAPI, KettleAPI): | |||
| managed_fields = [] | |||
| n = False | |||
| def next(self): | |||
| def __next__(self): | |||
| self.n = True | |||
| def init(self): | |||
| @@ -109,10 +109,10 @@ class StepBase(Timer, ActorAPI, SensorAPI, KettleAPI): | |||
| pass | |||
| def execute(self): | |||
| print "-------------" | |||
| print "Step Info" | |||
| print "Kettle ID: %s" % self.kettle_id | |||
| print "ID: %s" % self.id | |||
| print("-------------") | |||
| print("Step Info") | |||
| print(("Kettle ID: %s" % self.kettle_id)) | |||
| print(("ID: %s" % self.id)) | |||
| def __init__(self, *args, **kwds): | |||
| @@ -210,7 +210,7 @@ class FermenterView(BaseView): | |||
| def toggle(self, id): | |||
| fermenter = cbpi.cache.get(self.cache_key)[id] | |||
| try: | |||
| print fermenter.state | |||
| print((fermenter.state)) | |||
| if fermenter.state is False: | |||
| # Start controller | |||
| if fermenter.logic is not None: | |||
| @@ -236,7 +236,7 @@ class FermenterView(BaseView): | |||
| cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id)) | |||
| except Exception as e: | |||
| print e | |||
| print(e) | |||
| cbpi.notify("Toogle Fementer Controller failed", "Pleae check the %s configuration" % fermenter.name, | |||
| type="danger", timeout=None) | |||
| return ('', 500) | |||
| @@ -261,7 +261,7 @@ class FermenterView(BaseView): | |||
| cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id]) | |||
| def check_step(self): | |||
| for key, value in cbpi.cache["fermenter_task"].iteritems(): | |||
| for key, value in cbpi.cache["fermenter_task"].items(): | |||
| try: | |||
| fermenter = self.get_fermenter(key) | |||
| @@ -292,7 +292,7 @@ def read_target_temps(api): | |||
| :return: None | |||
| """ | |||
| result = {} | |||
| for key, value in cbpi.cache.get("fermenter").iteritems(): | |||
| for key, value in cbpi.cache.get("fermenter").items(): | |||
| cbpi.save_to_file(key, value.target_temp, prefix="fermenter") | |||
| @@ -86,7 +86,7 @@ def read_target_temps(api): | |||
| :return: None | |||
| """ | |||
| result = {} | |||
| for key, value in cbpi.cache.get("kettle").iteritems(): | |||
| for key, value in cbpi.cache.get("kettle").items(): | |||
| cbpi.save_to_file(key, value.target_temp, prefix="kettle") | |||
| @cbpi.initalizer() | |||
| @@ -1 +1 @@ | |||
| import endpoints | |||
| import modules.logs.endpoints | |||
| @@ -78,11 +78,11 @@ class LogView(FlaskView): | |||
| if t == "k": | |||
| kettle = cbpi.cache.get("kettle").get(id) | |||
| result = map(self.convert_chart_data_to_json, cbpi.get_controller(kettle.logic).get("class").chart(kettle)) | |||
| result = list(map(self.convert_chart_data_to_json, cbpi.get_controller(kettle.logic).get("class").chart(kettle))) | |||
| if t == "f": | |||
| fermenter = cbpi.cache.get("fermenter").get(id) | |||
| result = map(self.convert_chart_data_to_json, cbpi.get_fermentation_controller(fermenter.logic).get("class").chart(fermenter)) | |||
| result = list(map(self.convert_chart_data_to_json, cbpi.get_fermentation_controller(fermenter.logic).get("class").chart(fermenter))) | |||
| return json.dumps(result) | |||
| @@ -24,7 +24,7 @@ class NotificationView(FlaskView): | |||
| cbpi.cache["messages"].pop(idx) | |||
| return ('', 204) | |||
| @cbpi.event("MESSAGE", async=True) | |||
| @cbpi.event("MESSAGE", use_async=True) | |||
| def messageEvent(message, **kwargs): | |||
| """ | |||
| React on message event. add the message to the cache and push the message to the clients | |||
| @@ -1,3 +1,3 @@ | |||
| import beerxml | |||
| import kbh | |||
| import restapi | |||
| from . import beerxml | |||
| from . import kbh | |||
| from . import restapi | |||
| @@ -29,7 +29,7 @@ class KBH(FlaskView): | |||
| result.append({"id": row[0], "name": row[1], "brewed": row[2]}) | |||
| return json.dumps(result) | |||
| except Exception as e: | |||
| print e | |||
| print(e) | |||
| self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") | |||
| return ('', 500) | |||
| finally: | |||
| @@ -43,6 +43,6 @@ def read_passive_sensor(api): | |||
| :return: None | |||
| """ | |||
| for key, value in cbpi.cache.get("sensors").iteritems(): | |||
| for key, value in cbpi.cache.get("sensors").items(): | |||
| if value.mode == "P": | |||
| value.instance.read() | |||
| @@ -1 +1 @@ | |||
| import endpoints | |||
| import modules.system.endpoints | |||
| @@ -1,145 +1,145 @@ | |||
| import yaml | |||
| from flask import json, url_for, Response | |||
| from flask_classy import FlaskView, route | |||
| from git import Repo, Git | |||
| from modules.app_config import cbpi | |||
| import pprint | |||
| import time | |||
| class SystemView(FlaskView): | |||
| def doShutdown(self): | |||
| time.sleep(5) | |||
| from subprocess import call | |||
| call("halt") | |||
| @route('/shutdown', methods=['POST']) | |||
| def shutdown(self): | |||
| """ | |||
| Shutdown hook | |||
| :return: HTTP 204 | |||
| """ | |||
| self.doShutdown() | |||
| return ('', 204) | |||
| def doReboot(self): | |||
| time.sleep(5) | |||
| from subprocess import call | |||
| call("reboot") | |||
| @route('/reboot', methods=['POST']) | |||
| def reboot(self): | |||
| """ | |||
| Reboot hook | |||
| :return: HTTP 204 | |||
| """ | |||
| self.doReboot() | |||
| return ('', 204) | |||
| @route('/tags/<name>', methods=['GET']) | |||
| def checkout_tag(self,name): | |||
| repo = Repo('./') | |||
| repo.git.reset('--hard') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| g = Git('./') | |||
| g.checkout(name) | |||
| cbpi.notify("Checkout successful", "Please restart the system") | |||
| return ('', 204) | |||
| @route('/git/status', methods=['GET']) | |||
| def git_status(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| # Tags | |||
| tags = [] | |||
| for t in repo.tags: | |||
| tags.append({"name": t.name, "commit": str(t.commit), "date": t.commit.committed_date, | |||
| "committer": t.commit.committer.name, "message": t.commit.message}) | |||
| try: | |||
| branch_name = repo.active_branch.name | |||
| # test1 | |||
| except: | |||
| branch_name = None | |||
| changes = [] | |||
| commits_behind = repo.iter_commits('master..origin/master') | |||
| for c in list(commits_behind): | |||
| changes.append({"committer": c.committer.name, "message": c.message}) | |||
| return json.dumps({"tags": tags, "headcommit": str(repo.head.commit), "branchname": branch_name, | |||
| "master": {"changes": changes}}) | |||
| @route('/check_update', methods=['GET']) | |||
| def check_update(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| changes = [] | |||
| commits_behind = repo.iter_commits('master..origin/master') | |||
| for c in list(commits_behind): | |||
| changes.append({"committer": c.committer.name, "message": c.message}) | |||
| return json.dumps(changes) | |||
| @route('/git/pull', methods=['POST']) | |||
| def update(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| info = o.pull() | |||
| cbpi.notify("Pull successful", "The lasted updated was downloaded. Please restart the system") | |||
| return ('', 204) | |||
| @route('/dump', methods=['GET']) | |||
| def dump(self): | |||
| return json.dumps(cbpi.cache) | |||
| @route('/endpoints', methods=['GET']) | |||
| def endpoints(self): | |||
| import urllib | |||
| output = [] | |||
| vf = self.api.app.view_functions | |||
| for f in self.api.app.view_functions: | |||
| print f | |||
| endpoints = {} | |||
| re = { | |||
| "swagger": "2.0", | |||
| "host": "", | |||
| "info": { | |||
| "description":"", | |||
| "version": "", | |||
| "title": "CraftBeerPi" | |||
| }, | |||
| "schemes": ["http"], | |||
| "paths": endpoints} | |||
| for rule in self.api.app.url_map.iter_rules(): | |||
| r = rule | |||
| endpoints[rule.rule] = {} | |||
| if "HEAD" in r.methods: r.methods.remove("HEAD") | |||
| if "OPTIONS" in r.methods: r.methods.remove("OPTIONS") | |||
| for m in rule.methods: | |||
| endpoints[rule.rule][m] = dict(summary="", description="", consumes=["application/json"],produces=["application/json"]) | |||
| with open("config/version.yaml", 'r') as stream: | |||
| y = yaml.load(stream) | |||
| pprint.pprint(y) | |||
| pprint.pprint(re) | |||
| return Response(yaml.dump(re), mimetype='text/yaml') | |||
| @cbpi.initalizer() | |||
| def init(cbpi): | |||
| SystemView.api = cbpi | |||
| SystemView.register(cbpi.app, route_base='/api/system') | |||
| import yaml | |||
| from flask import json, url_for, Response | |||
| from flask_classy import FlaskView, route | |||
| from git import Repo, Git | |||
| from modules.app_config import cbpi | |||
| import pprint | |||
| import time | |||
| class SystemView(FlaskView): | |||
| def doShutdown(self): | |||
| time.sleep(5) | |||
| from subprocess import call | |||
| call("halt") | |||
| @route('/shutdown', methods=['POST']) | |||
| def shutdown(self): | |||
| """ | |||
| Shutdown hook | |||
| :return: HTTP 204 | |||
| """ | |||
| self.doShutdown() | |||
| return ('', 204) | |||
| def doReboot(self): | |||
| time.sleep(5) | |||
| from subprocess import call | |||
| call("reboot") | |||
| @route('/reboot', methods=['POST']) | |||
| def reboot(self): | |||
| """ | |||
| Reboot hook | |||
| :return: HTTP 204 | |||
| """ | |||
| self.doReboot() | |||
| return ('', 204) | |||
| @route('/tags/<name>', methods=['GET']) | |||
| def checkout_tag(self,name): | |||
| repo = Repo('./') | |||
| repo.git.reset('--hard') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| g = Git('./') | |||
| g.checkout(name) | |||
| cbpi.notify("Checkout successful", "Please restart the system") | |||
| return ('', 204) | |||
| @route('/git/status', methods=['GET']) | |||
| def git_status(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| # Tags | |||
| tags = [] | |||
| for t in repo.tags: | |||
| tags.append({"name": t.name, "commit": str(t.commit), "date": t.commit.committed_date, | |||
| "committer": t.commit.committer.name, "message": t.commit.message}) | |||
| try: | |||
| branch_name = repo.active_branch.name | |||
| # test1 | |||
| except: | |||
| branch_name = None | |||
| changes = [] | |||
| commits_behind = repo.iter_commits('master..origin/master') | |||
| for c in list(commits_behind): | |||
| changes.append({"committer": c.committer.name, "message": c.message}) | |||
| return json.dumps({"tags": tags, "headcommit": str(repo.head.commit), "branchname": branch_name, | |||
| "master": {"changes": changes}}) | |||
| @route('/check_update', methods=['GET']) | |||
| def check_update(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| o.fetch() | |||
| changes = [] | |||
| commits_behind = repo.iter_commits('master..origin/master') | |||
| for c in list(commits_behind): | |||
| changes.append({"committer": c.committer.name, "message": c.message}) | |||
| return json.dumps(changes) | |||
| @route('/git/pull', methods=['POST']) | |||
| def update(self): | |||
| repo = Repo('./') | |||
| o = repo.remotes.origin | |||
| info = o.pull() | |||
| cbpi.notify("Pull successful", "The lasted updated was downloaded. Please restart the system") | |||
| return ('', 204) | |||
| @route('/dump', methods=['GET']) | |||
| def dump(self): | |||
| return json.dumps(cbpi.cache) | |||
| @route('/endpoints', methods=['GET']) | |||
| def endpoints(self): | |||
| import urllib.request, urllib.parse, urllib.error | |||
| output = [] | |||
| vf = self.api.app.view_functions | |||
| for f in self.api.app.view_functions: | |||
| print(f) | |||
| endpoints = {} | |||
| re = { | |||
| "swagger": "2.0", | |||
| "host": "", | |||
| "info": { | |||
| "description":"", | |||
| "version": "", | |||
| "title": "CraftBeerPi" | |||
| }, | |||
| "schemes": ["http"], | |||
| "paths": endpoints} | |||
| for rule in self.api.app.url_map.iter_rules(): | |||
| r = rule | |||
| endpoints[rule.rule] = {} | |||
| if "HEAD" in r.methods: r.methods.remove("HEAD") | |||
| if "OPTIONS" in r.methods: r.methods.remove("OPTIONS") | |||
| for m in rule.methods: | |||
| endpoints[rule.rule][m] = dict(summary="", description="", consumes=["application/json"],produces=["application/json"]) | |||
| with open("config/version.yaml", 'r') as stream: | |||
| y = yaml.safe_load(stream) | |||
| pprint.pprint(y) | |||
| pprint.pprint(re) | |||
| return Response(yaml.dump(re), mimetype='text/yaml') | |||
| @cbpi.initalizer() | |||
| def init(cbpi): | |||
| SystemView.api = cbpi | |||
| SystemView.register(cbpi.app, route_base='/api/system') | |||
| @@ -1 +1 @@ | |||
| import endpoints | |||
| import modules.ui.endpoints | |||
| @@ -0,0 +1,3 @@ | |||
| coverage==5.2.1 | |||
| pre-commit | |||
| pylint | |||
| @@ -1,14 +1,26 @@ | |||
| Flask==0.12.4 | |||
| Flask-SocketIO==2.6.2 | |||
| eventlet==0.19.0 | |||
| greenlet==0.4.10 | |||
| python-dateutil==2.5.3 | |||
| python-engineio==0.9.2 | |||
| python-mimeparse==1.5.2 | |||
| python-socketio==1.4.4 | |||
| PyYAML==4.2b1 | |||
| requests==2.20.0 | |||
| Werkzeug==0.11.10 | |||
| httplib2==0.9.2 | |||
| flask-classy==0.6.10 | |||
| GitPython==2.1.3 | |||
| Flask==1.1.2 | |||
| Flask-Classy==0.6.10 | |||
| Flask-SocketIO==2.6.2 | |||
| greenlet==0.4.16 | |||
| eventlet==0.26.1 | |||
| python-engineio==3.13.1 | |||
| python-socketio==1.4.4 | |||
| attrs==19.3.0 | |||
| certifi==2020.6.20 | |||
| chardet==3.0.4 | |||
| click==7.1.2 | |||
| idna==2.10 | |||
| itsdangerous==1.1.0 | |||
| Jinja2==2.11.2 | |||
| MarkupSafe==1.1.1 | |||
| PyYAML==5.3.1 | |||
| requests==2.24.0 | |||
| six==1.15.0 | |||
| smmap==3.0.4 | |||
| urllib3==1.25.10 | |||
| Werkzeug==1.0.1 | |||
| gitdb==4.0.5 | |||
| GitPython==3.1.7 | |||