浏览代码

Merge 8ded4a1b1d into 2b095c8c77

pull/259/merge
Juan Pablo Giménez GitHub 5 年前
父节点
当前提交
b82d9a98c5
找不到此签名对应的密钥 GPG 密钥 ID: 4AEE18F83AFDEB23
共有 32 个文件被更改,包括 409 次插入325 次删除
  1. +5
    -0
      .gitignore
  2. +16
    -0
      .pre-commit-config.yaml
  3. +2
    -2
      Dockerfile
  4. +71
    -71
      modules/__init__.py
  5. +1
    -1
      modules/addon/__init__.py
  6. +6
    -5
      modules/addon/endpoints.py
  7. +6
    -6
      modules/base_plugins/brew_steps/__init__.py
  8. +1
    -1
      modules/base_plugins/dummy_temp/__init__.py
  9. +76
    -27
      modules/base_plugins/gpio_actor/__init__.py
  10. +1
    -1
      modules/buzzer/__init__.py
  11. +1
    -1
      modules/config/__init__.py
  12. +1
    -1
      modules/core/baseview.py
  13. +1
    -1
      modules/core/controller.py
  14. +13
    -13
      modules/core/core.py
  15. +1
    -1
      modules/core/db.py
  16. +8
    -10
      modules/core/db_mirgrate.py
  17. +3
    -3
      modules/core/hardware.py
  18. +5
    -5
      modules/core/step.py
  19. +4
    -4
      modules/fermenter/__init__.py
  20. +1
    -1
      modules/kettle/__init__.py
  21. +1
    -1
      modules/logs/__init__.py
  22. +2
    -2
      modules/logs/endpoints.py
  23. +1
    -1
      modules/notification/__init__.py
  24. +3
    -3
      modules/recipe_import/__init__.py
  25. +1
    -1
      modules/recipe_import/kbh.py
  26. +1
    -1
      modules/sensors/__init__.py
  27. +1
    -1
      modules/system/__init__.py
  28. +145
    -145
      modules/system/endpoints.py
  29. +1
    -1
      modules/ui/__init__.py
  30. +1
    -1
      modules/ui/static/bundle.js
  31. +3
    -0
      requirements-dev.txt
  32. +26
    -14
      requirements.txt

+ 5
- 0
.gitignore 查看文件

@@ -17,3 +17,8 @@ yarn.lock




modules/ui/package-lock.json modules/ui/package-lock.json

.python-version
upload/*
*.bak
.vscode

+ 16
- 0
.pre-commit-config.yaml 查看文件

@@ -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]

+ 2
- 2
Dockerfile 查看文件

@@ -1,5 +1,5 @@
# Dockerfile for development on a pc/mac # Dockerfile for development on a pc/mac
FROM python:2
FROM python:3.8


EXPOSE 5000 EXPOSE 5000


@@ -11,4 +11,4 @@ RUN pip install --no-cache-dir -r requirements.txt


COPY . . COPY . .


CMD ["python", "run.py"]
CMD ["python", "run.py"]

+ 71
- 71
modules/__init__.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("##########################################") app.logger.info("##########################################")

+ 1
- 1
modules/addon/__init__.py 查看文件

@@ -1 +1 @@
import endpoints
import modules.addon.endpoints

+ 6
- 5
modules/addon/endpoints.py 查看文件

@@ -11,6 +11,7 @@ import os
import requests import requests
import yaml import yaml
import shutil import shutil
import imp


blueprint = Blueprint('addon', __name__) blueprint = Blueprint('addon', __name__)


@@ -24,7 +25,7 @@ def merge(source, destination):
:param destination: :param destination:
:return: :return:
""" """
for key, value in source.items():
for key, value in list(source.items()):
if isinstance(value, dict): if isinstance(value, dict):
# get node or create one # get node or create one
node = destination.setdefault(key, {}) node = destination.setdefault(key, {})
@@ -115,7 +116,7 @@ def reload(name):
""" """
try: try:
if name in cache["modules"]: if name in cache["modules"]:
reload(cache["modules"][name])
imp.reload(cache["modules"][name])
cbpi.emit_message("REALOD OF PLUGIN %s SUCCESSFUL" % (name)) cbpi.emit_message("REALOD OF PLUGIN %s SUCCESSFUL" % (name))
return ('', 204) return ('', 204)
else: else:
@@ -132,9 +133,9 @@ def plugins():
Read the central plugin yaml to get a list of all official plugins Read the central plugin yaml to get a list of all official plugins
:return: :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)) value["installed"] = os.path.isdir("./modules/plugins/%s/" % (key))


return json.dumps(cbpi.cache["plugins"]) return json.dumps(cbpi.cache["plugins"])


+ 6
- 6
modules/base_plugins/brew_steps/__init__.py 查看文件

@@ -58,7 +58,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.notify("Mash Step Completed!", "Starting the next step", timeout=None)
self.next()
next(self)




@cbpi.step @cbpi.step
@@ -121,7 +121,7 @@ class ChilStep(StepBase):
self.start_timer(int(self.timer) * 60) self.start_timer(int(self.timer) * 60)


if self.is_timer_finished() == True: if self.is_timer_finished() == True:
self.next()
next(self)


@cbpi.step @cbpi.step
class PumpStep(StepBase): class PumpStep(StepBase):
@@ -149,7 +149,7 @@ class PumpStep(StepBase):
self.start_timer(int(self.timer) * 60) self.start_timer(int(self.timer) * 60)


if self.is_timer_finished() == True: if self.is_timer_finished() == True:
self.next()
next(self)


@cbpi.step @cbpi.step
class BoilStep(StepBase): class BoilStep(StepBase):
@@ -201,8 +201,8 @@ class BoilStep(StepBase):




def check_hop_timer(self, number, value): 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.timer_end - (int(self.timer) * 60 - int(value) * 60)):
self.__setattr__("hop_%s_added" % number, True) self.__setattr__("hop_%s_added" % number, True)
self.notify("Hop Alert", "Please add Hop %s" % number, timeout=None) 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 # 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.notify("Boil Step Completed!", "Starting the next step", timeout=None)
self.next()
next(self)

+ 1
- 1
modules/base_plugins/dummy_temp/__init__.py 查看文件

@@ -15,7 +15,7 @@ class DummyTempSensor(SensorActive):


@cbpi.action("My Custom Action") @cbpi.action("My Custom Action")
def my_action(self): def my_action(self):
print "HELLO WORLD"
print("HELLO WORLD")
pass pass


def get_unit(self): def get_unit(self):


+ 76
- 27
modules/base_plugins/gpio_actor/__init__.py 查看文件

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" base gpio actors """
import time import time


from modules import cbpi from modules import cbpi
@@ -6,46 +7,60 @@ from modules.core.hardware import ActorBase, SensorPassive, SensorActive
from modules.core.props import Property from modules.core.props import Property


try: try:
import RPi.GPIO as GPIO
import RPi.GPIO as GPIO # pylint: disable=import-error


GPIO.setmode(GPIO.BCM) GPIO.setmode(GPIO.BCM)
except Exception as e:
print e
pass

except ModuleNotFoundError as exp:
print(exp)




@cbpi.actor @cbpi.actor
class GPIOSimple(ActorBase): 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): def init(self):
GPIO.setup(int(self.gpio), GPIO.OUT) GPIO.setup(int(self.gpio), GPIO.OUT)
GPIO.output(int(self.gpio), 0) GPIO.output(int(self.gpio), 0)


def on(self, power=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) GPIO.output(int(self.gpio), 1)


def off(self): def off(self):
print "GPIO OFF"
print("GPIO OFF")
GPIO.output(int(self.gpio), 0) GPIO.output(int(self.gpio), 0)



@cbpi.actor @cbpi.actor
class GPIOPWM(ActorBase): 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) frequency = Property.Number("Frequency (Hz)", configurable=True)


p = None
gpio_inst = None
power = 100 # duty cycle power = 100 # duty cycle


def init(self): def init(self):
GPIO.setup(int(self.gpio), GPIO.OUT) GPIO.setup(int(self.gpio), GPIO.OUT)
GPIO.output(int(self.gpio), 0) GPIO.output(int(self.gpio), 0)



def on(self, power=None): def on(self, power=None):
if power is not None: if power is not None:
self.power = int(power) self.power = int(power)
@@ -53,28 +68,37 @@ class GPIOPWM(ActorBase):
if self.frequency is None: if self.frequency is None:
self.frequency = 0.5 # 2 sec 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): def set_power(self, power):
''' '''
Optional: Set the power of your actor Optional: Set the power of your actor
:param power: int value between 0 - 100 :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): def off(self):
print "GPIO OFF"
self.p.stop()
print("GPIO OFF")
self.gpio_inst.stop()




@cbpi.actor @cbpi.actor
class RelayBoard(ActorBase): 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): def init(self):
GPIO.setup(int(self.gpio), GPIO.OUT) GPIO.setup(int(self.gpio), GPIO.OUT)
@@ -88,20 +112,45 @@ class RelayBoard(ActorBase):


GPIO.output(int(self.gpio), 1) GPIO.output(int(self.gpio), 1)



@cbpi.actor @cbpi.actor
class Dummy(ActorBase): class Dummy(ActorBase):

"""
Simple Dummy Actor
"""


def on(self, power=100): def on(self, power=100):
''' '''
Code to switch on the actor Code to switch on the actor
:param power: int value between 0 - 100 :param power: int value between 0 - 100
:return:
:return:
''' '''
print "ON"
print("ON")


def off(self): 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
- 1
modules/buzzer/__init__.py 查看文件

@@ -1,5 +1,5 @@
import time import time
from thread import start_new_thread
from _thread import start_new_thread
from modules import cbpi from modules import cbpi


try: try:


+ 1
- 1
modules/config/__init__.py 查看文件

@@ -46,7 +46,7 @@ class ConfigView(BaseView):


with cls.api.app.app_context(): with cls.api.app.app_context():
cls.api.cache[cls.cache_key] = {} 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.post_init_callback(value)
cls.api.cache[cls.cache_key][value.name] = value cls.api.cache[cls.cache_key][value.name] = value




+ 1
- 1
modules/core/baseview.py 查看文件

@@ -104,6 +104,6 @@ class BaseView(FlaskView):
cls.api.cache[cls.cache_key].append(value) cls.api.cache[cls.cache_key].append(value)
else: else:
cls.api.cache[cls.cache_key] = {} 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.post_init_callback(value)
cls.api.cache[cls.cache_key][key] = value cls.api.cache[cls.cache_key][key] = value

+ 1
- 1
modules/core/controller.py 查看文件

@@ -42,7 +42,7 @@ class ControllerBase(object):


@staticmethod @staticmethod
def init_global(): def init_global():
print "GLOBAL CONTROLLER INIT"
print("GLOBAL CONTROLLER INIT")


def notify(self, headline, message, type="success", timeout=5000): def notify(self, headline, message, type="success", timeout=5000):
self.api.notify(headline, message, type, timeout) self.api.notify(headline, message, type, timeout)


+ 13
- 13
modules/core/core.py 查看文件

@@ -12,9 +12,9 @@ from time import localtime, strftime
from functools import wraps, update_wrapper 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 time
import uuid import uuid
@@ -28,7 +28,7 @@ class ActorAPI(object):
def init_actors(self): def init_actors(self):
self.app.logger.info("Init Actors") self.app.logger.info("Init Actors")
t = self.cache.get("actor_types") 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").api = self
value.get("class").init_global() value.get("class").init_global()


@@ -89,7 +89,7 @@ class SensorAPI(object):
self.app.logger.info("Init Sensors") self.app.logger.info("Init Sensors")


t = self.cache.get("sensor_types") t = self.cache.get("sensor_types")
for key, value in t.iteritems():
for key, value in list(t.items()):
value.get("class").init_global() value.get("class").init_global()


for key in self.cache.get("sensors"): for key in self.cache.get("sensors"):
@@ -292,7 +292,7 @@ class CraftBeerPi(ActorAPI, SensorAPI):
t = tmpObj.__getattribute__(m) t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description}) 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"): if hasattr(method, "action"):
label = method.__getattribute__("label") label = method.__getattribute__("label")
self.cache[key][cls.__name__]["actions"].append({"method": name, "label": 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 actor2(self, description="", power=True, **options):


def decorator(f): def decorator(f):
print f()
print f
print options
print description
print((f()))
print(f)
print(options)
print(description)
return f return f
return decorator return decorator


@@ -369,7 +369,7 @@ class CraftBeerPi(ActorAPI, SensorAPI):
t = tmpObj.__getattribute__(m) t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description}) 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"): if hasattr(method, "action"):
label = method.__getattribute__("label") label = method.__getattribute__("label")
self.cache[key][cls.__name__]["actions"].append({"method": name, "label": label}) self.cache[key][cls.__name__]["actions"].append({"method": name, "label": label})
@@ -378,12 +378,12 @@ class CraftBeerPi(ActorAPI, SensorAPI):




# Event Bus # Event Bus
def event(self, name, async=False):
def event(self, name, use_async=False):


def real_decorator(function): def real_decorator(function):
if self.eventbus.get(name) is None: if self.eventbus.get(name) is None:
self.eventbus[name] = [] self.eventbus[name] = []
self.eventbus[name].append({"function": function, "async": async})
self.eventbus[name].append({"function": function, "async": use_async})
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
return function(*args, **kwargs) return function(*args, **kwargs)
return wrapper return wrapper
@@ -485,7 +485,7 @@ class CraftBeerPi(ActorAPI, SensorAPI):
try: try:
method(self) method(self)
except Exception as e: 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) self.socketio.sleep(interval)






+ 1
- 1
modules/core/db.py 查看文件

@@ -79,7 +79,7 @@ class DBModel(object):
cur = get_db().cursor() 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)" % ( query = "INSERT INTO %s (%s, %s) VALUES (?, %s)" % (
cls.__table_name__, cls.__table_name__,
cls.__priamry_key__, cls.__priamry_key__,


+ 8
- 10
modules/core/db_mirgrate.py 查看文件

@@ -1,10 +1,11 @@
import sqlite3 import sqlite3
import os import os
from modules import cbpi 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"]) cbpi.app.logger.info("SKIP DB FILE: %s" % data["file"])
return return
try: try:
@@ -19,8 +20,9 @@ def execute_file(curernt_version, data):
conn.commit() conn.commit()


except sqlite3.OperationalError as err: except sqlite3.OperationalError as err:
print "EXCEPT"
print err
print("EXCEPT")
print(err)



@cbpi.initalizer(order=-9999) @cbpi.initalizer(order=-9999)
def init(app=None): def init(app=None):
@@ -28,7 +30,7 @@ def init(app=None):
with cbpi.app.app_context(): with cbpi.app.app_context():
conn = get_db() conn = get_db()
cur = conn.cursor() cur = conn.cursor()
current_version = None
current_version = 0
try: try:
cur.execute("SELECT max(version) as m FROM schema_info") cur.execute("SELECT max(version) as m FROM schema_info")
m = cur.fetchone() m = cur.fetchone()
@@ -41,7 +43,3 @@ def init(app=None):
d = {"version": int(filename[:filename.index('_')]), "file": filename} d = {"version": int(filename[:filename.index('_')]), "file": filename}
result.append(d) result.append(d)
execute_file(current_version, d) execute_file(current_version, d)





+ 3
- 3
modules/core/hardware.py 查看文件

@@ -44,10 +44,10 @@ class SensorBase(Base):
last_value = 0 last_value = 0


def init(self): def init(self):
print "INIT Base SENSOR"
print("INIT Base SENSOR")


def stop(self): def stop(self):
print "STOP SENSOR"
print("STOP SENSOR")


def data_received(self, data): def data_received(self, data):


@@ -86,7 +86,7 @@ class SensorActive(SensorBase):


class SensorPassive(SensorBase): class SensorPassive(SensorBase):
def init(self): def init(self):
print "INIT PASSIV SENSOR"
print("INIT PASSIV SENSOR")
pass pass


def read(self): def read(self):


+ 5
- 5
modules/core/step.py 查看文件

@@ -96,7 +96,7 @@ class StepBase(Timer, ActorAPI, SensorAPI, KettleAPI):
managed_fields = [] managed_fields = []
n = False n = False


def next(self):
def __next__(self):
self.n = True self.n = True


def init(self): def init(self):
@@ -109,10 +109,10 @@ class StepBase(Timer, ActorAPI, SensorAPI, KettleAPI):
pass pass


def execute(self): 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): def __init__(self, *args, **kwds):


+ 4
- 4
modules/fermenter/__init__.py 查看文件

@@ -210,7 +210,7 @@ class FermenterView(BaseView):
def toggle(self, id): def toggle(self, id):
fermenter = cbpi.cache.get(self.cache_key)[id] fermenter = cbpi.cache.get(self.cache_key)[id]
try: try:
print fermenter.state
print((fermenter.state))
if fermenter.state is False: if fermenter.state is False:
# Start controller # Start controller
if fermenter.logic is not None: 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)) cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id))


except Exception as e: except Exception as e:
print e
print(e)
cbpi.notify("Toogle Fementer Controller failed", "Pleae check the %s configuration" % fermenter.name, cbpi.notify("Toogle Fementer Controller failed", "Pleae check the %s configuration" % fermenter.name,
type="danger", timeout=None) type="danger", timeout=None)
return ('', 500) return ('', 500)
@@ -261,7 +261,7 @@ class FermenterView(BaseView):
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id]) cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])


def check_step(self): def check_step(self):
for key, value in cbpi.cache["fermenter_task"].iteritems():
for key, value in cbpi.cache["fermenter_task"].items():


try: try:
fermenter = self.get_fermenter(key) fermenter = self.get_fermenter(key)
@@ -292,7 +292,7 @@ def read_target_temps(api):
:return: None :return: None
""" """
result = {} 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") cbpi.save_to_file(key, value.target_temp, prefix="fermenter")






+ 1
- 1
modules/kettle/__init__.py 查看文件

@@ -86,7 +86,7 @@ def read_target_temps(api):
:return: None :return: None
""" """
result = {} 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.save_to_file(key, value.target_temp, prefix="kettle")


@cbpi.initalizer() @cbpi.initalizer()


+ 1
- 1
modules/logs/__init__.py 查看文件

@@ -1 +1 @@
import endpoints
import modules.logs.endpoints

+ 2
- 2
modules/logs/endpoints.py 查看文件

@@ -78,11 +78,11 @@ class LogView(FlaskView):


if t == "k": if t == "k":
kettle = cbpi.cache.get("kettle").get(id) 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": if t == "f":
fermenter = cbpi.cache.get("fermenter").get(id) 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) return json.dumps(result)




+ 1
- 1
modules/notification/__init__.py 查看文件

@@ -24,7 +24,7 @@ class NotificationView(FlaskView):
cbpi.cache["messages"].pop(idx) cbpi.cache["messages"].pop(idx)
return ('', 204) return ('', 204)


@cbpi.event("MESSAGE", async=True)
@cbpi.event("MESSAGE", use_async=True)
def messageEvent(message, **kwargs): def messageEvent(message, **kwargs):
""" """
React on message event. add the message to the cache and push the message to the clients React on message event. add the message to the cache and push the message to the clients


+ 3
- 3
modules/recipe_import/__init__.py 查看文件

@@ -1,3 +1,3 @@
import beerxml
import kbh
import restapi
from . import beerxml
from . import kbh
from . import restapi

+ 1
- 1
modules/recipe_import/kbh.py 查看文件

@@ -29,7 +29,7 @@ class KBH(FlaskView):
result.append({"id": row[0], "name": row[1], "brewed": row[2]}) result.append({"id": row[0], "name": row[1], "brewed": row[2]})
return json.dumps(result) return json.dumps(result)
except Exception as e: except Exception as e:
print e
print(e)
self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger")
return ('', 500) return ('', 500)
finally: finally:


+ 1
- 1
modules/sensors/__init__.py 查看文件

@@ -43,6 +43,6 @@ def read_passive_sensor(api):
:return: None :return: None


""" """
for key, value in cbpi.cache.get("sensors").iteritems():
for key, value in cbpi.cache.get("sensors").items():
if value.mode == "P": if value.mode == "P":
value.instance.read() value.instance.read()

+ 1
- 1
modules/system/__init__.py 查看文件

@@ -1 +1 @@
import endpoints
import modules.system.endpoints

+ 145
- 145
modules/system/endpoints.py 查看文件

@@ -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
modules/ui/__init__.py 查看文件

@@ -1 +1 @@
import endpoints
import modules.ui.endpoints

+ 1
- 1
modules/ui/static/bundle.js
文件差异内容过多而无法显示
查看文件


+ 3
- 0
requirements-dev.txt 查看文件

@@ -0,0 +1,3 @@
coverage==5.2.1
pre-commit
pylint

+ 26
- 14
requirements.txt 查看文件

@@ -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

正在加载...
取消
保存