diff --git a/cbpi/api/__init__.py b/cbpi/api/__init__.py index c265b9a3..2a3d8008 100644 --- a/cbpi/api/__init__.py +++ b/cbpi/api/__init__.py @@ -9,8 +9,10 @@ "parameters", "background_task", "CBPiKettleLogic", + "CBPiFermenterLogic", "CBPiException", "KettleException", + "FermenterException", "SensorException", "ActorException", "CBPiSensor", @@ -22,5 +24,6 @@ from cbpi.api.property import * from cbpi.api.decorator import * from cbpi.api.kettle_logic import * +from cbpi.api.fermenter_logic import * from cbpi.api.step import * from cbpi.api.exceptions import * \ No newline at end of file diff --git a/cbpi/api/base.py b/cbpi/api/base.py index 6b303984..83e7363d 100644 --- a/cbpi/api/base.py +++ b/cbpi/api/base.py @@ -28,6 +28,15 @@ def get_kettle_target_temp(self,id): async def set_target_temp(self,id, temp): await self.cbpi.kettle.set_target_temp(id, temp) + + def get_fermenter(self,id): + return self.cbpi.fermenter.find_by_id(id) + + def get_fermenter_target_temp(self,id): + return self.cbpi.fermenter.find_by_id(id).target_temp + + async def set_fermenter_target_temp(self,id, temp): + await self.cbpi.fermenter.set_target_temp(id, temp) def get_sensor(self,id): return self.cbpi.sensor.find_by_id(id) diff --git a/cbpi/api/config.py b/cbpi/api/config.py index 0188d653..c383f5ea 100644 --- a/cbpi/api/config.py +++ b/cbpi/api/config.py @@ -5,6 +5,7 @@ class ConfigType(Enum): NUMBER = "number" SELECT = "select" KETTLE = "kettle" + FERMENTER = "fermenter" ACTOR = "actor" SENSOR = "sensor" diff --git a/cbpi/api/dataclasses.py b/cbpi/api/dataclasses.py index ebba8647..8e895b7a 100644 --- a/cbpi/api/dataclasses.py +++ b/cbpi/api/dataclasses.py @@ -102,6 +102,29 @@ def to_dict(self): state = False return dict(id=self.id, name=self.name, state=state, target_temp=self.target_temp, heater=self.heater, agitator=self.agitator, sensor=self.sensor, type=self.type, props=self.props.to_dict()) +@dataclass +class Fermenter: + id: str = None + name: str = None + props: Props = Props() + instance: str = None + cooler: Actor = None + sensor: Sensor = None + type: str = None + target_temp: int = 0 + + def __str__(self): + return "name={} props={} temp={}".format(self.name, self.props, self.target_temp) + def to_dict(self): + + if self.instance is not None: + + state = self.instance.state + print("READ STATE", state) + else: + state = False + return dict(id=self.id, name=self.name, state=state, target_temp=self.target_temp, heater=self.cooler, sensor=self.sensor, type=self.type, props=self.props.to_dict()) + @dataclass class Step: id: str = None @@ -126,6 +149,7 @@ class ConfigType(Enum): ACTOR="actor" SENSOR="sensor" KETTLE="kettle" + FERMENTER="fermenter" NUMBER="number" SELECT="select" diff --git a/cbpi/api/exceptions.py b/cbpi/api/exceptions.py index acec4ee0..a17a2a68 100644 --- a/cbpi/api/exceptions.py +++ b/cbpi/api/exceptions.py @@ -1,4 +1,4 @@ -__all__ = ["CBPiException","KettleException","SensorException","ActorException"] +__all__ = ["CBPiException","KettleException","FermenterException","SensorException","ActorException"] class CBPiException(Exception): @@ -7,6 +7,9 @@ class CBPiException(Exception): class KettleException(CBPiException): pass +class FermenterException(CBPiException): + pass + class SensorException(CBPiException): pass diff --git a/cbpi/api/fermenter_logic.py b/cbpi/api/fermenter_logic.py new file mode 100644 index 00000000..fbebdf8c --- /dev/null +++ b/cbpi/api/fermenter_logic.py @@ -0,0 +1,51 @@ +from cbpi.api.base import CBPiBase +from cbpi.api.extension import CBPiExtension +from abc import ABCMeta +import logging +import asyncio + + + +class CBPiFermenterLogic(CBPiBase, metaclass=ABCMeta): + + def __init__(self, cbpi, id, props): + self.cbpi = cbpi + self.id = id + self.props = props + self.state = False + self.running = False + + def init(self): + pass + + async def on_start(self): + pass + + async def on_stop(self): + pass + + async def run(self): + pass + + async def _run(self): + + try: + await self.on_start() + self.cancel_reason = await self.run() + except asyncio.CancelledError as e: + pass + finally: + await self.on_stop() + + def get_state(self): + return dict(running=self.state) + + async def start(self): + + self.state = True + + async def stop(self): + + self.task.cancel() + await self.task + self.state = False diff --git a/cbpi/api/property.py b/cbpi/api/property.py index 048c9893..8a1df66f 100644 --- a/cbpi/api/property.py +++ b/cbpi/api/property.py @@ -95,7 +95,24 @@ def __init__(self, label, description=""): class Kettle(PropertyType): ''' - The user select a kettle which is available in the system. The value of this variable will be the kettle id + The user selects a kettle which is available in the system. The value of this variable will be the kettle id + ''' + + def __init__(self, label, description=""): + ''' + + :param label: + :param description: + ''' + + PropertyType.__init__(self) + self.label = label + self.configurable = True + self.description = description + + class Fermenter(PropertyType): + ''' + The user selects a fermenter which is available in the system. The value of this variable will be the fermenter id ''' def __init__(self, label, description=""): diff --git a/cbpi/cli.py b/cbpi/cli.py index 53e4c304..d5f4ec2e 100644 --- a/cbpi/cli.py +++ b/cbpi/cli.py @@ -17,7 +17,7 @@ from subprocess import call from jinja2 import Template - +MAIN_DIR = "." def create_config_file(): if os.path.exists(os.path.join(".", 'config', "config.yaml")) is False: @@ -40,6 +40,11 @@ def create_config_file(): destfile = os.path.join(".", 'config') shutil.copy(srcfile, destfile) + if os.path.exists(os.path.join(".", 'config', "fermenter.json")) is False: + srcfile = os.path.join(os.path.dirname(__file__), "config", "fermenter.json") + destfile = os.path.join(".", 'config') + shutil.copy(srcfile, destfile) + if os.path.exists(os.path.join(".", 'config', "step_data.json")) is False: srcfile = os.path.join(os.path.dirname(__file__), "config", "step_data.json") destfile = os.path.join(".", 'config') diff --git a/cbpi/config/actor.json b/cbpi/config/actor.json index f7883130..e6ce0de0 100644 --- a/cbpi/config/actor.json +++ b/cbpi/config/actor.json @@ -1,5 +1,25 @@ { "data": [ - + { + "id": "6CNB5aS7qQxDFhF4zPqRJd", + "name": "dsfsd", + "props": {}, + "state": false, + "type": "MyCustomActors" + }, + { + "id": "TtTuZZ7hE8r46cNTCkHz3D", + "name": "abc", + "props": {}, + "state": false, + "type": "DummyActor" + }, + { + "id": "Sk6VnCE2629RxukRVFkhMB", + "name": "fgfdg", + "props": {}, + "state": false, + "type": "MyCustomActors" + } ] } \ No newline at end of file diff --git a/cbpi/config/config.yaml b/cbpi/config/config.yaml index a7116f87..f5238cbd 100644 --- a/cbpi/config/config.yaml +++ b/cbpi/config/config.yaml @@ -1,14 +1,11 @@ - -name: CraftBeerPi -version: 4.0.8 - index_url: /cbpi_ui/static/index.html - -port: 8000 - -username: cbpi +name: CraftBeerPi password: 123 - plugins: - cbpi4ui - +- myplugin2 +- test +- tester +port: 8000 +username: cbpi +version: 4.0.8 diff --git a/cbpi/config/create_database.sql b/cbpi/config/create_database.sql index fe1ca0e9..4b56b33b 100644 --- a/cbpi/config/create_database.sql +++ b/cbpi/config/create_database.sql @@ -49,6 +49,20 @@ CREATE TABLE IF NOT EXISTS kettle diameter INTEGER ); +CREATE TABLE IF NOT EXISTS fermenter +( + id INTEGER PRIMARY KEY NOT NULL, + name VARCHAR(80), + sensor INTEGER, + cooler INTEGER, + automatic VARCHAR(255), + logic VARCHAR(50), + config VARCHAR(1000), + target_temp INTEGER, + height INTEGER, + diameter INTEGER +); + CREATE TABLE IF NOT EXISTS config ( name VARCHAR(50) PRIMARY KEY NOT NULL, diff --git a/cbpi/config/fermenter.json b/cbpi/config/fermenter.json new file mode 100644 index 00000000..e3a94ce7 --- /dev/null +++ b/cbpi/config/fermenter.json @@ -0,0 +1,34 @@ +{ + "data": [ + { + "heater": null, + "id": "gTetr9nv3FN8ZkcAtYsYjc", + "name": "testing", + "props": {}, + "sensor": "eCa5Mnmr25G24oAAcqFZY2", + "state": false, + "target_temp": 0, + "type": null + }, + { + "heater": null, + "id": "LE4EorYLq4bNugRkvR2wc6", + "name": "tzest", + "props": {}, + "sensor": "eCa5Mnmr25G24oAAcqFZY2", + "state": false, + "target_temp": 0, + "type": "Hysteresis" + }, + { + "heater": null, + "id": "6ScZZMfqGswGfFcmNggzST", + "name": "a", + "props": {}, + "sensor": "kr6vwViDyusVsVJMMmoHqQ", + "state": false, + "target_temp": 0, + "type": "Hysteresis" + } + ] +} \ No newline at end of file diff --git a/cbpi/config/kettle.json b/cbpi/config/kettle.json index f7883130..ce96464c 100644 --- a/cbpi/config/kettle.json +++ b/cbpi/config/kettle.json @@ -1,5 +1,3 @@ { - "data": [ - - ] + "data": [] } \ No newline at end of file diff --git a/cbpi/config/sensor.json b/cbpi/config/sensor.json index 6346c5f9..def8e98d 100644 --- a/cbpi/config/sensor.json +++ b/cbpi/config/sensor.json @@ -1,5 +1,25 @@ { "data": [ - + { + "id": "kr6vwViDyusVsVJMMmoHqQ", + "name": "abc", + "props": {}, + "state": false, + "type": "MyCustomSensorss" + }, + { + "id": "ehD8mesfHRnqk35GrxHZc6", + "name": "tttt", + "props": {}, + "state": false, + "type": "MyCustomSensorss" + }, + { + "id": "UYCNrTf8bWPxX5TXEbpB76", + "name": "abv", + "props": {}, + "state": false, + "type": "HTTPSensor" + } ] } \ No newline at end of file diff --git a/cbpi/config/step_data.json b/cbpi/config/step_data.json index 60a4e287..fa93cc60 100644 --- a/cbpi/config/step_data.json +++ b/cbpi/config/step_data.json @@ -2,7 +2,5 @@ "basic": { "name": "" }, - "steps": [ - - ] + "steps": [] } \ No newline at end of file diff --git a/cbpi/controller/fermenter_controller.py b/cbpi/controller/fermenter_controller.py new file mode 100644 index 00000000..fb1556a6 --- /dev/null +++ b/cbpi/controller/fermenter_controller.py @@ -0,0 +1,35 @@ +from cbpi.api.dataclasses import Fermenter, Props +from cbpi.controller.basic_controller2 import BasicController +import logging +from tabulate import tabulate +class FermenterController(BasicController): + + def __init__(self, cbpi): + super(FermenterController, self).__init__(cbpi, Fermenter, "fermenter.json") + self.update_key = "fermenterupdate" + self.autostart = False + + def create(self, data): + return Fermenter(data.get("id"), data.get("name"), type=data.get("type"), props=Props(data.get("props", {})), sensor=data.get("sensor"), cooler=data.get("cooler")) + + async def toggle(self, id): + + try: + item = self.find_by_id(id) + + if item.instance is None or item.instance.state == False: + await self.start(id) + else: + await item.instance.stop() + await self.push_udpate() + except Exception as e: + logging.error("Faild to switch on FermenterLogic {} {}".format(id, e)) + + async def set_target_temp(self, id, target_temp): + try: + item = self.find_by_id(id) + item.target_temp = target_temp + await self.save() + except Exception as e: + logging.error("Faild to set Target Temp {} {}".format(id, e)) + diff --git a/cbpi/controller/plugin_controller.py b/cbpi/controller/plugin_controller.py index 60742ad9..309328dd 100644 --- a/cbpi/controller/plugin_controller.py +++ b/cbpi/controller/plugin_controller.py @@ -73,6 +73,9 @@ def register(self, name, clazz) -> None: if issubclass(clazz, CBPiKettleLogic): self.cbpi.kettle.types[name] = self._parse_step_props(clazz, name) + if issubclass(clazz, CBPiFermenterLogic): + self.cbpi.fermenter.types[name] = self._parse_step_props(clazz, name) + if issubclass(clazz, CBPiSensor): self.cbpi.sensor.types[name] = self._parse_step_props(clazz, name) @@ -98,6 +101,8 @@ def _parse_property_object(self, p): return {"label": p.label, "type": "sensor", "configurable": p.configurable, "description": p.description} elif isinstance(p, Property.Kettle): return {"label": p.label, "type": "kettle", "configurable": p.configurable, "description": p.description} + elif isinstance(p, Property.Fermenter): + return {"label": p.label, "type": "fermenter", "configurable": p.configurable, "description": p.description} def _parse_step_props(self, cls, name): @@ -158,6 +163,11 @@ def _parse_props(self, cls): result["properties"].append( {"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description}) + elif isinstance(tmpObj.__getattribute__(m), Property.Fermenter): + t = tmpObj.__getattribute__(m) + result["properties"].append( + {"name": m, "label": t.label, "type": "fermenter", "configurable": t.configurable, + "description": t.description}) for method_name, method in cls.__dict__.items(): if hasattr(method, "action"): diff --git a/cbpi/controller/sensor_controller.py b/cbpi/controller/sensor_controller.py index fad71521..21d995b7 100644 --- a/cbpi/controller/sensor_controller.py +++ b/cbpi/controller/sensor_controller.py @@ -19,7 +19,8 @@ def create_dict(self, data): def get_sensor_value(self, id): try: - return self.find_by_id(id).instance.get_state() + item = self.find_by_id(id) + return item.instance.get_state() except Exception as e: logging.error("Faild read sensor value {} {} ".format(id, e)) return None \ No newline at end of file diff --git a/cbpi/craftbeerpi.py b/cbpi/craftbeerpi.py index 89f31da2..b468aa56 100644 --- a/cbpi/craftbeerpi.py +++ b/cbpi/craftbeerpi.py @@ -16,6 +16,7 @@ from cbpi.controller.actor_controller import ActorController from cbpi.controller.config_controller import ConfigController from cbpi.controller.kettle_controller import KettleController +from cbpi.controller.fermenter_controller import FermenterController from cbpi.controller.plugin_controller import PluginController from cbpi.controller.sensor_controller import SensorController from cbpi.controller.step_controller import StepController @@ -33,6 +34,7 @@ from cbpi.http_endpoints.http_config import ConfigHttpEndpoints from cbpi.http_endpoints.http_dashboard import DashBoardHttpEndpoints from cbpi.http_endpoints.http_kettle import KettleHttpEndpoints +from cbpi.http_endpoints.http_fermenter import FermenterHttpEndpoints from cbpi.http_endpoints.http_sensor import SensorHttpEndpoints from cbpi.http_endpoints.http_step import StepHttpEndpoints from cbpi.http_endpoints.http_recipe import RecipeHttpEndpoints @@ -96,6 +98,7 @@ def __init__(self): self.log = LogController(self) self.system = SystemController(self) self.kettle = KettleController(self) + self.fermenter = FermenterController(self) self.step : StepController = StepController(self) self.recipe : RecipeController = RecipeController(self) #self.satellite: SatelliteController = SatelliteController(self) @@ -107,6 +110,7 @@ def __init__(self): self.http_config = ConfigHttpEndpoints(self) self.http_actor = ActorHttpEndpoints(self) self.http_kettle = KettleHttpEndpoints(self) + self.http_fermenter = FermenterHttpEndpoints(self) self.http_dashboard = DashBoardHttpEndpoints(self) self.http_plugin = PluginHttpEndpoints(self) self.http_system = SystemHttpEndpoints(self) @@ -261,6 +265,7 @@ async def init_serivces(self): await self.actor.init() await self.kettle.init() + await self.fermenter.init() await self.call_initializer(self.app) await self.dashboard.init() #await self.satellite.init() diff --git a/cbpi/extension/fermenter_hysteresis/__init__.py b/cbpi/extension/fermenter_hysteresis/__init__.py new file mode 100644 index 00000000..c9706155 --- /dev/null +++ b/cbpi/extension/fermenter_hysteresis/__init__.py @@ -0,0 +1,51 @@ +import asyncio +from asyncio import tasks +import logging +from cbpi.api import * + +@parameters([Property.Number(label="OffsetOn", configurable=True, description="Offset below target temp when cooler should switched on"), + Property.Number(label="OffsetOff", configurable=True, description="Offset above target temp when cooler should switched off")]) +class Hysteresis(CBPiFermenterLogic): + + async def run(self): + try: + self.offset_on = float(self.props.get("OffsetOn", 0)) + self.offset_off = float(self.props.get("OffsetOff", 0)) + self.fermenter = self.get_fermenter(self.id) + self.cooler = self.fermenter.cooler + logging.info("Hysteresis {} {} {} {}".format(self.offset_on, self.offset_off, self.id, self.cooler)) + + self.get_actor_state() + + + while True: + + sensor_value = self.get_sensor_value(self.fermenter.sensor).get("value") + target_temp = self.fermenter(self.id) + if sensor_value > target_temp - self.offset_on: + await self.actor_on(self.cooler) + elif sensor_value <= target_temp + self.offset_off: + await self.actor_off(self.cooler) + await asyncio.sleep(1) + + except asyncio.CancelledError as e: + pass + except Exception as e: + logging.error("CustomLogic Error {}".format(e)) + finally: + self.running = False + await self.actor_off(self.cooler) + + + +def setup(cbpi): + + ''' + This method is called by the server during startup + Here you need to register your plugins at the server + + :param cbpi: the cbpi core + :return: + ''' + + cbpi.plugin.register("Fermentor_Hysteresis", Hysteresis) diff --git a/cbpi/extension/fermenter_hysteresis/config.yaml b/cbpi/extension/fermenter_hysteresis/config.yaml new file mode 100644 index 00000000..847fa7cd --- /dev/null +++ b/cbpi/extension/fermenter_hysteresis/config.yaml @@ -0,0 +1,3 @@ +name: DummyFermenterLogic +version: 4 +active: true \ No newline at end of file diff --git a/cbpi/http_endpoints/http_actor.py b/cbpi/http_endpoints/http_actor.py index 0572206e..257d4966 100644 --- a/cbpi/http_endpoints/http_actor.py +++ b/cbpi/http_endpoints/http_actor.py @@ -15,12 +15,12 @@ async def http_get_all(self, request): """ --- - description: Switch actor on + description: Get list of actors. tags: - Actor responses: - "204": - description: successful operation + "200": + description: JSON-list of acors, their name, label, types, ... """ return web.json_response(data=self.controller.get_state()) @@ -152,7 +152,7 @@ async def http_off(self, request) -> web.Response: """ --- - description: Switch actor on + description: Switch actor off tags: - Actor diff --git a/cbpi/http_endpoints/http_fermenter.py b/cbpi/http_endpoints/http_fermenter.py new file mode 100644 index 00000000..c53b076d --- /dev/null +++ b/cbpi/http_endpoints/http_fermenter.py @@ -0,0 +1,278 @@ +from cbpi.controller.fermenter_controller import FermenterController +from cbpi.api.dataclasses import Fermenter, Props +from aiohttp import web +from cbpi.api import * + +auth = False + +class FermenterHttpEndpoints(): + + def __init__(self, cbpi): + self.cbpi = cbpi + self.controller : FermenterController = cbpi.fermenter + self.cbpi.register(self, "/fermenter") + + @request_mapping(path="/", auth_required=False) + async def http_get_all(self, request): + """ + + --- + description: Switch actor on + tags: + - Fermenter + responses: + "204": + description: successful operation + """ + return web.json_response(data=self.controller.get_state()) + + + @request_mapping(path="/", method="POST", auth_required=False) + async def http_add(self, request): + """ + --- + description: add one Actor + tags: + - Fermenter + parameters: + - in: body + name: body + description: Created an actor + required: true + + schema: + type: object + + properties: + name: + type: string + sensor: + type: "integer" + format: "int64" + cooler: + type: "integer" + format: "int64" + target_temp: + type: "integer" + format: "int64" + type: + type: string + props: + type: object + example: + name: "Fermenter 1" + type: "CustomFermenterLogic" + props: {} + + responses: + "204": + description: successful operation + """ + data = await request.json() + + fermenter = Fermenter(name=data.get("name"), sensor=data.get("sensor"), cooler=data.get("cooler"), props=Props(data.get("props", {})), type=data.get("type")) + response_data = await self.controller.add(fermenter) + return web.json_response(data=response_data.to_dict()) + + + @request_mapping(path="/{id}", method="PUT", auth_required=False) + async def http_update(self, request): + """ + --- + description: Update an actor + tags: + - Fermenter + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "integer" + format: "int64" + - in: body + name: body + description: Update an actor + required: false + schema: + type: object + properties: + name: + type: string + type: + type: string + config: + props: object + responses: + "200": + description: successful operation + """ + id = request.match_info['id'] + data = await request.json() + fermenter = Fermenter(id=id, name=data.get("name"), sensor=data.get("sensor"), cooler=data.get("cooler"), props=Props(data.get("props", {})), type=data.get("type")) + return web.json_response(data=(await self.controller.update(fermenter)).to_dict()) + + @request_mapping(path="/{id}", method="DELETE", auth_required=False) + async def http_delete_one(self, request): + """ + --- + description: Delete an actor + tags: + - Fermenter + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "string" + responses: + "204": + description: successful operation + """ + id = request.match_info['id'] + await self.controller.delete(id) + return web.Response(status=204) + + @request_mapping(path="/{id}/on", method="POST", auth_required=False) + async def http_on(self, request) -> web.Response: + """ + + --- + description: Switch actor on + tags: + - Fermenter + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "string" + + responses: + "204": + description: successful operation + "405": + description: invalid HTTP Met + """ + id = request.match_info['id'] + await self.controller.start(id) + return web.Response(status=204) + + @request_mapping(path="/{id}/off", method="POST", auth_required=False) + async def http_off(self, request) -> web.Response: + """ + + --- + description: Switch actor on + tags: + - Fermenter + + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "string" + + responses: + "204": + description: successful operation + "405": + description: invalid HTTP Met + """ + id = request.match_info['id'] + await self.controller.off(id) + return web.Response(status=204) + + @request_mapping(path="/{id}/toggle", method="POST", auth_required=False) + async def http_toggle(self, request) -> web.Response: + """ + + --- + description: Switch actor on + tags: + - Fermenter + + parameters: + - name: "id" + in: "path" + description: "Fermenter ID" + required: true + type: "string" + + responses: + "204": + description: successful operation + "405": + description: invalid HTTP Met + """ + id = request.match_info['id'] + await self.controller.toggle(id) + return web.Response(status=204) + + @request_mapping(path="/{id}/action", method="POST", auth_required=auth) + async def http_action(self, request) -> web.Response: + """ + + --- + description: Toogle an actor on or off + tags: + - Fermenter + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "integer" + format: "int64" + - in: body + name: body + description: Update an actor + required: false + schema: + type: object + properties: + name: + type: string + parameter: + type: object + responses: + "204": + description: successful operation + """ + actor_id = request.match_info['id'] + data = await request.json() + await self.controller.call_action(actor_id, data.get("name"), data.get("parameter")) + + return web.Response(status=204) + @request_mapping(path="/{id}/target_temp", method="POST", auth_required=auth) + async def http_target(self, request) -> web.Response: + """ + + --- + description: Toogle an actor on or off + tags: + - Fermenter + parameters: + - name: "id" + in: "path" + description: "Actor ID" + required: true + type: "integer" + format: "int64" + - in: body + name: body + description: Update Temp + required: true + schema: + type: object + properties: + temp: + type: integer + responses: + "204": + description: successful operation + """ + id = request.match_info['id'] + data = await request.json() + await self.controller.set_target_temp(id,data.get("temp")) + return web.Response(status=204) \ No newline at end of file diff --git a/cbpi/http_endpoints/http_sensor.py b/cbpi/http_endpoints/http_sensor.py index 7ab9a3e6..29f54969 100644 --- a/cbpi/http_endpoints/http_sensor.py +++ b/cbpi/http_endpoints/http_sensor.py @@ -15,15 +15,31 @@ async def http_get_all(self, request): """ --- - description: Switch actor on + description: Get list of sensors. tags: - Sensor responses: "204": - description: successful operation + description: JSON-list of sensors, their name, label, types, .. """ return web.json_response(data=self.controller.get_state()) + @request_mapping(path="/{id}", method="GET", auth_required=False) + async def http_get_sensor(self, request): + """ + + --- + description: Get value of sensor + tags: + - Sensor + responses: + "204": + description: JSON-list of sensors, their name, label, types, .. + """ + id = request.match_info['id'] + response_data = self.controller.get_sensor_value(id) + print(response_data) + return web.json_response(data=response_data) @request_mapping(path="/", method="POST", auth_required=False) async def http_add(self, request): diff --git a/cbpi/http_endpoints/http_system.py b/cbpi/http_endpoints/http_system.py index 8a05bab1..e8e29959 100644 --- a/cbpi/http_endpoints/http_system.py +++ b/cbpi/http_endpoints/http_system.py @@ -26,6 +26,7 @@ async def state(self, request): actor=self.cbpi.actor.get_state(), sensor=self.cbpi.sensor.get_state(), kettle=self.cbpi.kettle.get_state(), + fermenter=self.cbpi.fermenter.get_state(), step=self.cbpi.step.get_state(), config=self.cbpi.config.get_state(), version=__version__)