mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-23 23:48:16 +01:00
Merge pull request #120 from PiBrewing/development
merge from Development to allow for installation with pipx under bookworm
This commit is contained in:
commit
42d8a6c65d
18 changed files with 190 additions and 84 deletions
|
@ -1,3 +1,3 @@
|
|||
__version__ = "4.1.11"
|
||||
__codename__ = "Groundhog Day"
|
||||
__version__ = "4.2.0"
|
||||
__codename__ = "Indian Summer"
|
||||
|
||||
|
|
108
cbpi/cli.py
108
cbpi/cli.py
|
@ -1,6 +1,8 @@
|
|||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import requests
|
||||
from cbpi import __version__, __codename__
|
||||
from cbpi.configFolder import ConfigFolder
|
||||
from cbpi.utils.utils import load_config
|
||||
from zipfile import ZipFile
|
||||
|
@ -38,14 +40,27 @@ class CraftBeerPiCli():
|
|||
|
||||
def setup_one_wire(self):
|
||||
print("Setting up 1Wire")
|
||||
with open('/boot/config.txt', 'w') as f:
|
||||
f.write("dtoverlay=w1-gpio,gpiopin=4,pullup=on")
|
||||
with open('/boot/config.txt', 'r') as f:
|
||||
lines=f.readlines()
|
||||
lines.append("dtoverlay=w1-gpio,gpiopin=4,pullup=on")
|
||||
|
||||
configtempfile=os.path.join(self.config.get_file_path(""),"config.txt")
|
||||
|
||||
with open(configtempfile, 'w') as f:
|
||||
for line in lines:
|
||||
f.write(line)
|
||||
destfile="/boot/config.txt"
|
||||
|
||||
#copy and remove afterwards as mv will work, but raise an error message due to different file owners
|
||||
shutil.os.system('sudo cp "{}" "{}"'.format(configtempfile,destfile))
|
||||
shutil.os.system('rm -rf "{}"'.format(configtempfile))
|
||||
|
||||
print("/boot/config.txt created")
|
||||
|
||||
def list_one_wire(self):
|
||||
print("List 1Wire")
|
||||
call(["modprobe", "w1-gpio"])
|
||||
call(["modprobe", "w1-therm"])
|
||||
call(["sudo","modprobe", "w1-gpio"])
|
||||
call(["sudo","modprobe", "w1-therm"])
|
||||
try:
|
||||
for dirname in os.listdir('/sys/bus/w1/devices'):
|
||||
if (dirname.startswith("28") or dirname.startswith("10")):
|
||||
|
@ -150,16 +165,34 @@ class CraftBeerPiCli():
|
|||
else:
|
||||
print("CraftBeerPi Autostart is {}OFF{}".format(Fore.RED,Style.RESET_ALL))
|
||||
elif(name == "on"):
|
||||
user=os.getlogin()
|
||||
path="/usr/local/bin/cbpi"
|
||||
if os.path.exists("/home/"+user+"/.local/bin/cbpi") is True:
|
||||
path="/home/"+user+"/.local/bin/cbpi"
|
||||
print("Add craftbeerpi.service to systemd")
|
||||
try:
|
||||
if os.path.exists(os.path.join("/etc/systemd/system","craftbeerpi.service")) is False:
|
||||
templatefile=self.config.get_file_path("craftbeerpi.template")
|
||||
shutil.os.system('cp "{}" "{}"'.format(templatefile,self.config.get_file_path("craftbeerpi.service")))
|
||||
srcfile = self.config.get_file_path("craftbeerpi.service")
|
||||
import jinja2
|
||||
|
||||
templateLoader = jinja2.FileSystemLoader(searchpath=os.path.join(self.config.get_file_path("")))
|
||||
templateEnv = jinja2.Environment(loader=templateLoader)
|
||||
operatingsystem = str(platform.system()).lower()
|
||||
if operatingsystem.startswith("win"):
|
||||
srcfile=str(srcfile).replace('\\','/')
|
||||
|
||||
template = templateEnv.get_template("craftbeerpi.service")
|
||||
outputText = template.render(user=user, path=path)
|
||||
with open(srcfile, "w") as fh:
|
||||
fh.write(outputText)
|
||||
destfile = os.path.join("/etc/systemd/system")
|
||||
shutil.copy(srcfile, destfile)
|
||||
shutil.os.system('sudo mv "{}" "{}"'.format(srcfile,destfile))
|
||||
print("Copied craftbeerpi.service to /etc/systemd/system")
|
||||
os.system('systemctl enable craftbeerpi.service')
|
||||
shutil.os.system('sudo systemctl enable craftbeerpi.service')
|
||||
print('Enabled craftbeerpi service')
|
||||
os.system('systemctl start craftbeerpi.service')
|
||||
shutil.os.system('sudo systemctl start craftbeerpi.service')
|
||||
print('Started craftbeerpi.service')
|
||||
else:
|
||||
print("craftbeerpi.service is already located in /etc/systemd/system")
|
||||
|
@ -167,20 +200,20 @@ class CraftBeerPiCli():
|
|||
print(e)
|
||||
return
|
||||
return
|
||||
elif(name == "off"):
|
||||
elif(name == "off"):
|
||||
print("Remove craftbeerpi.service from systemd")
|
||||
try:
|
||||
status = os.popen('systemctl list-units --type=service --state=running | grep craftbeerpi.service').read()
|
||||
if status.find("craftbeerpi.service") != -1:
|
||||
os.system('systemctl stop craftbeerpi.service')
|
||||
shutil.os.system('sudo systemctl stop craftbeerpi.service')
|
||||
print('Stopped craftbeerpi service')
|
||||
os.system('systemctl disable craftbeerpi.service')
|
||||
shutil.os.system('sudo systemctl disable craftbeerpi.service')
|
||||
print('Removed craftbeerpi.service as service')
|
||||
else:
|
||||
print('craftbeerpi.service service is not running')
|
||||
|
||||
if os.path.exists(os.path.join("/etc/systemd/system","craftbeerpi.service")) is True:
|
||||
os.remove(os.path.join("/etc/systemd/system","craftbeerpi.service"))
|
||||
shutil.os.system('sudo rm -rf "{}"'.format(os.path.join("/etc/systemd/system","craftbeerpi.service")))
|
||||
print("Deleted craftbeerpi.service from /etc/systemd/system")
|
||||
else:
|
||||
print("craftbeerpi.service is not located in /etc/systemd/system")
|
||||
|
@ -188,8 +221,6 @@ class CraftBeerPiCli():
|
|||
print(e)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
def chromium(self, name):
|
||||
'''Enable or disable autostart'''
|
||||
if(name == "status"):
|
||||
|
@ -203,7 +234,7 @@ class CraftBeerPiCli():
|
|||
if os.path.exists(os.path.join("/etc/xdg/autostart/","chromium.desktop")) is False:
|
||||
srcfile = self.config.get_file_path("chromium.desktop")
|
||||
destfile = os.path.join("/etc/xdg/autostart/")
|
||||
shutil.copy(srcfile, destfile)
|
||||
shutil.os.system('sudo cp "{}" "{}"'.format(srcfile,destfile))
|
||||
print("Copied chromium.desktop to /etc/xdg/autostart/")
|
||||
else:
|
||||
print("chromium.desktop is already located in /etc/xdg/autostart/")
|
||||
|
@ -215,7 +246,7 @@ class CraftBeerPiCli():
|
|||
print("Remove chromium.desktop from /etc/xdg/autostart/")
|
||||
try:
|
||||
if os.path.exists(os.path.join("/etc/xdg/autostart/","chromium.desktop")) is True:
|
||||
os.remove(os.path.join("/etc/xdg/autostart/","chromium.desktop"))
|
||||
shutil.os.system('sudo rm -rf "{}"'.format(os.path.join("/etc/xdg/autostart/","chromium.desktop")))
|
||||
print("Deleted chromium.desktop from /etc/xdg/autostart/")
|
||||
else:
|
||||
print("chromium.desktop is not located in /etc/xdg/autostart/")
|
||||
|
@ -229,16 +260,27 @@ class CraftBeerPiCli():
|
|||
@click.pass_context
|
||||
@click.option('--config-folder-path', '-c', default="./config", type=click.Path(), help="Specify where the config folder is located. Defaults to './config'.")
|
||||
@click.option('--logs-folder-path', '-l', default="", type=click.Path(), help="Specify where the log folder is located. Defaults to '../logs' relative from the config folder.")
|
||||
@click.option('--debug-log-level', '-d', default="30", type=int, help="Specify the log level you want to write to all logs. 0=ALL, 10=DEBUG, 20=INFO 30(default)=WARNING, 40=ERROR, 50=CRITICAL")
|
||||
@click.option('--debug-log-level', '-d', default="99", type=int, help="Specify the log level you want to write to all logs. 0=ALL, 10=DEBUG, 20=INFO 30(default)=WARNING, 40=ERROR, 50=CRITICAL. Can be also set in config.yaml (debug-log-level: INT)")
|
||||
def main(context, config_folder_path, logs_folder_path, debug_log_level):
|
||||
print("---------------------")
|
||||
print("Welcome to CBPi")
|
||||
print("---------------------")
|
||||
print("--------------------------")
|
||||
print("Welcome to CBPi "+__version__)
|
||||
print("--------------------------")
|
||||
if logs_folder_path == "":
|
||||
logs_folder_path = os.path.join(Path(config_folder_path).absolute().parent, 'logs')
|
||||
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
|
||||
config=ConfigFolder(config_folder_path, logs_folder_path)
|
||||
static_config = load_config(config.get_file_path("config.yaml"))
|
||||
try:
|
||||
if debug_log_level == 99:
|
||||
debug_log_level=static_config['debug-log-level']
|
||||
except:
|
||||
debug_log_level=30
|
||||
|
||||
logging.basicConfig(format=formatter, stream=logging.StreamHandler())
|
||||
logger = logging.getLogger()
|
||||
print("*******************************")
|
||||
print("Debug-log-level is {}".format(debug_log_level))
|
||||
print("*******************************")
|
||||
logger.setLevel(debug_log_level)
|
||||
try:
|
||||
if not os.path.isdir(logs_folder_path):
|
||||
|
@ -249,7 +291,7 @@ def main(context, config_folder_path, logs_folder_path, debug_log_level):
|
|||
except Exception as e:
|
||||
logger.warning("log folder or log file could not be created or accessed. check folder and file permissions or create the logs folder somewhere you have access with a start option like '--log-folder-path=./logs'")
|
||||
logging.critical(e, exc_info=True)
|
||||
cbpi_cli = CraftBeerPiCli(ConfigFolder(config_folder_path, logs_folder_path))
|
||||
cbpi_cli = CraftBeerPiCli(config)
|
||||
context.obj = cbpi_cli
|
||||
|
||||
@main.command()
|
||||
|
@ -263,11 +305,15 @@ def setup(context):
|
|||
@click.option('--list', is_flag=True, help="List all 1Wire Devices")
|
||||
@click.option('--setup', is_flag=True, help="Setup 1Wire on Raspberry Pi")
|
||||
def onewire(context, list, setup):
|
||||
'''Setup 1wire on Raspberry Pi'''
|
||||
if setup is True:
|
||||
context.obj.setup_one_wire()
|
||||
if list is True:
|
||||
context.obj.list_one_wire()
|
||||
'''(--setup | --list) Setup 1wire on Raspberry Pi or list sensors'''
|
||||
operationsystem= sys.platform
|
||||
if not operationsystem.startswith('win'):
|
||||
if setup is True:
|
||||
context.obj.setup_one_wire()
|
||||
if list is True:
|
||||
context.obj.list_one_wire()
|
||||
else:
|
||||
print("Onewire options NOT available under Windows")
|
||||
|
||||
@main.command()
|
||||
@click.pass_context
|
||||
|
@ -297,7 +343,11 @@ def create(context, pluginname=[]):
|
|||
@click.argument('name')
|
||||
def autostart(context, name):
|
||||
'''(on|off|status) Enable or disable autostart'''
|
||||
context.obj.autostart(name)
|
||||
operationsystem= sys.platform
|
||||
if not operationsystem.startswith('win'):
|
||||
context.obj.autostart(name)
|
||||
else:
|
||||
print("Autostart option NOT available under Windows")
|
||||
|
||||
|
||||
@main.command()
|
||||
|
@ -305,4 +355,8 @@ def autostart(context, name):
|
|||
@click.argument('name')
|
||||
def chromium(context, name):
|
||||
'''(on|off|status) Enable or disable Kiosk mode'''
|
||||
context.obj.chromium(name)
|
||||
operationsystem= sys.platform
|
||||
if not operationsystem.startswith('win'):
|
||||
context.obj.chromium(name)
|
||||
else:
|
||||
print("Chromium option NOT available under Windows")
|
||||
|
|
|
@ -5,7 +5,7 @@ version: 4.0.8
|
|||
index_url: /cbpi_ui/static/index.html
|
||||
|
||||
port: 8000
|
||||
|
||||
debug-log-level: 30
|
||||
mqtt: false
|
||||
mqtt_host: localhost
|
||||
mqtt_port: 1883
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
Description=Craftbeer Pi
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/home/pi
|
||||
ExecStart=/usr/local/bin/cbpi start
|
||||
WorkingDirectory=/home/{{ user }}
|
||||
ExecStart={{ path }} start
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -94,7 +94,7 @@ class ConfigFolder:
|
|||
#['fermenter_data.json', 'file'], created by fermentation_controller @ start if not available
|
||||
#['step_data.json', 'file'], created by step_controller @ start if not available
|
||||
['config.json', 'file'],
|
||||
['craftbeerpi.service', 'file'],
|
||||
['craftbeerpi.template', 'file'],
|
||||
['chromium.desktop', 'file'],
|
||||
['dashboard', 'folder'],
|
||||
['dashboard/widgets', 'folder'],
|
||||
|
@ -106,7 +106,7 @@ class ConfigFolder:
|
|||
]
|
||||
for checking in required_config_content:
|
||||
if self.inform_missing_content(self.check_for_file_or_folder(os.path.join(self.configFolderPath, checking[0]), checking[1])):
|
||||
# since there is no complete config we now check if the config folde rmay be completely empty to show hints:
|
||||
# since there is no complete config we now check if the config folder may be completely empty to show hints:
|
||||
if len(os.listdir(os.path.join(self.configFolderPath))) == 0 :
|
||||
print("***************************************************")
|
||||
print(f"the config folder '{self.configFolderPath}' seems to be completely empty")
|
||||
|
@ -118,7 +118,7 @@ class ConfigFolder:
|
|||
print("***************************************************")
|
||||
return False
|
||||
|
||||
# if cbpi_dashboard_1.json doesnt exist at the new location (configFolderPath/dashboard)
|
||||
# if cbpi_dashboard_1.json does'nt exist at the new location (configFolderPath/dashboard)
|
||||
# we move every cbpi_dashboard_n.json file from the old location (configFolderPath) there.
|
||||
# this could be a config zip file restore from version 4.0.7.a4 or prior.
|
||||
dashboard_1_path = os.path.join(self.configFolderPath, 'dashboard', 'cbpi_dashboard_1.json')
|
||||
|
@ -132,7 +132,7 @@ class ConfigFolder:
|
|||
try:
|
||||
with open(dashboard_1_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
if (len(data['elements']) == 0): # there may exist some pathes but pathes without elements in dashboard is not very likely
|
||||
if (len(data['elements']) == 0): # there may exist some paths but paths without elements in dashboard is not very likely
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -142,6 +142,11 @@ class ConfigFolder:
|
|||
def inform_missing_content(self, whatsmissing : str):
|
||||
if whatsmissing == "":
|
||||
return False
|
||||
# Starting with cbpi 4.2.0, the craftbeerpi.service file will be created dynamically from the template file based on the user id.
|
||||
# Therefore, the service file is replaced with a template file in the config folder
|
||||
if whatsmissing.find("craftbeerpi.template"):
|
||||
self.copyDefaultFileIfNotExists("craftbeerpi.template")
|
||||
return False
|
||||
print("***************************************************")
|
||||
print(f"CraftBeerPi config content not found: {whatsmissing}")
|
||||
print("Please run 'cbpi setup' before starting the server ")
|
||||
|
@ -181,7 +186,7 @@ class ConfigFolder:
|
|||
self.copyDefaultFileIfNotExists("fermenter_data.json")
|
||||
self.copyDefaultFileIfNotExists("step_data.json")
|
||||
self.copyDefaultFileIfNotExists("config.json")
|
||||
self.copyDefaultFileIfNotExists("craftbeerpi.service")
|
||||
self.copyDefaultFileIfNotExists("craftbeerpi.template")
|
||||
self.copyDefaultFileIfNotExists("chromium.desktop")
|
||||
|
||||
print("Config Folder created")
|
||||
|
@ -206,5 +211,5 @@ class ConfigFolder:
|
|||
shutil.chown(os.path.join(dirpath, filename), owner, group)
|
||||
except:
|
||||
print("problems assigning file or folder permissions")
|
||||
print("if this happend on windows its fine")
|
||||
print("if this happend in the dev container running inside windows its also fine but you might have to rebuild the container if you run into further problems")
|
||||
print("if this happened on windows its fine")
|
||||
print("if this happened in the dev container running inside windows its also fine but you might have to rebuild the container if you run into further problems")
|
||||
|
|
|
@ -60,11 +60,19 @@ class DashboardController:
|
|||
async def get_current_dashboard(self):
|
||||
current_dashboard_number = self.cbpi.config.get("current_dashboard_number", 1)
|
||||
return current_dashboard_number
|
||||
|
||||
|
||||
async def set_current_dashboard(self, dashboard_id=1):
|
||||
await self.cbpi.config.set("current_dashboard_number", dashboard_id)
|
||||
return {"status": "OK"}
|
||||
|
||||
async def get_current_grid(self):
|
||||
current_grid = self.cbpi.config.get("current_grid", 5)
|
||||
return current_grid
|
||||
|
||||
async def set_current_grid(self, grid_width=5):
|
||||
await self.cbpi.config.set("current_grid", grid_width)
|
||||
return {"status": "OK"}
|
||||
|
||||
async def get_slow_pipe_animation(self):
|
||||
slow_pipe_animation = self.cbpi.config.get("slow_pipe_animation", "Yes")
|
||||
return slow_pipe_animation
|
|
@ -219,12 +219,12 @@ class SystemController:
|
|||
for nic, addrs in ethernet.items():
|
||||
if nic == "eth0":
|
||||
for addr in addrs:
|
||||
if str(addr.family) == "AddressFamily.AF_INET":
|
||||
if str(addr.family) == "AddressFamily.AF_INET" or str(addr.family) == "2":
|
||||
if addr.address:
|
||||
eth0IP = addr.address
|
||||
if nic == "wlan0":
|
||||
for addr in addrs:
|
||||
if str(addr.family) == "AddressFamily.AF_INET":
|
||||
if str(addr.family) == "AddressFamily.AF_INET" or str(addr.family) == "2":
|
||||
if addr.address:
|
||||
wlan0IP = addr.address
|
||||
info = psutil.net_if_stats()
|
||||
|
|
|
@ -170,7 +170,7 @@ class UploadController:
|
|||
# load beerxml file located in upload folder
|
||||
self.path = self.cbpi.config_folder.get_upload_file("kbh.db")
|
||||
if os.path.exists(self.path) is False:
|
||||
self.cbpi.notify("File Not Found", "Please upload a kbh V2 databsel file", NotificationType.ERROR)
|
||||
self.cbpi.notify("File Not Found", "Please upload a kbh V2 database file", NotificationType.ERROR)
|
||||
|
||||
try:
|
||||
# Get Recipe Nmae
|
||||
|
@ -179,19 +179,19 @@ class UploadController:
|
|||
c.execute('SELECT Sudname FROM Sud WHERE ID = ?', (Recipe_ID,))
|
||||
row = c.fetchone()
|
||||
name = row[0]
|
||||
|
||||
# get MashIn Temp
|
||||
mashin_temp = None
|
||||
c.execute('SELECT Temp FROM Rasten WHERE Typ = 0 AND SudID = ?', (Recipe_ID,))
|
||||
c.execute('SELECT TempWasser FROM Maischplan WHERE Typ = 0 AND SudID = ?', (Recipe_ID,))
|
||||
row = c.fetchone()
|
||||
try:
|
||||
if self.cbpi.config.get("TEMP_UNIT", "C") == "C":
|
||||
mashin_temp = str(int(row[0]))
|
||||
mashin_temp = str(float(row[0]))
|
||||
else:
|
||||
mashin_temp = str(round(9.0 / 5.0 * int(row[0]) + 32))
|
||||
mashin_temp = str(round(9.0 / 5.0 * float(row[0]) + 32))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
logging.error(mashin_temp)
|
||||
# get the hop addition times
|
||||
c.execute('SELECT Zeit, Name FROM Hopfengaben WHERE Vorderwuerze <> 1 AND SudID = ?', (Recipe_ID,))
|
||||
hops = c.fetchall()
|
||||
|
@ -201,11 +201,9 @@ class UploadController:
|
|||
whirlpool.append(hop)
|
||||
for whirl in whirlpool:
|
||||
hops.remove(whirl)
|
||||
|
||||
# get the misc addition times
|
||||
c.execute('SELECT Zugabedauer, Name FROM WeitereZutatenGaben WHERE Zeitpunkt = 1 AND SudID = ?', (Recipe_ID,))
|
||||
miscs = c.fetchall()
|
||||
|
||||
try:
|
||||
c.execute('SELECT Zeit, Name FROM Hopfengaben WHERE Vorderwuerze = 1 AND SudID = ?', (Recipe_ID,))
|
||||
FW_Hops = c.fetchall()
|
||||
|
@ -216,9 +214,7 @@ class UploadController:
|
|||
c.execute('SELECT Kochdauer FROM Sud WHERE ID = ?', (Recipe_ID,))
|
||||
row = c.fetchone()
|
||||
BoilTime = str(int(row[0]))
|
||||
|
||||
|
||||
|
||||
|
||||
await self.create_recipe(name)
|
||||
|
||||
if mashin_temp is not None:
|
||||
|
@ -238,7 +234,7 @@ class UploadController:
|
|||
}
|
||||
await self.create_step(step_string)
|
||||
|
||||
for row in c.execute('SELECT Name, Temp, Dauer FROM Rasten WHERE Typ <> 0 AND SudID = ?', (Recipe_ID,)):
|
||||
for row in c.execute('SELECT Name, TempRast, DauerRast FROM Maischplan WHERE Typ <> 0 AND SudID = ?', (Recipe_ID,)):
|
||||
if mashin_temp is None and self.addmashin == "Yes":
|
||||
step_type = self.mashin if self.mashin != "" else "MashInStep"
|
||||
step_string = { "name": "MashIn",
|
||||
|
@ -246,7 +242,7 @@ class UploadController:
|
|||
"AutoMode": self.AutoMode,
|
||||
"Kettle": self.id,
|
||||
"Sensor": self.kettle.sensor,
|
||||
"Temp": str(int(row[1])) if self.TEMP_UNIT == "C" else str(round(9.0 / 5.0 * int(row[1]) + 32)),
|
||||
"Temp": str(float(row[1])) if self.TEMP_UNIT == "C" else str(round(9.0 / 5.0 * float(row[1]) + 32)),
|
||||
"Timer": "0",
|
||||
"Notification": "Target temperature reached. Please add malt."
|
||||
},
|
||||
|
@ -263,7 +259,7 @@ class UploadController:
|
|||
"AutoMode": self.AutoMode,
|
||||
"Kettle": self.id,
|
||||
"Sensor": self.kettle.sensor,
|
||||
"Temp": str(int(row[1])) if self.TEMP_UNIT == "C" else str(round(9.0 / 5.0 * int(row[1]) + 32)),
|
||||
"Temp": str(float(row[1])) if self.TEMP_UNIT == "C" else str(round(9.0 / 5.0 * float(row[1]) + 32)),
|
||||
"Timer": str(int(row[2]))
|
||||
},
|
||||
"status_text": "",
|
||||
|
|
|
@ -260,9 +260,9 @@ class CraftBeerPi:
|
|||
def _print_logo(self):
|
||||
from pyfiglet import Figlet
|
||||
f = Figlet(font='big')
|
||||
logger.info("\n%s" % f.renderText("CraftBeerPi %s " % self.version))
|
||||
logger.info("www.CraftBeerPi.com")
|
||||
logger.info("(c) 2021/2022 Manuel Fritsch / Alexander Vollkopf")
|
||||
logger.warning("\n%s" % f.renderText("CraftBeerPi %s " % self.version))
|
||||
logger.warning("www.CraftBeerPi.com")
|
||||
logger.warning("(c) 2021/2022/2023 Manuel Fritsch / Alexander Vollkopf")
|
||||
|
||||
def _setup_http_index(self):
|
||||
async def http_index(request):
|
||||
|
|
|
@ -64,6 +64,7 @@ class ConfigUpdate(CBPiExtension):
|
|||
BoilKettle = self.cbpi.config.get("BoilKettle", None)
|
||||
CONFIG_STATUS = self.cbpi.config.get("CONFIG_STATUS", None)
|
||||
self.version=__version__
|
||||
current_grid = self.cbpi.config.get("current_grid", None)
|
||||
|
||||
|
||||
if boil_temp is None:
|
||||
|
@ -491,6 +492,16 @@ class ConfigUpdate(CBPiExtension):
|
|||
source="steps",
|
||||
options=[{"label": "Yes", "value": "Yes"},
|
||||
{"label": "No", "value": "No"}])
|
||||
|
||||
if current_grid is None:
|
||||
logger.info("INIT Current Dashboard Number")
|
||||
try:
|
||||
await self.cbpi.config.add("current_grid", 5, type=ConfigType.NUMBER, description="Dashboard Grid Width",source="hidden")
|
||||
except:
|
||||
logger.warning('Unable to update database')
|
||||
else:
|
||||
if CONFIG_STATUS is None or CONFIG_STATUS != self.version:
|
||||
await self.cbpi.config.add("current_grid", current_grid, type=ConfigType.NUMBER, description="Dashboard Grid Width",source="hidden")
|
||||
|
||||
|
||||
|
||||
|
@ -503,6 +514,8 @@ class ConfigUpdate(CBPiExtension):
|
|||
logger.warning('Unable to update config')
|
||||
|
||||
|
||||
|
||||
|
||||
def setup(cbpi):
|
||||
cbpi.plugin.register("ConfigUpdate", ConfigUpdate)
|
||||
pass
|
||||
|
|
|
@ -170,7 +170,7 @@ def setup(cbpi):
|
|||
cbpi.plugin.register("OneWire", OneWire)
|
||||
try:
|
||||
# Global Init
|
||||
call(["modprobe", "w1-gpio"])
|
||||
call(["modprobe", "w1-therm"])
|
||||
call(["sudo","modprobe", "w1-gpio"])
|
||||
call(["sudo","modprobe", "w1-therm"])
|
||||
except Exception as e:
|
||||
pass
|
||||
|
|
|
@ -156,6 +156,40 @@ class DashBoardHttpEndpoints:
|
|||
"""
|
||||
dashboard_id = int(request.match_info['id'])
|
||||
return web.json_response(await self.cbpi.dashboard.set_current_dashboard(dashboard_id))
|
||||
|
||||
@request_mapping(path="/currentgrid", method="GET", auth_required=False)
|
||||
async def get_current_grid(self, request):
|
||||
"""
|
||||
---
|
||||
description: Get Dashboard Numbers
|
||||
tags:
|
||||
- Dashboard
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
"""
|
||||
return web.json_response(await self.cbpi.dashboard.get_current_grid(), dumps=json_dumps)
|
||||
|
||||
@request_mapping(path="/{width}/currentgrid", method="POST", auth_required=False)
|
||||
async def set_current_grid(self, request):
|
||||
"""
|
||||
---
|
||||
description: Set Current Grid Width
|
||||
tags:
|
||||
- Dashboard
|
||||
parameters:
|
||||
- name: "width"
|
||||
in: "path"
|
||||
description: "Grid Width"
|
||||
required: true
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
"""
|
||||
grid_width = int(request.match_info['width'])
|
||||
return web.json_response(await self.cbpi.dashboard.set_current_grid(grid_width))
|
||||
|
||||
@request_mapping(path="/slowPipeAnimation", method="GET", auth_required=False)
|
||||
async def get_slow_pipe_animation(self, request):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
typing-extensions>=4
|
||||
aiohttp==3.8.5
|
||||
aiohttp==3.8.6
|
||||
aiohttp-auth==0.1.1
|
||||
aiohttp-route-decorator==0.1.4
|
||||
aiohttp-security==0.4.0
|
||||
|
@ -7,22 +7,22 @@ aiohttp-session==2.12.0
|
|||
aiohttp-swagger==1.0.16
|
||||
aiojobs==1.1.0
|
||||
aiosqlite==0.17.0
|
||||
cryptography==41.0.2
|
||||
pyopenssl==23.2.0
|
||||
cryptography==41.0.5
|
||||
pyopenssl==23.3.0
|
||||
requests==2.31.0
|
||||
voluptuous==0.13.1
|
||||
pyfiglet==0.8.post1
|
||||
pyfiglet==1.0.2
|
||||
pandas==1.5.3
|
||||
shortuuid==1.0.11
|
||||
tabulate==0.9.0
|
||||
numpy==1.24.1
|
||||
cbpi4gui
|
||||
click==8.1.3
|
||||
click==8.1.7
|
||||
importlib_metadata==4.11.1
|
||||
aiomqtt==1.0.0
|
||||
psutil==5.9.4
|
||||
aiomqtt==1.2.1
|
||||
psutil==5.9.6
|
||||
zipp>=0.5
|
||||
colorama==0.4.6
|
||||
pytest-aiohttp
|
||||
coverage==6.3.1
|
||||
inquirer==3.1.1
|
||||
inquirer==3.1.3
|
||||
|
|
16
setup.py
16
setup.py
|
@ -39,7 +39,7 @@ setup(name='cbpi4',
|
|||
long_description_content_type='text/markdown',
|
||||
install_requires=[
|
||||
"typing-extensions>=4",
|
||||
"aiohttp==3.8.5",
|
||||
"aiohttp==3.8.6",
|
||||
"aiohttp-auth==0.1.1",
|
||||
"aiohttp-route-decorator==0.1.4",
|
||||
"aiohttp-security==0.4.0",
|
||||
|
@ -47,18 +47,18 @@ setup(name='cbpi4',
|
|||
"aiohttp-swagger==1.0.16",
|
||||
"aiojobs==1.1.0 ",
|
||||
"aiosqlite==0.17.0",
|
||||
"cryptography==41.0.2",
|
||||
"pyopenssl==23.2.0",
|
||||
"cryptography==41.0.5",
|
||||
"pyopenssl==23.3.0",
|
||||
"requests==2.31.0",
|
||||
"voluptuous==0.13.1",
|
||||
"pyfiglet==0.8.post1",
|
||||
'click==8.1.3',
|
||||
"pyfiglet==1.0.2",
|
||||
'click==8.1.7',
|
||||
'shortuuid==1.0.11',
|
||||
'tabulate==0.9.0',
|
||||
'aiomqtt==1.0.0',
|
||||
'inquirer==3.1.1',
|
||||
'aiomqtt==1.2.1',
|
||||
'inquirer==3.1.3',
|
||||
'colorama==0.4.6',
|
||||
'psutil==5.9.4',
|
||||
'psutil==5.9.6',
|
||||
'cbpi4gui',
|
||||
'importlib_metadata',
|
||||
'numpy==1.24.1',
|
||||
|
|
|
@ -80,10 +80,10 @@
|
|||
"options": null,
|
||||
"source": "hidden",
|
||||
"type": "string",
|
||||
"value": "4.1.10.a1"
|
||||
"value": "4.2.0.a6"
|
||||
},
|
||||
"CSVLOGFILES": {
|
||||
"description": "Write sensor data to csv logfiles",
|
||||
"description": "Write sensor data to csv logfiles (enabling requires restart)",
|
||||
"name": "CSVLOGFILES",
|
||||
"options": [
|
||||
{
|
||||
|
@ -100,7 +100,7 @@
|
|||
"value": "Yes"
|
||||
},
|
||||
"INFLUXDB": {
|
||||
"description": "Write sensor data to influxdb",
|
||||
"description": "Write sensor data to influxdb (enabling requires restart)",
|
||||
"name": "INFLUXDB",
|
||||
"options": [
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@ from tests.cbpi_config_fixture import CraftBeerPiTestCase
|
|||
|
||||
class SensorTestCase(CraftBeerPiTestCase):
|
||||
|
||||
@unittest_run_loop
|
||||
async def test_crud(self):
|
||||
|
||||
data = {
|
||||
|
|
|
@ -4,7 +4,6 @@ from tests.cbpi_config_fixture import CraftBeerPiTestCase
|
|||
|
||||
class StepTestCase(CraftBeerPiTestCase):
|
||||
|
||||
@unittest_run_loop
|
||||
async def test_get(self):
|
||||
|
||||
resp = await self.client.request("GET", "/step2")
|
||||
|
@ -12,7 +11,6 @@ class StepTestCase(CraftBeerPiTestCase):
|
|||
assert resp.status == 200
|
||||
|
||||
|
||||
@unittest_run_loop
|
||||
async def test_crud(self):
|
||||
data = {
|
||||
"name": "Test",
|
||||
|
|
|
@ -4,7 +4,6 @@ from tests.cbpi_config_fixture import CraftBeerPiTestCase
|
|||
|
||||
class IndexTestCase(CraftBeerPiTestCase):
|
||||
|
||||
@unittest_run_loop
|
||||
async def test_endpoints(self):
|
||||
# Test Index Page
|
||||
resp = await self.client.post(path="/system/restart")
|
||||
|
|
Loading…
Reference in a new issue