浏览代码

Merge 4d574b1278 into eda209422f

pull/194/merge
Johannes GitHub 7 年前
父节点
当前提交
a31cb0d02e
找不到此签名对应的密钥 GPG 密钥 ID: 4AEE18F83AFDEB23
共有 11 个文件被更改,包括 212 次插入67 次删除
  1. +1
    -0
      .gitignore
  2. +1
    -1
      README.md
  3. +19
    -0
      config/logger.yaml
  4. +19
    -7
      install.sh
  5. +5
    -12
      modules/app_config.py
  6. +42
    -14
      modules/core/core.py
  7. +82
    -23
      modules/logs/endpoints.py
  8. +25
    -9
      modules/recipe_import/beerxml.py
  9. +10
    -1
      modules/steps/__init__.py
  10. +4
    -0
      modules/system/endpoints.py
  11. +4
    -0
      update/4_kairosdb_config.sql

+ 1
- 0
.gitignore 查看文件

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




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

+ 1
- 1
README.md 查看文件

@@ -41,7 +41,7 @@ app_1 | [2018-08-13 12:54:44,264] ERROR in __init__: BUZZER not working
app_1 | (1) wsgi starting up on http://0.0.0.0:5000 app_1 | (1) wsgi starting up on http://0.0.0.0:5000
``` ```


The contents of this folder will be mounted to `/usr/src/craftbeerpi3` and the server will be accesible on `localhost:5000`.
The contents of this folder will be mounted to `/usr/src/craftbeerpi3` and the server will be accesible on `localhost:3000`.


## Donation ## Donation




+ 19
- 0
config/logger.yaml 查看文件

@@ -0,0 +1,19 @@
version: 1
formatters:
simple:
format: '%(asctime)s - %(levelname)s - %(name)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
file:
class : logging.handlers.RotatingFileHandler
formatter: simple
filename: ./logs/app.log
maxBytes: 10000000
backupCount: 3
root:
level: DEBUG
handlers: [console, file]

+ 19
- 7
install.sh 查看文件

@@ -20,7 +20,8 @@ show_menu () {
"8" "Reset File Changes (git reset --hard)" \ "8" "Reset File Changes (git reset --hard)" \
"9" "Clear all logs" \ "9" "Clear all logs" \
"10" "Reboot Raspberry Pi" \ "10" "Reboot Raspberry Pi" \
"11" "Stop CraftBeerPi, Clear logs, Start CraftBeerPi" 3>&1 1>&2 2>&3)
"11" "Stop CraftBeerPi, Clear logs, Start CraftBeerPi" \
"12" "Install KairosDB" 3>&1 1>&2 2>&3)


BUTTON=$? BUTTON=$?
# Exit if user pressed cancel or escape # Exit if user pressed cancel or escape
@@ -49,7 +50,7 @@ show_menu () {
apt-get -y install libpcre3-dev apt-get -y install libpcre3-dev
pip install -r requirements.txt pip install -r requirements.txt


confirmAnswer "Would you like to add active 1-wire support at your Raspberry PI now? IMPORTANT: The 1-wire thermometer must be conneted to GPIO 4!"
confirmAnswer "Would you like to add active 1-wire support at your Raspberry PI now? IMPORTANT: The 1-wire thermometer must be connected to GPIO 4!"
if [ $? = 0 ]; then if [ $? = 0 ]; then
#apt-get -y update; apt-get -y upgrade; #apt-get -y update; apt-get -y upgrade;
echo '# CraftBeerPi 1-wire support' >> "/boot/config.txt" echo '# CraftBeerPi 1-wire support' >> "/boot/config.txt"
@@ -62,14 +63,14 @@ show_menu () {
sed "s@#DIR#@${PWD}@g" config/craftbeerpiboot > /etc/init.d/craftbeerpiboot sed "s@#DIR#@${PWD}@g" config/craftbeerpiboot > /etc/init.d/craftbeerpiboot
chmod 755 /etc/init.d/craftbeerpiboot; chmod 755 /etc/init.d/craftbeerpiboot;


whiptail --title "Installition Finished" --msgbox "CraftBeerPi installation finished! You must hit OK to continue." 8 78
whiptail --title "Installation Finished" --msgbox "CraftBeerPi installation finished! You must hit OK to continue." 8 78
show_menu show_menu
;; ;;
2) 2)
confirmAnswer "Are you sure you want to clear the CraftBeerPi. All hardware setting will be deleted" confirmAnswer "Are you sure you want to clear the CraftBeerPi. All hardware setting will be deleted"
if [ $? = 0 ]; then if [ $? = 0 ]; then
sudo rm -f craftbeerpi.db sudo rm -f craftbeerpi.db
whiptail --title "Database Delted" --msgbox "The CraftBeerPi database was succesfully deleted. You must hit OK to continue." 8 78
whiptail --title "Database Deleted" --msgbox "The CraftBeerPi database was successfully deleted. You must hit OK to continue." 8 78
show_menu show_menu
else else
show_menu show_menu
@@ -81,7 +82,7 @@ show_menu () {
sed "s@#DIR#@${PWD}@g" config/craftbeerpiboot > /etc/init.d/craftbeerpiboot sed "s@#DIR#@${PWD}@g" config/craftbeerpiboot > /etc/init.d/craftbeerpiboot
chmod 755 /etc/init.d/craftbeerpiboot; chmod 755 /etc/init.d/craftbeerpiboot;
update-rc.d craftbeerpiboot defaults; update-rc.d craftbeerpiboot defaults;
whiptail --title "Added succesfull to autostart" --msgbox "The CraftBeerPi was added to autostart succesfully. You must hit OK to continue." 8 78
whiptail --title "Added successful to autostart" --msgbox "The CraftBeerPi was added to autostart successfully. You must hit OK to continue." 8 78
show_menu show_menu
else else
show_menu show_menu
@@ -104,7 +105,7 @@ show_menu () {
;; ;;
6) 6)
sudo /etc/init.d/craftbeerpiboot stop sudo /etc/init.d/craftbeerpiboot stop
whiptail --title "CraftBeerPi stoped" --msgbox "The software is stoped" 8 78
whiptail --title "CraftBeerPi stopped" --msgbox "The software is stopped" 8 78
show_menu show_menu
;; ;;
7) 7)
@@ -118,7 +119,7 @@ show_menu () {
fi fi
;; ;;
8) 8)
confirmAnswer "Are you sure you want to reset all file changes for this git respository (git reset --hard)?"
confirmAnswer "Are you sure you want to reset all file changes for this git repository (git reset --hard)?"
if [ $? = 0 ]; then if [ $? = 0 ]; then
whiptail --textbox /dev/stdin 20 50 <<<"$(git reset --hard)" whiptail --textbox /dev/stdin 20 50 <<<"$(git reset --hard)"
show_menu show_menu
@@ -155,6 +156,17 @@ show_menu () {
show_menu show_menu
fi fi
;; ;;
12)
confirmAnswer "Are you sure you want to install KairosDB?"
if [ $? = 0 ]; then
wget https://github.com/kairosdb/kairosdb/releases/download/v1.2.1/kairosdb_1.2.1-1_all.deb
sudo dpkg -i kairosdb_1.2.1-1_all.deb
sudo service kairosdb start
show_menu
else
show_menu
fi
;;
esac esac
fi fi
} }


+ 5
- 12
modules/app_config.py 查看文件

@@ -1,23 +1,16 @@
from flask import Flask, json, g
from flask_socketio import SocketIO


import json
import sys, os
from flask import Flask, render_template, redirect, json, g


from flask_socketio import SocketIO, emit

import logging


import yaml
import logging.config


from modules.core.core import CraftBeerPi, ActorBase, SensorBase from modules.core.core import CraftBeerPi, ActorBase, SensorBase
from modules.core.db import DBModel from modules.core.db import DBModel


app = Flask(__name__) app = Flask(__name__)


FORMAT = '%(asctime)-15s - %(levelname)s - %(message)s'
logging.config.dictConfig(yaml.load(open('./config/logger.yaml', 'r')))


logging.basicConfig(filename='./logs/app.log',level=logging.INFO, format=FORMAT)
app.config['SECRET_KEY'] = 'craftbeerpi' app.config['SECRET_KEY'] = 'craftbeerpi'
app.config['UPLOAD_FOLDER'] = './upload' app.config['UPLOAD_FOLDER'] = './upload'




+ 42
- 14
modules/core/core.py 查看文件

@@ -1,16 +1,14 @@
import inspect import inspect
import pprint


import sqlite3
from flask import make_response, g from flask import make_response, g
import datetime import datetime
from datetime import datetime from datetime import datetime
from flask.views import MethodView
from flask_classy import FlaskView, route


from time import localtime, strftime from time import localtime, strftime
from functools import wraps, update_wrapper from functools import wraps, update_wrapper


import requests
import json


from props import * from props import *


@@ -18,6 +16,7 @@ from hardware import *


import time import time
import uuid import uuid
import logging




class NotificationAPI(object): class NotificationAPI(object):
@@ -86,6 +85,8 @@ class SensorAPI(object):
:return: :return:
''' '''


self.logger = logging.getLogger(__name__)

self.app.logger.info("Init Sensors") self.app.logger.info("Init Sensors")


t = self.cache.get("sensor_types") t = self.cache.get("sensor_types")
@@ -145,22 +146,48 @@ class SensorAPI(object):


def receive_sensor_value(self, id, value): def receive_sensor_value(self, id, value):
self.emit("SENSOR_UPDATE", self.cache.get("sensors")[id]) self.emit("SENSOR_UPDATE", self.cache.get("sensors")[id])
self.save_to_file(id, value)
self.save_to_file(id, value, "sensor")

def save_to_file(self, id, value, prefix):
sensor_name = "%s_%s" % (prefix, str(id))
use_kairosdb = (self.cache["config"]["kairos_db"].__dict__["value"] == "YES")

if use_kairosdb:
self.write_to_tsdb(prefix, sensor_name, value)
else:
self.write_to_logfile(sensor_name, value)


def save_to_file(self, id, value, prefix="sensor"):
filename = "./logs/%s_%s.log" % (prefix, str(id))
def write_to_logfile(self, sensor_name, value):
filename = "./logs/%s.log" % sensor_name
formatted_time = strftime("%Y-%m-%d %H:%M:%S", localtime()) formatted_time = strftime("%Y-%m-%d %H:%M:%S", localtime())
msg = str(formatted_time) + "," +str(value) + "\n"
msg = str(formatted_time) + "," + str(value) + "\n"


with open(filename, "a") as file: with open(filename, "a") as file:
file.write(msg) file.write(msg)


def write_to_tsdb(self, prefix, sensor_name, value):
kairosdb_server = "http://127.0.0.1:" + self.cache["config"]["kairos_db_port"].__dict__["value"]

data = [
dict(name="cbpi." + sensor_name, datapoints=[
[int(round(time.time() * 1000)), value]
], tags={
"cbpi": prefix,
"brew": self.cache["active_brew"]
})
]

response = requests.post(kairosdb_server + "/api/v1/datapoints", json.dumps(data))
if not response.ok:
self.logger.warning("Failed to write time series entry for [%s]. Response [%s]", sensor_name, response)

def log_action(self, text): def log_action(self, text):
filename = "./logs/action.log"
formatted_time = strftime("%Y-%m-%d %H:%M:%S", localtime())
with open(filename, "a") as file:
text = text.encode("utf-8")
file.write("%s,%s\n" % (formatted_time, text))
use_kairosdb = (self.cache["config"]["kairos_db"].__dict__["value"] == "YES")

if use_kairosdb:
self.write_to_tsdb("action", "action", text)
else:
self.write_to_logfile("action", text)


def shutdown_sensor(self, id): def shutdown_sensor(self, id):
self.cache.get("sensors")[id].stop() self.cache.get("sensors")[id].stop()
@@ -204,7 +231,8 @@ class CraftBeerPi(ActorAPI, SensorAPI):
"messages": [], "messages": [],
"plugins": {}, "plugins": {},
"fermentation_controller_types": {}, "fermentation_controller_types": {},
"fermenter_task": {}
"fermenter_task": {},
"active_brew": "none"
} }
buzzer = None buzzer = None
eventbus = {} eventbus = {}


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

@@ -1,11 +1,15 @@
import datetime import datetime
import os import os
from flask import Blueprint, request, send_from_directory, json
import requests
import logging
from flask import request, send_from_directory, json
from flask_classy import FlaskView, route from flask_classy import FlaskView, route
from modules import cbpi from modules import cbpi




class LogView(FlaskView): class LogView(FlaskView):
def __init__(self):
self.logger = logging.getLogger(__name__)


@route('/', methods=['GET']) @route('/', methods=['GET'])
def get_all_logfiles(self): def get_all_logfiles(self):
@@ -17,19 +21,10 @@ class LogView(FlaskView):


@route('/actions') @route('/actions')
def actions(self): def actions(self):
filename = "./logs/action.log"
if os.path.isfile(filename) == False:
return
import csv
array = []
with open(filename, 'rb') as f:
reader = csv.reader(f)
for row in reader:
try:
array.append([int((datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") - datetime.datetime(1970, 1, 1)).total_seconds()) * 1000, row[1]])
except:
pass
return json.dumps(array)
array = self.read_log_as_json("action")
json_dumps = json.dumps(array)

return json_dumps


@route('/<file>', methods=["DELETE"]) @route('/<file>', methods=["DELETE"])
def clearlog(self, file): def clearlog(self, file):
@@ -49,24 +44,85 @@ class LogView(FlaskView):
cbpi.notify("Failed to delete log", "", type="danger") cbpi.notify("Failed to delete log", "", type="danger")
return ('', 204) return ('', 204)


def read_log_as_json(self, type, id):
filename = "./logs/%s_%s.log" % (type, id)
if os.path.isfile(filename) == False:
return
def query_tsdb(self, sensor_name):
kairosdb_server = "http://127.0.0.1:" + cbpi.cache["config"]["kairos_db_port"].__dict__["value"]

data = dict(metrics=[
{
"tags": {},
"name": "cbpi.%s" % sensor_name,
"aggregators": [
{
"name": "avg",
"align_sampling": True,
"sampling": {
"value": cbpi.cache["config"]["kairos_db_sampling_value"].__dict__["value"],
"unit": "seconds"
},
"align_start_time": True
}
]
}
],
cache_time=0,
start_relative={
"value": cbpi.cache["config"]["kairos_db_start_relative"].__dict__["value"],
"unit": "days"
})

if cbpi.cache["active_brew"] != "none":
data["metrics"][0]["tags"] = {"brew": [cbpi.cache["active_brew"]]}

self.logger.debug("query: %s", json.dumps(data))

response = requests.post(kairosdb_server + "/api/v1/datapoints/query", json.dumps(data))
if response.ok:
self.logger.debug("Fetching time series for [%s] took [%s]", sensor_name, response.elapsed)
self.logger.debug("Time series for [%s] is [%s]", sensor_name, response.json())
return response.json()["queries"][0]["results"][0]["values"]
else:
self.logger.warning("Failed to fetch time series for [%s]. Response [%s]", sensor_name, response)


import csv
def query_log(self, filename, value_type):
array = [] array = []

if not os.path.isfile(filename):
self.logger.warn("File does not exist [%s]", filename)
return array

import csv

if value_type == "float":
converter = float
else:
converter = str

with open(filename, 'rb') as f: with open(filename, 'rb') as f:
reader = csv.reader(f) reader = csv.reader(f)
for row in reader: for row in reader:
try: try:
array.append([int((datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") - datetime.datetime(1970, 1, 1)).total_seconds()) * 1000, float(row[1])])
point_of_time = int((datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S")
- datetime.datetime(1970, 1, 1)).total_seconds()) * 1000
value = converter(row[1])
array.append([point_of_time, value])
except: except:
self.logger.exception("error in reading logfile [%s]", filename)
pass pass
return array return array


def read_log_as_json(self, sensor_name):
use_kairosdb = (cbpi.cache["config"]["kairos_db"].__dict__["value"] == "YES")

if use_kairosdb:
return self.query_tsdb(sensor_name)
else:
filename = "./logs/%s.log" % sensor_name
return self.query_log(filename, "float")


def convert_chart_data_to_json(self, chart_data): 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"])}
return {"name": chart_data["name"],
"data": self.read_log_as_json(chart_data["data_type"] + "_" + str(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):
@@ -74,7 +130,8 @@ class LogView(FlaskView):
result = [] result = []
if t == "s": if t == "s":
name = cbpi.cache.get("sensors").get(id).name name = cbpi.cache.get("sensors").get(id).name
result.append({"name": name, "data": self.read_log_as_json("sensor", id)})
sensor_name = "%s_%s" % ("sensor", str(id))
result.append({"name": name, "data": self.read_log_as_json(sensor_name)})


if t == "k": if t == "k":
kettle = cbpi.cache.get("kettle").get(id) kettle = cbpi.cache.get("kettle").get(id)
@@ -82,7 +139,8 @@ class LogView(FlaskView):


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 = 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)


@@ -99,6 +157,7 @@ class LogView(FlaskView):


return True if pattern.match(name) else False return True if pattern.match(name) else False



@cbpi.initalizer() @cbpi.initalizer()
def init(app): def init(app):
""" """


+ 25
- 9
modules/recipe_import/beerxml.py 查看文件

@@ -46,13 +46,13 @@ class BeerXMLImport(FlaskView):
@route('/<int:id>', methods=['POST']) @route('/<int:id>', methods=['POST'])
def load(self, id): def load(self, id):



steps = self.getSteps(id) steps = self.getSteps(id)
boil_time_alerts = self.getBoilAlerts(id) boil_time_alerts = self.getBoilAlerts(id)
name = self.getRecipeName(id) name = self.getRecipeName(id)
self.api.set_config_parameter("brew_name", name) self.api.set_config_parameter("brew_name", name)
boil_time = self.getBoilTime(id) boil_time = self.getBoilTime(id)
mashstep_type = cbpi.get_config_parameter("step_mash", "MashStep") mashstep_type = cbpi.get_config_parameter("step_mash", "MashStep")
mashinstep_type = cbpi.get_config_parameter("step_mashin", "MashInStep")
mash_kettle = cbpi.get_config_parameter("step_mash_kettle", None) mash_kettle = cbpi.get_config_parameter("step_mash_kettle", None)


boilstep_type = cbpi.get_config_parameter("step_boil", "BoilStep") boilstep_type = cbpi.get_config_parameter("step_boil", "BoilStep")
@@ -65,10 +65,20 @@ class BeerXMLImport(FlaskView):


try: try:


# Add mash in or mash step, depends on timer > 0
for row in steps: for row in steps:
Step.insert(**{"name": row.get("name"), "type": mashstep_type, "config": {"kettle": mash_kettle, "temp": float(row.get("temp")), "timer": row.get("timer")}})
if row.get("timer") > 0:
Step.insert(**{"name": row.get("name"), "type": mashstep_type,
"config": {"kettle": mash_kettle, "temp": float(row.get("temp")),
"timer": row.get("timer")}})
else:
Step.insert(**{"name": row.get("name"), "type": mashinstep_type,
"config": {"kettle": mash_kettle, "temp": float(row.get("temp"))}})

# Add chilling step
Step.insert(**{"name": "ChilStep", "type": "ChilStep", "config": {"timer": 15}}) Step.insert(**{"name": "ChilStep", "type": "ChilStep", "config": {"timer": 15}})
## Add boiling step

# Add boiling step
Step.insert(**{ Step.insert(**{
"name": "Boil", "name": "Boil",
"type": boilstep_type, "type": boilstep_type,
@@ -76,11 +86,11 @@ class BeerXMLImport(FlaskView):
"kettle": boil_kettle, "kettle": boil_kettle,
"temp": boil_temp, "temp": boil_temp,
"timer": boil_time, "timer": boil_time,
## Beer XML defines additions as the total time spent in boiling,
## CBP defines it as time-until-alert
# Beer XML defines additions as the total time spent in boiling,
# CBP defines it as time-until-alert


## Also, The model supports five boil-time additions.
## Set the rest to None to signal them being absent
# Also, The model supports five boil-time additions.
# Set the rest to None to signal them being absent
"hop_1": boil_time - boil_time_alerts[0] if len(boil_time_alerts) >= 1 else None, "hop_1": boil_time - boil_time_alerts[0] if len(boil_time_alerts) >= 1 else None,
"hop_2": boil_time - boil_time_alerts[1] if len(boil_time_alerts) >= 2 else None, "hop_2": boil_time - boil_time_alerts[1] if len(boil_time_alerts) >= 2 else None,
"hop_3": boil_time - boil_time_alerts[2] if len(boil_time_alerts) >= 3 else None, "hop_3": boil_time - boil_time_alerts[2] if len(boil_time_alerts) >= 3 else None,
@@ -88,7 +98,8 @@ class BeerXMLImport(FlaskView):
"hop_5": boil_time - boil_time_alerts[4] if len(boil_time_alerts) >= 5 else None "hop_5": boil_time - boil_time_alerts[4] if len(boil_time_alerts) >= 5 else None
} }
}) })
## Add Whirlpool step

# Add Whirlpool step
Step.insert(**{"name": "Whirlpool", "type": "ChilStep", "config": {"timer": 15}}) Step.insert(**{"name": "Whirlpool", "type": "ChilStep", "config": {"timer": 15}})
StepView().reset() StepView().reset()
self.api.emit("UPDATE_ALL_STEPS", Step.get_all()) self.api.emit("UPDATE_ALL_STEPS", Step.get_all())
@@ -141,7 +152,12 @@ class BeerXMLImport(FlaskView):
else: else:
temp = round(9.0 / 5.0 * float(e.find("STEP_TEMP").text) + 32, 2) temp = round(9.0 / 5.0 * float(e.find("STEP_TEMP").text) + 32, 2)


steps.append({"name": e.find("NAME").text, "temp": temp, "timer": float(e.find("STEP_TIME").text)})
if e.find("STEP_TIME").text is None:
stepTime = 0.0
else:
stepTime = float(e.find("STEP_TIME").text)

steps.append({"name": e.find("NAME").text, "temp": temp, "timer": stepTime})


return steps return steps




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

@@ -1,4 +1,5 @@
import time import time
import datetime
from flask import json, request from flask import json, request
from flask_classy import route from flask_classy import route


@@ -93,6 +94,7 @@ class StepView(BaseView):
self.model.reset_all_steps() self.model.reset_all_steps()
self.stop_step() self.stop_step()
cbpi.emit("UPDATE_ALL_STEPS", self.model.get_all()) cbpi.emit("UPDATE_ALL_STEPS", self.model.get_all())
cbpi.cache["active_brew"] = "none"
return ('', 204) return ('', 204)


def stop_step(self): def stop_step(self):
@@ -142,9 +144,15 @@ class StepView(BaseView):
# set step instance to ache # set step instance to ache
cbpi.cache["active_step"] = instance cbpi.cache["active_step"] = instance


@route('/next', methods=['POST'])
@route('/start', methods=['POST']) @route('/start', methods=['POST'])
def start(self): def start(self):
if "none" == cbpi.cache["active_brew"]:
cbpi.cache["active_brew"] = cbpi.cache["config"]["brew_name"].__dict__["value"] + \
"_" + datetime.datetime.now().strftime('%y-%m-%dT%H:%M')
return self.next()

@route('/next', methods=['POST'])
def next(self):
active = Step.get_by_state("A") active = Step.get_by_state("A")
inactive = Step.get_by_state('I') inactive = Step.get_by_state('I')


@@ -163,6 +171,7 @@ class StepView(BaseView):
else: else:
cbpi.log_action("Brewing Finished") cbpi.log_action("Brewing Finished")
cbpi.notify("Brewing Finished", "You are done!", timeout=None) cbpi.notify("Brewing Finished", "You are done!", timeout=None)
cbpi.cache["active_brew"] = "none"


cbpi.emit("UPDATE_ALL_STEPS", Step.get_all()) cbpi.emit("UPDATE_ALL_STEPS", Step.get_all())
return ('', 204) return ('', 204)


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

@@ -61,6 +61,10 @@ class SystemView(FlaskView):
for t in repo.tags: for t in repo.tags:
tags.append({"name": t.name, "commit": str(t.commit), "date": t.commit.committed_date, tags.append({"name": t.name, "commit": str(t.commit), "date": t.commit.committed_date,
"committer": t.commit.committer.name, "message": t.commit.message}) "committer": t.commit.committer.name, "message": t.commit.message})
for b in repo.branches:
tags.append({"name": b.name, "commit": str(b.commit), "date": b.commit.committed_date,
"committer": b.commit.committer.name, "message": b.commit.message})
try: try:
branch_name = repo.active_branch.name branch_name = repo.active_branch.name
# test1 # test1


+ 4
- 0
update/4_kairosdb_config.sql 查看文件

@@ -0,0 +1,4 @@
INSERT OR IGNORE INTO config VALUES ('kairos_db', 'NO', 'select', 'Use timeseries database KairosDB for storing sensor values. You can install KairosDB with the CraftBeerPi installer.', '["YES","NO"]' );
INSERT OR IGNORE INTO config VALUES ('kairos_db_port', 8080, 'number', 'Port for KairosDB. We assume the DB is running on your PI, so IP-Address is 127.0.0.1.', NULL );
INSERT OR IGNORE INTO config VALUES ('kairos_db_sampling_value', 5, 'number', 'A timeseries database has the advantage to aggregate data points and therefore to reduce the transmitted data. This value sets a time span in seconds to calculate the average', NULL );
INSERT OR IGNORE INTO config VALUES ('kairos_db_start_relative', 1, 'number', 'If you have an ongoing brew or fermentation process only values related to this process will be shown in the graph. Additionally you can define in days how far the time series should reach in the past. The earliest time of both information defines when the data series starts.', NULL );

正在加载...
取消
保存