mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-10 01:17:42 +01:00
Merge branch 'development' into master
This commit is contained in:
commit
49e8488c0b
13 changed files with 180 additions and 22 deletions
|
@ -1,2 +1 @@
|
|||
__version__ = "4.0.1.2"
|
||||
|
||||
__version__ = "4.0.1.12"
|
||||
|
|
|
@ -51,10 +51,10 @@ class CBPiBase(metaclass=ABCMeta):
|
|||
def get_actor_state(self,id):
|
||||
try:
|
||||
actor = self.cbpi.actor.find_by_id(id)
|
||||
return actor.get("instance").get_state()
|
||||
return actor.instance.state
|
||||
except:
|
||||
logging.error("Failed to read actor state in step - actor {}".format(id))
|
||||
return None
|
||||
return False
|
||||
|
||||
async def actor_on(self,id,power=100):
|
||||
|
||||
|
|
14
cbpi/cli.py
14
cbpi/cli.py
|
@ -10,6 +10,7 @@ from cbpi.utils.utils import load_config
|
|||
from zipfile import ZipFile
|
||||
from cbpi.craftbeerpi import CraftBeerPi
|
||||
import os
|
||||
import platform
|
||||
import pathlib
|
||||
import shutil
|
||||
import yaml
|
||||
|
@ -152,14 +153,19 @@ def check_for_setup():
|
|||
if zip_content == True:
|
||||
print("Found correct content. Starting Restore process")
|
||||
output_path = pathlib.Path(os.path.join(".", 'config'))
|
||||
owner = output_path.owner()
|
||||
group = output_path.group()
|
||||
system = platform.system()
|
||||
print(system)
|
||||
if system != "Windows":
|
||||
owner = output_path.owner()
|
||||
group = output_path.group()
|
||||
print("Removing old config folder")
|
||||
shutil.rmtree(output_path, ignore_errors=True)
|
||||
print("Extracting zip file to config folder")
|
||||
zip.extractall(output_path)
|
||||
print("Changing owner and group of config folder recursively to {}:{}".format(owner,group))
|
||||
recursive_chown(output_path, owner, group)
|
||||
zip.close()
|
||||
if system != "Windows":
|
||||
print("Changing owner and group of config folder recursively to {}:{}".format(owner,group))
|
||||
recursive_chown(output_path, owner, group)
|
||||
print("Removing backup file")
|
||||
os.remove(backupfile)
|
||||
else:
|
||||
|
|
|
@ -9,7 +9,6 @@ class ActorController(BasicController):
|
|||
self.update_key = "actorupdate"
|
||||
|
||||
async def on(self, id, power=None):
|
||||
# logging.info("Controller_power: {}".format(power))
|
||||
try:
|
||||
item = self.find_by_id(id)
|
||||
if power is None:
|
||||
|
@ -20,7 +19,8 @@ class ActorController(BasicController):
|
|||
power = 100
|
||||
if item.instance.state is False:
|
||||
await item.instance.on(power)
|
||||
await self.push_udpate()
|
||||
#await self.push_udpate()
|
||||
self.cbpi.ws.send(dict(topic=self.update_key, data=list(map(lambda item: item.to_dict(), self.data))))
|
||||
self.cbpi.push_update("cbpi/actorupdate/{}".format(id), item.to_dict(), True)
|
||||
else:
|
||||
await self.set_power(id, power)
|
||||
|
@ -33,7 +33,8 @@ class ActorController(BasicController):
|
|||
item = self.find_by_id(id)
|
||||
if item.instance.state is True:
|
||||
await item.instance.off()
|
||||
await self.push_udpate()
|
||||
#await self.push_udpate()
|
||||
self.cbpi.ws.send(dict(topic=self.update_key, data=list(map(lambda item: item.to_dict(), self.data))))
|
||||
self.cbpi.push_update("cbpi/actorupdate/{}".format(id), item.to_dict())
|
||||
except Exception as e:
|
||||
logging.error("Failed to switch on Actor {} {}".format(id, e), True)
|
||||
|
@ -43,6 +44,7 @@ class ActorController(BasicController):
|
|||
item = self.find_by_id(id)
|
||||
instance = item.get("instance")
|
||||
await instance.toggle()
|
||||
self.cbpi.ws.send(dict(topic=self.update_key, data=list(map(lambda item: item.to_dict(), self.data))))
|
||||
self.cbpi.push_update("cbpi/actorupdate/{}".format(id), item.to_dict())
|
||||
except Exception as e:
|
||||
logging.error("Failed to toggle Actor {} {}".format(id, e))
|
||||
|
@ -58,7 +60,8 @@ class ActorController(BasicController):
|
|||
try:
|
||||
item = self.find_by_id(id)
|
||||
item.power = round(power)
|
||||
await self.push_udpate()
|
||||
#await self.push_udpate()
|
||||
self.cbpi.ws.send(dict(topic=self.update_key, data=list(map(lambda item: item.to_dict(), self.data))))
|
||||
self.cbpi.push_update("cbpi/actorupdate/{}".format(id), item.to_dict())
|
||||
except Exception as e:
|
||||
logging.error("Failed to update Actor {} {}".format(id, e))
|
||||
|
|
|
@ -199,7 +199,8 @@ class FermentationController:
|
|||
|
||||
def get_state(self):
|
||||
if self.data == []:
|
||||
logging.info(self.data)
|
||||
#logging.info(self.data)
|
||||
pass
|
||||
|
||||
return {"data": list(map(lambda x: x.to_dict(), self.data)), "types":self.get_types(), "steptypes":self.get_steptypes()}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from re import M
|
||||
|
@ -8,11 +7,14 @@ from contextlib import AsyncExitStack, asynccontextmanager
|
|||
from cbpi import __version__
|
||||
import logging
|
||||
|
||||
|
||||
class SatelliteController:
|
||||
|
||||
def __init__(self, cbpi):
|
||||
self.cbpi = cbpi
|
||||
self.kettlecontroller = cbpi.kettle
|
||||
self.fermentercontroller = cbpi.fermenter
|
||||
self.sensorcontroller = cbpi.sensor
|
||||
self.actorcontroller = cbpi.actor
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.host = cbpi.static_config.get("mqtt_host", "localhost")
|
||||
self.port = cbpi.static_config.get("mqtt_port", 1883)
|
||||
|
@ -23,6 +25,11 @@ class SatelliteController:
|
|||
("cbpi/actor/+/on", self._actor_on),
|
||||
("cbpi/actor/+/off", self._actor_off),
|
||||
("cbpi/actor/+/power", self._actor_power),
|
||||
("cbpi/updateactor", self._actorupdate),
|
||||
("cbpi/updatekettle", self._kettleupdate),
|
||||
("cbpi/updatesensor", self._sensorupdate),
|
||||
("cbpi/updatefermenter", self._fermenterupdate),
|
||||
|
||||
]
|
||||
self.tasks = set()
|
||||
|
||||
|
@ -63,12 +70,48 @@ class SatelliteController:
|
|||
if power < 0:
|
||||
power = 0
|
||||
await self.cbpi.actor.set_power(topic_key[2],power)
|
||||
await self.cbpi.actor.actor_update(topic_key[2],power)
|
||||
#await self.cbpi.actor.actor_update(topic_key[2],power)
|
||||
except:
|
||||
self.logger.warning("Failed to set actor power via mqtt. No valid power in message")
|
||||
except:
|
||||
self.logger.warning("Failed to set actor power via mqtt")
|
||||
|
||||
async def _kettleupdate(self, messages):
|
||||
async for message in messages:
|
||||
try:
|
||||
self.kettle=self.kettlecontroller.get_state()
|
||||
for item in self.kettle['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("kettleupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
self.logger.warning("Failed to send kettleupdate via mqtt: {}".format(e))
|
||||
|
||||
async def _fermenterupdate(self, messages):
|
||||
async for message in messages:
|
||||
try:
|
||||
self.fermenter=self.fermentercontroller.get_state()
|
||||
for item in self.fermenter['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("fermenterupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
self.logger.warning("Failed to send fermenterupdate via mqtt: {}".format(e))
|
||||
|
||||
async def _actorupdate(self, messages):
|
||||
async for message in messages:
|
||||
try:
|
||||
self.actor=self.actorcontroller.get_state()
|
||||
for item in self.actor['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("actorupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
self.logger.warning("Failed to send actorupdate via mqtt: {}".format(e))
|
||||
|
||||
async def _sensorupdate(self, messages):
|
||||
async for message in messages:
|
||||
try:
|
||||
self.sensor=self.sensorcontroller.get_state()
|
||||
for item in self.sensor['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("sensorupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
self.logger.warning("Failed to send sensorupdate via mqtt: {}".format(e))
|
||||
|
||||
def subcribe(self, topic, method):
|
||||
task = asyncio.create_task(self._subcribe(topic, method))
|
||||
return task
|
||||
|
|
|
@ -977,7 +977,8 @@ class UploadController:
|
|||
"Kettle": self.boilid,
|
||||
"Timer": step_timer,
|
||||
"Temp": step_temp,
|
||||
"Sensor": cooldown_sensor
|
||||
"Sensor": cooldown_sensor,
|
||||
"Actor": self.CoolDownActor
|
||||
},
|
||||
"status_text": "",
|
||||
"status": "I",
|
||||
|
@ -1001,6 +1002,7 @@ class UploadController:
|
|||
self.BoilTemp = self.cbpi.config.get("steps_boil_temp", 98)
|
||||
#get default cooldown temp alarm setting
|
||||
self.CoolDownTemp = self.cbpi.config.get("steps_cooldown_temp", 25)
|
||||
self.CoolDownActor = self.cbpi.config.get("steps_cooldown_actor", None)
|
||||
# get default Kettle from Settings
|
||||
self.id = self.cbpi.config.get('MASH_TUN', None)
|
||||
self.boilid = self.cbpi.config.get('BoilKettle', None)
|
||||
|
@ -1030,6 +1032,7 @@ class UploadController:
|
|||
"cooldown": str(self.cooldown),
|
||||
"boiltemp": str(self.BoilTemp),
|
||||
"cooldowntemp": str(self.CoolDownTemp),
|
||||
"cooldownactor": self.CoolDownActor,
|
||||
"temp_unit": str(self.TEMP_UNIT),
|
||||
"AutoMode": str(self.AutoMode)
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ class CraftBeerPi:
|
|||
self.log = LogController(self)
|
||||
self.system = SystemController(self)
|
||||
self.kettle = KettleController(self)
|
||||
self.fermenter : FermentationController = FermentationController(self)
|
||||
self.step : StepController = StepController(self)
|
||||
self.recipe : RecipeController = RecipeController(self)
|
||||
self.upload : UploadController = UploadController(self)
|
||||
|
@ -117,7 +118,6 @@ class CraftBeerPi:
|
|||
if str(self.static_config.get("mqtt", False)).lower() == "true":
|
||||
self.satellite: SatelliteController = SatelliteController(self)
|
||||
self.dashboard = DashboardController(self)
|
||||
self.fermenter : FermentationController = FermentationController(self)
|
||||
|
||||
self.http_step = StepHttpEndpoints(self)
|
||||
self.http_recipe = RecipeHttpEndpoints(self)
|
||||
|
|
|
@ -28,6 +28,7 @@ class ConfigUpdate(CBPiExtension):
|
|||
default_cool_temp = 20 if TEMP_UNIT == "C" else 68
|
||||
boil_temp = self.cbpi.config.get("steps_boil_temp", None)
|
||||
cooldown_sensor = self.cbpi.config.get("steps_cooldown_sensor", None)
|
||||
cooldown_actor = self.cbpi.config.get("steps_cooldown_actor", None)
|
||||
cooldown_temp = self.cbpi.config.get("steps_cooldown_temp", None)
|
||||
mashin_step = self.cbpi.config.get("steps_mashin", None)
|
||||
mash_step = self.cbpi.config.get("steps_mash", None)
|
||||
|
@ -44,6 +45,7 @@ class ConfigUpdate(CBPiExtension):
|
|||
influxdbuser = self.cbpi.config.get("INFLUXDBUSER", None)
|
||||
influxdbpwd = self.cbpi.config.get("INFLUXDBPWD", None)
|
||||
influxdbcloud = self.cbpi.config.get("INFLUXDBCLOUD", None)
|
||||
mqttupdate = self.cbpi.config.get("MQTTUpdate", None)
|
||||
|
||||
|
||||
|
||||
|
@ -61,6 +63,13 @@ class ConfigUpdate(CBPiExtension):
|
|||
except:
|
||||
logger.warning('Unable to update database')
|
||||
|
||||
if cooldown_actor is None:
|
||||
logger.info("INIT Cooldown Actor Setting")
|
||||
try:
|
||||
await self.cbpi.config.add("steps_cooldown_actor", "", ConfigType.ACTOR, "Actor to trigger cooldown water on and off (default: None)")
|
||||
except:
|
||||
logger.warning('Unable to update database')
|
||||
|
||||
if cooldown_temp is None:
|
||||
logger.info("INIT Cooldown Temp Setting")
|
||||
try:
|
||||
|
@ -255,6 +264,19 @@ class ConfigUpdate(CBPiExtension):
|
|||
except:
|
||||
logger.warning('Unable to update config')
|
||||
|
||||
if mqttupdate is None:
|
||||
logger.info("INIT MQTT update frequency for Kettles and Fermenters")
|
||||
try:
|
||||
await self.cbpi.config.add("MQTTUpdate", 0, ConfigType.SELECT, "Forced MQTT Update frequency in s for Kettle and Fermenter (no changes in payload required). Restart required after change",
|
||||
[{"label": "30", "value": 30},
|
||||
{"label": "60", "value": 60},
|
||||
{"label": "120", "value": 120},
|
||||
{"label": "300", "value": 300},
|
||||
{"label": "Never", "value": 0}])
|
||||
except:
|
||||
logger.warning('Unable to update database')
|
||||
|
||||
|
||||
def setup(cbpi):
|
||||
cbpi.plugin.register("ConfigUpdate", ConfigUpdate)
|
||||
pass
|
||||
|
|
74
cbpi/extension/mqtt_util/__init__.py
Normal file
74
cbpi/extension/mqtt_util/__init__.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
import logging
|
||||
import asyncio
|
||||
from cbpi.api import *
|
||||
from cbpi.api.config import ConfigType
|
||||
from cbpi.api.base import CBPiBase
|
||||
from cbpi.controller.fermentation_controller import FermentationController
|
||||
from cbpi.controller.kettle_controller import KettleController
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class MQTTUtil(CBPiExtension):
|
||||
|
||||
def __init__(self,cbpi):
|
||||
self.cbpi = cbpi
|
||||
self.kettlecontroller = cbpi.kettle
|
||||
self.fermentationcontroller = cbpi.fermenter
|
||||
# sensor and actor update is done anyhow during startup
|
||||
# self.sensorcontroller = cbpi.sensor
|
||||
# self.actorcontroller = cbpi.actor
|
||||
|
||||
self.mqttupdate = int(self.cbpi.config.get("MQTTUpdate", 0))
|
||||
if self.mqttupdate != 0:
|
||||
self._task = asyncio.create_task(self.run())
|
||||
logger.info("INIT MQTTUtil")
|
||||
else:
|
||||
self._task = asyncio.create_task(self.push_once())
|
||||
|
||||
async def push_once(self):
|
||||
# wait some time to ensure that kettlecontroller is started
|
||||
await asyncio.sleep(5)
|
||||
self.push_update()
|
||||
|
||||
|
||||
async def run(self):
|
||||
|
||||
while True:
|
||||
self.push_update()
|
||||
await asyncio.sleep(self.mqttupdate)
|
||||
|
||||
def push_update(self):
|
||||
# try:
|
||||
# self.actor=self.actorcontroller.get_state()
|
||||
# for item in self.actor['data']:
|
||||
# self.cbpi.push_update("cbpi/{}/{}".format("actorupdate",item['id']), item)
|
||||
# except Exception as e:
|
||||
# logging.error(e)
|
||||
# pass
|
||||
# try:
|
||||
# self.sensor=self.sensorcontroller.get_state()
|
||||
# for item in self.sensor['data']:
|
||||
# self.cbpi.push_update("cbpi/{}/{}".format("sensorupdate",item['id']), item)
|
||||
# except Exception as e:
|
||||
# logging.error(e)
|
||||
# pass
|
||||
try:
|
||||
self.kettle=self.kettlecontroller.get_state()
|
||||
for item in self.kettle['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("kettleupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
pass
|
||||
try:
|
||||
self.fermenter=self.fermentationcontroller.get_state()
|
||||
for item in self.fermenter['data']:
|
||||
self.cbpi.push_update("cbpi/{}/{}".format("fermenterupdate",item['id']), item)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
pass
|
||||
|
||||
|
||||
def setup(cbpi):
|
||||
if str(cbpi.static_config.get("mqtt", False)).lower() == "true":
|
||||
cbpi.plugin.register("MQTTUtil", MQTTUtil)
|
||||
pass
|
3
cbpi/extension/mqtt_util/config.yaml
Normal file
3
cbpi/extension/mqtt_util/config.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
name: MQTTUtil
|
||||
version: 4
|
||||
active: true
|
|
@ -41,7 +41,7 @@ class ReadThread (threading.Thread):
|
|||
try:
|
||||
if self.sensor_name is None:
|
||||
return
|
||||
with open('/sys/bus/w1/devices/w1_bus_master1/%s/w1_slave' % self.sensor_name, 'r') as content_file:
|
||||
with open('/sys/bus/w1/devices/%s/w1_slave' % self.sensor_name, 'r') as content_file:
|
||||
content = content_file.read()
|
||||
if (content.split('\n')[0].split(' ')[11] == "YES"):
|
||||
temp = float(content.split("=")[-1]) / 1000 # temp in Celcius
|
||||
|
|
|
@ -32,7 +32,11 @@ class CBPiWebSocket:
|
|||
self.logger.debug("broadcast to ws clients. Data: %s" % data)
|
||||
for ws in self._clients:
|
||||
async def send_data(ws, data):
|
||||
await ws.send_json(data=data, dumps=json_dumps)
|
||||
try:
|
||||
await ws.send_json(data=data, dumps=json_dumps)
|
||||
except Exception as e:
|
||||
self.logger.error("Error with client %s: %s" % (ws, str(e)))
|
||||
|
||||
self.cbpi.app.loop.create_task(send_data(ws, data))
|
||||
|
||||
async def websocket_handler(self, request):
|
||||
|
|
Loading…
Reference in a new issue