diff --git a/cbpi/__init__.py b/cbpi/__init__.py index aba157c..452d099 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1 +1 @@ -__version__ = "4.0.0.13" \ No newline at end of file +__version__ = "4.0.0.14" \ No newline at end of file diff --git a/cbpi/controller/config_controller.py b/cbpi/controller/config_controller.py index 43ecb2c..3b39cc0 100644 --- a/cbpi/controller/config_controller.py +++ b/cbpi/controller/config_controller.py @@ -24,6 +24,7 @@ class ConfigController: async def init(self): this_directory = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-2]) + self.static = load_config("{}/config/config.yaml".format(this_directory)) items = await self.model.get_all() for key, value in items.items(): diff --git a/cbpi/craftbeerpi.py b/cbpi/craftbeerpi.py index ec2af01..26258ae 100644 --- a/cbpi/craftbeerpi.py +++ b/cbpi/craftbeerpi.py @@ -28,6 +28,7 @@ from cbpi.eventbus import CBPiEventBus from cbpi.http_endpoints.http_login import Login from cbpi.utils import * from cbpi.websocket import CBPiWebSocket +from cbpi.satellite import CBPiSatellite from cbpi.http_endpoints.http_actor import ActorHttpEndpoints from cbpi.http_endpoints.http_config import ConfigHttpEndpoints @@ -69,10 +70,12 @@ class CraftBeerPi: def __init__(self): self.path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1]) # The path to the package dir + self.version = __version__ - self.static_config = load_config("{}/config/config.yaml".format(self.path)) - self.database_file = "{}/craftbeerpi.db".format(self.path) + self.static_config = load_config(os.path.join(".", 'config', "config.yaml")) + print(self.path, self.static_config) + self.database_file = os.path.join(".", 'config', "craftbeerpi.db") logger.info("Init CraftBeerPI") policy = auth.SessionTktAuthentication(urandom(32), 60, include_ip=True) @@ -88,7 +91,7 @@ class CraftBeerPi: self.job = JobController(self) self.config = ConfigController(self) self.ws = CBPiWebSocket(self) - + self.satellite = CBPiSatellite(self) self.actor = ActorController(self) self.sensor = SensorController(self) self.plugin = PluginController(self) diff --git a/cbpi/extension/mqtt/__init__.py b/cbpi/extension/mqtt/__init__.py index 48e331f..545e4f8 100644 --- a/cbpi/extension/mqtt/__init__.py +++ b/cbpi/extension/mqtt/__init__.py @@ -3,6 +3,10 @@ import json from cbpi.utils.encoder import ComplexEncoder from hbmqtt.mqtt.constants import QOS_0 from hbmqtt.client import MQTTClient +from hbmqtt.mqtt.constants import QOS_1, QOS_2 +from asyncio_mqtt import Client, MqttError, Will +import asyncio + class CBPiMqttClient: @@ -10,13 +14,18 @@ class CBPiMqttClient: self.cbpi = cbpi self.cbpi.bus.register("#", self.listen) self.client = None - self.cbpi.app.on_startup.append(self.init_client) + self._loop = asyncio.get_event_loop() + self._loop.create_task(self.init_client(self.cbpi)) async def init_client(self, cbpi): - self.client = MQTTClient() - await self.client.connect('mqtt://localhost:1883') + async with Client("localhost", will=Will(topic="cbpi/diconnect", payload="MY CLIENT"))as client: + async with client.filtered_messages("cbpi/#") as messages: + await client.subscribe("cbpi/#") + async for message in messages: + await self.cbpi.actor.on("YwGzXvWMpmbLb6XobesL8n") + print(message.topic, message.payload.decode()) async def listen(self, topic, **kwargs): @@ -31,10 +40,6 @@ def setup(cbpi): :param cbpi: the cbpi core :return: ''' - print("MQTT") - print("###################") - print("###################") - print("###################") - print("###################") + client = CBPiMqttClient(cbpi) diff --git a/cbpi/extension/mqtt/config.yaml b/cbpi/extension/mqtt/config.yaml index aa3909a..e24ed7d 100644 --- a/cbpi/extension/mqtt/config.yaml +++ b/cbpi/extension/mqtt/config.yaml @@ -1,3 +1,3 @@ name: MQTT version: 4.0 -active: False \ No newline at end of file +active: false \ No newline at end of file diff --git a/cbpi/extension/onewire/__init__.py b/cbpi/extension/onewire/__init__.py new file mode 100644 index 0000000..72eb0f8 --- /dev/null +++ b/cbpi/extension/onewire/__init__.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +import asyncio +import random +import re +import random +from aiohttp import web +from cbpi.api import * +import os, re, threading, time + +class myThread (threading.Thread): + + value = 0 + + + def __init__(self, sensor_name): + threading.Thread.__init__(self) + self.value = 0 + self.sensor_name = sensor_name + self.runnig = True + + def shutdown(self): + pass + + def stop(self): + self.runnig = False + + def run(self): + + while self.runnig: + try: + + print("READ SENSOR") + except: + pass + + time.sleep(1) + + + +@parameters([]) +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") + + def shudown(): + shudown.cb.shutdown() + shudown.cb = self.t + + self.t.start() + pass + + async def stop(self): + try: + self.t.stop() + except: + pass + + async def run(self): + + while self.running is True: + + self.push_update(self.value) + await asyncio.sleep(10) + + 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) diff --git a/cbpi/extension/onewire/config.yaml b/cbpi/extension/onewire/config.yaml new file mode 100644 index 0000000..7f0aa15 --- /dev/null +++ b/cbpi/extension/onewire/config.yaml @@ -0,0 +1,3 @@ +name: DummySensor +version: 4 +active: true \ No newline at end of file diff --git a/cbpi/satellite.py b/cbpi/satellite.py new file mode 100644 index 0000000..ea20ffe --- /dev/null +++ b/cbpi/satellite.py @@ -0,0 +1,88 @@ +import logging +import weakref +from collections import defaultdict + +import aiohttp +from aiohttp import web +from voluptuous import Schema + +from cbpi.utils import json_dumps + + +class CBPiSatellite: + def __init__(self, cbpi) -> None: + self.cbpi = cbpi + self._callbacks = defaultdict(set) + self._clients = weakref.WeakSet() + self.logger = logging.getLogger(__name__) + self.cbpi.app.add_routes([web.get('/satellite', self.websocket_handler)]) + self.cbpi.bus.register_object(self) + + #if self.cbpi.config.static.get("ws_push_all", False): + self.cbpi.bus.register("#", self.listen) + + + async def listen(self, topic, **kwargs): + data = dict(topic=topic, data=dict(**kwargs)) + self.logger.debug("PUSH %s " % data) + self.send(data) + + + def send(self, data): + 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) + self.cbpi.app.loop.create_task(send_data(ws, data)) + + async def websocket_handler(self, request): + + + print("HALLO SATELLITE") + ws = web.WebSocketResponse() + await ws.prepare(request) + self._clients.add(ws) + try: + peername = request.transport.get_extra_info('peername') + if peername is not None: + print(peername) + host = peername[0] + port = peername[1] + else: + host, port = "Unknowen" + self.logger.info("Client Connected - Host: %s Port: %s - client count: %s " % (host, port, len(self._clients))) + except Exception as e: + print(e) + + + try: + await ws.send_json(data=dict(topic="connection/success")) + async for msg in ws: + if msg.type == aiohttp.WSMsgType.TEXT: + + msg_obj = msg.json() + schema = Schema({"topic": str, "data": dict}) + schema(msg_obj) + + topic = msg_obj.get("topic") + data = msg_obj.get("data") + if topic == "close": + await ws.close() + else: + if data is not None: + await self.cbpi.bus.fire(topic=topic, **data) + else: + await self.cbpi.bus.fire(topic=topic) + elif msg.type == aiohttp.WSMsgType.ERROR: + self.logger.error('ws connection closed with exception %s' % ws.exception()) + + except Exception as e: + self.logger.error("%s - Received Data %s" % (str(e), msg.data)) + + finally: + self._clients.discard(ws) + + self.logger.info("Web Socket Close") + + return ws + \ No newline at end of file diff --git a/cheat_sheet.txt b/cheat_sheet.txt index 53cea8a..907515b 100644 --- a/cheat_sheet.txt +++ b/cheat_sheet.txt @@ -9,7 +9,6 @@ twine upload dist/* # Checkout Pull Request -git fetch origin pull/ID/head:BRANCHNAME -git checkout BRANCHNAME +git fetch origin pull/ID/head:BRANCHNAMEgit checkout BRANCHNAME diff --git a/config/cbpi_dashboard_1.json b/config/cbpi_dashboard_1.json index 01b1ce9..5f7e5df 100644 --- a/config/cbpi_dashboard_1.json +++ b/config/cbpi_dashboard_1.json @@ -1,22 +1,67 @@ { - "elements": [], + "elements": [ + { + "id": "fb8e005c-e936-4bd3-882e-ba4020496067", + "name": "Kettle", + "props": { + "heigth": "150", + "width": "100" + }, + "type": "Kettle", + "x": 230, + "y": 70 + }, + { + "id": "84a4fb23-9226-4c3d-922b-24be78811c4a", + "name": "Actor", + "props": { + "actor": "YwGzXvWMpmbLb6XobesL8n" + }, + "type": "ActorButton", + "x": 130, + "y": 250 + } + ], "pathes": [ { + "condition": [ + "YwGzXvWMpmbLb6XobesL8n" + ], "coordinates": [ [ - 35, - 170 + 70, + 70 ], [ - 105, - 65 + 40, + 350 ], [ - 185, - 140 + 200, + 435 + ], + [ + 115, + 530 ] ], - "id": "d374b969-a94d-4d75-a529-1aafd4a79e04" + "id": "23789f6d-ec5b-4704-8cc0-e6614b14b5c6" + }, + { + "condition": [ + "YwGzXvWMpmbLb6XobesL8n" + ], + "coordinates": [ + [ + 100, + 180 + ], + [ + 220, + 135 + ] + ], + "id": "fa887fcf-69e6-4a25-bb42-b65a13cc4012" } ] } \ No newline at end of file diff --git a/config/sensor.json b/config/sensor.json index a2b8d06..ce96464 100644 --- a/config/sensor.json +++ b/config/sensor.json @@ -1,13 +1,3 @@ { - "data": [ - { - "id": "8ohkXvFA9UrkHLsxQL38wu", - "name": "Sensor1", - "props": {}, - "state": { - "value": 35 - }, - "type": "CustomSensor" - } - ] + "data": [] } \ No newline at end of file