diff --git a/cbpi/api/sensor.py b/cbpi/api/sensor.py index 2e25f2b..c91f48a 100644 --- a/cbpi/api/sensor.py +++ b/cbpi/api/sensor.py @@ -2,7 +2,7 @@ import logging from abc import abstractmethod, ABCMeta from cbpi.api.extension import CBPiExtension - +from cbpi.api.config import ConfigType class CBPiSensor(metaclass=ABCMeta): @@ -35,6 +35,18 @@ class CBPiSensor(metaclass=ABCMeta): def get_unit(self): pass + def get_static_config_value(self,name,default): + return self.cbpi.static_config.get(name, default) + + def get_config_value(self,name,default): + return self.cbpi.config.get(name, default=default) + + async def set_config_value(self,name,value): + return await self.cbpi.config.set(name,value) + + async def add_config_value(self, name, value, type: ConfigType, description, options=None): + await self.cbpi.add(name, value, type, description, options=None) + def push_update(self, value): try: self.cbpi.ws.send(dict(topic="sensorstate", id=self.id, value=value)) diff --git a/cbpi/controller/config_controller.py b/cbpi/controller/config_controller.py index 3b39cc0..fb638db 100644 --- a/cbpi/controller/config_controller.py +++ b/cbpi/controller/config_controller.py @@ -33,6 +33,7 @@ class ConfigController: def get(self, name, default=None): self.logger.debug("GET CONFIG VALUE %s (default %s)" % (name, default)) if name in self.cache and self.cache[name].value is not None: + print("name", self.cache[name].value) return self.cache[name].value else: return default diff --git a/cbpi/controller/dashboard_controller.py b/cbpi/controller/dashboard_controller.py index f8963b2..ec14950 100644 --- a/cbpi/controller/dashboard_controller.py +++ b/cbpi/controller/dashboard_controller.py @@ -1,6 +1,8 @@ import logging import json import os +from os import listdir +from os.path import isfile, join class DashboardController(): @@ -33,3 +35,7 @@ class DashboardController(): if os.path.exists(self.path): os.remove(self.path) + async def get_custom_widgets(self): + path = os.path.join(".", 'config', "dashboard", "widgets") + onlyfiles = [os.path.splitext(f)[0] for f in listdir(path) if isfile(join(path, f)) and f.endswith(".svg")] + return onlyfiles diff --git a/cbpi/extension/dummysensor/__init__.py b/cbpi/extension/dummysensor/__init__.py index 9d2b410..3d4556a 100644 --- a/cbpi/extension/dummysensor/__init__.py +++ b/cbpi/extension/dummysensor/__init__.py @@ -30,9 +30,13 @@ class CustomSensor(CBPiSensor): async def run(self): while self.running is True: + print(self.get_config_value("TEMP_UNIT", "NONE")) + print(self.get_static_config_value("port", "NONE")) + await self.set_config_value("BREWERY_NAME", "WOOHOO HELLO") + self.value = random.randint(0,50) self.push_update(self.value) - await asyncio.sleep(10) + await asyncio.sleep(1) def get_state(self): return dict(value=self.value) diff --git a/cbpi/extension/onewire/__init__.py b/cbpi/extension/onewire/__init__.py index 72eb0f8..02b2304 100644 --- a/cbpi/extension/onewire/__init__.py +++ b/cbpi/extension/onewire/__init__.py @@ -6,12 +6,23 @@ import random from aiohttp import web from cbpi.api import * import os, re, threading, time +from subprocess import call -class myThread (threading.Thread): + +def getSensors(): + try: + arr = [] + for dirname in os.listdir('/sys/bus/w1/devices'): + if (dirname.startswith("28") or dirname.startswith("10")): + arr.append(dirname) + return arr + except: + return ["ABC","DEF"] + + +class ReadThread (threading.Thread): value = 0 - - def __init__(self, sensor_name): threading.Thread.__init__(self) self.value = 0 @@ -27,61 +38,59 @@ class myThread (threading.Thread): def run(self): while self.runnig: - try: - - print("READ SENSOR") + 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: + content = content_file.read() + if (content.split('\n')[0].split(' ')[11] == "YES"): + temp = float(content.split("=")[-1]) / 1000 # temp in Celcius + self.value = temp except: pass - time.sleep(1) - - -@parameters([]) +@parameters([Property.Select(label="Sensor", options=getSensors()), Property.Select(label="Interval", options=[1,5,10,30,60], description="Interval in Seconds")]) class OneWire(CBPiSensor): def __init__(self, cbpi, id, props): super(OneWire, self).__init__(cbpi, id, props) self.value = 0 - async def start(self): - - print("START") await super().start() - self.t = myThread("ABC") - + self.name = self.props.get("Sensor") + self.interval = self.props.get("Interval", 60) + self.t = ReadThread(self.name) + self.t.daemon = True def shudown(): shudown.cb.shutdown() shudown.cb = self.t - self.t.start() - pass async def stop(self): try: + print("STOP THE SENSOR") self.t.stop() + self.running = False except: pass async def run(self): - while self.running is True: - + self.value = self.t.value self.push_update(self.value) - await asyncio.sleep(10) + await asyncio.sleep(self.interval) def get_state(self): return dict(value=self.value) 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("OneWire", OneWire) + try: + # Global Init + call(["modprobe", "w1-gpio"]) + call(["modprobe", "w1-therm"]) + except Exception as e: + pass diff --git a/cbpi/http_endpoints/http_dashboard.py b/cbpi/http_endpoints/http_dashboard.py index c18d74f..1b785b9 100644 --- a/cbpi/http_endpoints/http_dashboard.py +++ b/cbpi/http_endpoints/http_dashboard.py @@ -93,3 +93,19 @@ class DashBoardHttpEndpoints(HttpCrudEndpoints): dashboard_id = int(request.match_info['id']) await self.cbpi.dashboard.delete_content(dashboard_id) return web.Response(status=204) + + @request_mapping(path="/widgets", method="GET", auth_required=False) + async def get_custom_widgets(self, request): + """ + --- + description: Get Custom Widgets + tags: + - Dashboard + responses: + "200": + description: successful operation + """ + + + return web.json_response(await self.cbpi.dashboard.get_custom_widgets(), dumps=json_dumps) + diff --git a/cbpi/http_endpoints/http_system.py b/cbpi/http_endpoints/http_system.py index e7b31ea..8a05bab 100644 --- a/cbpi/http_endpoints/http_system.py +++ b/cbpi/http_endpoints/http_system.py @@ -3,7 +3,7 @@ from cbpi.job.aiohttp import get_scheduler_from_app from cbpi.api import request_mapping from cbpi.utils import json_dumps - +from cbpi import __version__ class SystemHttpEndpoints: @@ -27,7 +27,8 @@ class SystemHttpEndpoints: sensor=self.cbpi.sensor.get_state(), kettle=self.cbpi.kettle.get_state(), step=self.cbpi.step.get_state(), - config=self.cbpi.config.get_state()) + config=self.cbpi.config.get_state(), + version=__version__) , dumps=json_dumps) @request_mapping(path="/logs", auth_required=False) diff --git a/config/cbpi_dashboard_1.json b/config/cbpi_dashboard_1.json index 5f7e5df..36e33eb 100644 --- a/config/cbpi_dashboard_1.json +++ b/config/cbpi_dashboard_1.json @@ -1,67 +1,90 @@ { "elements": [ { - "id": "fb8e005c-e936-4bd3-882e-ba4020496067", + "id": "84e6afbd-7ed0-4135-b64e-4ce89568946d", "name": "Kettle", "props": { "heigth": "150", "width": "100" }, "type": "Kettle", - "x": 230, - "y": 70 + "x": 120, + "y": 55 }, { - "id": "84a4fb23-9226-4c3d-922b-24be78811c4a", - "name": "Actor", + "id": "bec11478-8056-4577-a095-a5909282b0ac", + "name": "Kettle", + "props": { + "heigth": "150", + "width": "100" + }, + "type": "Kettle", + "x": 360, + "y": 55 + }, + { + "id": "d07d7f84-5bc8-42d5-9ef5-9d5be1ff4584", + "name": "Left", "props": { "actor": "YwGzXvWMpmbLb6XobesL8n" }, "type": "ActorButton", - "x": 130, - "y": 250 + "x": 510, + "y": 60 + }, + { + "id": "310d78c3-b3c0-40dc-b2a1-42488787fd46", + "name": "Right", + "props": { + "actor": "EsmZwWi9Qp3bzmXqq7N3Ly" + }, + "type": "ActorButton", + "x": 505, + "y": 140 } ], "pathes": [ { - "condition": [ - "YwGzXvWMpmbLb6XobesL8n" - ], + "condition": { + "left": [ + "YwGzXvWMpmbLb6XobesL8n" + ], + "right": [ + "EsmZwWi9Qp3bzmXqq7N3Ly" + ] + }, "coordinates": [ [ - 70, - 70 + 215, + 90 ], [ - 40, - 350 - ], - [ - 200, - 435 - ], - [ - 115, - 530 + 360, + 90 ] ], - "id": "23789f6d-ec5b-4704-8cc0-e6614b14b5c6" + "id": "559fb368-bce9-4f9b-a25c-c468ae0cac88" }, { - "condition": [ - "YwGzXvWMpmbLb6XobesL8n" - ], + "condition": { + "left": [ + "YwGzXvWMpmbLb6XobesL8n" + ], + "right": [ + "EsmZwWi9Qp3bzmXqq7N3Ly" + ] + }, "coordinates": [ [ - 100, - 180 + 365, + 160 ], [ - 220, - 135 + 215, + 160 ] ], - "id": "fa887fcf-69e6-4a25-bb42-b65a13cc4012" + "id": "f0b05e9f-132b-4797-9fb0-1431c0579733" } ] } \ No newline at end of file diff --git a/config/kettle.json b/config/kettle.json index 74b96b1..f10a774 100644 --- a/config/kettle.json +++ b/config/kettle.json @@ -1,8 +1,8 @@ { "data": [ { - "agitator": "", - "heater": "8BLRqagLicCdEBDdc77Sgr", + "agitator": "EsmZwWi9Qp3bzmXqq7N3Ly", + "heater": "YwGzXvWMpmbLb6XobesL8n", "id": "oHxKz3z5RjbsxfSz6KUgov", "name": "MashTun", "props": {}, diff --git a/config/sensor.json b/config/sensor.json index ce96464..f51d600 100644 --- a/config/sensor.json +++ b/config/sensor.json @@ -1,3 +1,16 @@ { - "data": [] + "data": [ + { + "id": "RedQfuxfy4mYe6PwioY95y", + "name": "Test", + "props": { + "Interval": 5, + "Sensor": "DEF" + }, + "state": { + "value": 0 + }, + "type": "OneWire" + } + ] } \ No newline at end of file diff --git a/craftbeerpi.db b/craftbeerpi.db index ebaacfa..4df71f1 100644 Binary files a/craftbeerpi.db and b/craftbeerpi.db differ diff --git a/requirements.txt b/requirements.txt index dc05279..c93cee6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ pyfiglet==0.8.post1 pandas==1.1.5 shortuuid==1.0.1 tabulate==0.8.7 -cbpi4-ui \ No newline at end of file +cbpi4-ui +asyncio-mqtt \ No newline at end of file diff --git a/setup.py b/setup.py index 8dd84bf..22fca55 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,7 @@ setup(name='cbpi', 'click==7.1.2', 'shortuuid==1.0.1', 'tabulate==0.8.7', + 'asyncio-mqtt', 'cbpi4-ui @ git+https://github.com/Manuel83/craftbeerpi4-ui.git', ], dependency_links=[