Bläddra i källkod

Merge 933096624e into 6253cb9976

pull/147/merge
isarvalley GitHub 8 år sedan
förälder
incheckning
27df35dc5c
24 ändrade filer med 162 tillägg och 47 borttagningar
  1. +1
    -0
      .codebeatignore
  2. +13
    -0
      .travis.yml
  3. +8
    -0
      README.md
  4. +19
    -0
      config/logger.yaml
  5. +4
    -0
      modules/action/__init__.py
  6. +9
    -5
      modules/base_plugins/actor.py
  7. +9
    -4
      modules/base_plugins/sensor.py
  8. +6
    -2
      modules/core/baseapi.py
  9. +18
    -9
      modules/core/basetypes.py
  10. +28
    -17
      modules/core/core.py
  11. +1
    -2
      modules/core/db_migrate.py
  12. +4
    -0
      modules/example_plugins/WebViewJquery/__init__.py
  13. +3
    -0
      modules/example_plugins/WebViewReactJs/__init__.py
  14. +3
    -0
      modules/fermenter/__init__.py
  15. +2
    -0
      modules/login/__init__.py
  16. +3
    -1
      modules/logs/__init__.py
  17. +5
    -1
      modules/recipe_import/kbh.py
  18. +0
    -6
      run.py
  19. +0
    -0
      tests/__init__.py
  20. +0
    -0
      tests/logs/__init__.py
  21. +13
    -0
      tests/logs/test_log_view.py
  22. +0
    -0
      tests/testlib/__init__.py
  23. +13
    -0
      tests/testlib/utils.py
  24. +0
    -0
      update/5_kairosdb_config.sql

+ 1
- 0
.codebeatignore Visa fil

@@ -0,0 +1 @@
modules/ui/static/**

+ 13
- 0
.travis.yml Visa fil

@@ -0,0 +1,13 @@
language: python
python:
- "2.7"

#before_install:
# - pip install pytest pytest-cov

# command to install dependencies
install:
- pip install -r requirements.txt

script:
- py.test

+ 8
- 0
README.md Visa fil

@@ -1,3 +1,11 @@
[![Build Status](https://travis-ci.org/isarvalley/craftbeerpi3.svg?branch=core_refactoring)](https://travis-ci.org/isarvalley/craftbeerpi3)

[![codebeat badge](https://codebeat.co/badges/72fa1981-c82a-488f-9a53-9e21ed9de4cc)](https://codebeat.co/projects/github-com-isarvalley-craftbeerpi3-core_refactoring)

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/0a970c7873f84953bd772c36d5ffc05c)](https://www.codacy.com/app/isar_valley/craftbeerpi3?utm_source=github.com&utm_medium=referral&utm_content=isarvalley/craftbeerpi3&utm_campaign=Badge_Grade)

[![BCH compliance](https://bettercodehub.com/edge/badge/isarvalley/craftbeerpi3?branch=core_refactoring)](https://bettercodehub.com/)

# CraftBeerPi V3.0 # CraftBeerPi V3.0


This is CraftBeerPi version 3.0. It's currently in beta status. This is CraftBeerPi version 3.0. It's currently in beta status.


+ 19
- 0
config/logger.yaml Visa fil

@@ -0,0 +1,19 @@
version: 1
formatters:
simple:
format: '%(asctime)s - %(levelname)-8s - %(name)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
file:
class : logging.handlers.RotatingFileHandler
formatter: simple
filename: ./logs/app.log
maxBytes: 10000000
backupCount: 3
root:
level: DEBUG
handlers: [console, file]

+ 4
- 0
modules/action/__init__.py Visa fil

@@ -1,8 +1,12 @@
import json import json
import logging
from flask_classy import FlaskView, route from flask_classy import FlaskView, route
from modules.core.core import cbpi from modules.core.core import cbpi



class ActionView(FlaskView): class ActionView(FlaskView):
def __init__(self):
self.logger = logging.getLogger(__name__)


@route('/<action>', methods=['POST']) @route('/<action>', methods=['POST'])
def action(self, action): def action(self, action):


+ 9
- 5
modules/base_plugins/actor.py Visa fil

@@ -1,10 +1,13 @@
import logging
from modules.core.baseapi import Buzzer from modules.core.baseapi import Buzzer
from modules.core.basetypes import Actor, KettleController, FermenterController from modules.core.basetypes import Actor, KettleController, FermenterController
from modules.core.core import cbpi from modules.core.core import cbpi



@cbpi.addon.actor.type("Dummy Actor") @cbpi.addon.actor.type("Dummy Actor")
class Dummy(Actor): class Dummy(Actor):

def __init__(self):
self.logger = logging.getLogger(__name__)


@cbpi.addon.actor.action("WOHOO") @cbpi.addon.actor.action("WOHOO")
def myaction(self): def myaction(self):
@@ -16,10 +19,10 @@ class Dummy(Actor):
:param power: int value between 0 - 100 :param power: int value between 0 - 100
:return: :return:
''' '''
print "ON"
self.logger.info("ON")


def off(self): def off(self):
print "OFF"
self.logger.info("OFF")






@@ -33,11 +36,12 @@ class MyController(KettleController):


@cbpi.addon.fermenter.controller() @cbpi.addon.fermenter.controller()
class MyController2(FermenterController): class MyController2(FermenterController):

def __init__(self):
self.logger = logging.getLogger(__name__)


def run(self): def run(self):
while self.is_running(): while self.is_running():
print "HALLO"
self.logger.debug("HALLO")
self.sleep(1) self.sleep(1)


@cbpi.addon.core.initializer(order=200) @cbpi.addon.core.initializer(order=200)


+ 9
- 4
modules/base_plugins/sensor.py Visa fil

@@ -3,10 +3,12 @@ import os


from os.path import join from os.path import join


from modules.core.basetypes import Actor, Sensor
from modules.core.basetypes import Sensor
from modules.core.core import cbpi from modules.core.core import cbpi
from modules.core.proptypes import Property from modules.core.proptypes import Property
import random

import logging



@cbpi.addon.sensor.type("Dummy Sensor") @cbpi.addon.sensor.type("Dummy Sensor")
class Dummy(Sensor): class Dummy(Sensor):
@@ -14,6 +16,10 @@ class Dummy(Sensor):
text = Property.Text(label="Text", required=True, description="This is a parameter", configurable=True) text = Property.Text(label="Text", required=True, description="This is a parameter", configurable=True)
p = Property.Select(label="hallo",options=[1,2,3]) p = Property.Select(label="hallo",options=[1,2,3])


def __init__(self):
self.logger = logging.getLogger(__name__)
self.logger.info("INIT SENSOR")

def init(self): def init(self):


if self.api.get_config_parameter("unit","C") == "C": if self.api.get_config_parameter("unit","C") == "C":
@@ -23,8 +29,7 @@ class Dummy(Sensor):


@cbpi.addon.sensor.action("WOHOO") @cbpi.addon.sensor.action("WOHOO")
def myaction(self): def myaction(self):

print "SENSOR ACTION HALLO!!!"
self.logger.debug("SENSOR ACTION HALLO!!!")


def execute(self): def execute(self):
while True: while True:


+ 6
- 2
modules/core/baseapi.py Visa fil

@@ -1,3 +1,5 @@
import logging
from proptypes import * from proptypes import *
class BaseAPI(object): class BaseAPI(object):
@@ -148,6 +150,8 @@ class CoreAPI(BaseAPI):
key = "core" key = "core"
def __init__(self, cbpi): def __init__(self, cbpi):
self.logger = logging.getLogger(__name__)
self.cbpi = cbpi self.cbpi = cbpi
self.cbpi.cache["actions"] = {} self.cbpi.cache["actions"] = {}
self.cbpi.cache["init"] = [] self.cbpi.cache["init"] = []
@@ -168,7 +172,7 @@ class CoreAPI(BaseAPI):
try: try:
method(self.cbpi) method(self.cbpi)
except Exception as e: except Exception as e:
print e
self.logger.debug(e)
self.cbpi._socketio.sleep(interval) self.cbpi._socketio.sleep(interval)
for value in self.cbpi.cache.get("background"): for value in self.cbpi.cache.get("background"):
@@ -220,5 +224,5 @@ class CoreAPI(BaseAPI):
class Buzzer(object): class Buzzer(object):
def beep():
def beep(self):
pass pass

+ 18
- 9
modules/core/basetypes.py Visa fil

@@ -1,3 +1,5 @@
import logging
from modules.core.proptypes import Property from modules.core.proptypes import Property
import time import time
@@ -12,7 +14,9 @@ class Base(object):
self.value = None self.value = None
self.__dirty = False self.__dirty = False
class Actor(Base): class Actor(Base):
__logger = logging.getLogger(__name__)
@classmethod @classmethod
def init_global(cls): def init_global(cls):
@@ -26,15 +30,15 @@ class Actor(Base):
pass pass
def on(self, power=100): def on(self, power=100):
print "SWITCH ON"
self._logger.info("SWITCH ON")
pass pass
def off(self): def off(self):
print "SWITCH OFF"
self._logger.info("SWITCH OFF")
pass pass
def power(self, power): def power(self, power):
print "SET POWER", power
self._logger.info("SET POWER TO [%s]", power)
pass pass
def state(self): def state(self):
@@ -42,6 +46,7 @@ class Actor(Base):
class Sensor(Base): class Sensor(Base):
__logger = logging.getLogger(__name__)
unit = "" unit = ""
@@ -60,12 +65,13 @@ class Sensor(Base):
def update_value(self, value): def update_value(self, value):
self.value = value self.value = value
self.__logger.info("Updated value for sensor [%s] with value [%s].", self.id, value)
self.cbpi.sensor.write_log(self.id, value) self.cbpi.sensor.write_log(self.id, value)
self.cbpi.emit("SENSOR_UPDATE", id=self.id, value=value) self.cbpi.emit("SENSOR_UPDATE", id=self.id, value=value)
self.cbpi.ws_emit("SENSOR_UPDATE", self.cbpi.cache["sensors"][self.id]) self.cbpi.ws_emit("SENSOR_UPDATE", self.cbpi.cache["sensors"][self.id])
def execute(self): def execute(self):
print "EXECUTE"
self.__logger.info("EXECUTE")
pass pass
@@ -75,9 +81,11 @@ class ControllerBase(object):
__dirty = False __dirty = False
__running = False __running = False
__logger = logging.getLogger(__name__)
@staticmethod @staticmethod
def init_global(): def init_global():
print "GLOBAL CONTROLLER INIT"
ControllerBase.__logger.info("GLOBAL CONTROLLER INIT")
def notify(self, headline, message, type="success", timeout=5000): def notify(self, headline, message, type="success", timeout=5000):
self.api.notify(headline, message, type, timeout) self.api.notify(headline, message, type, timeout)
@@ -251,12 +259,13 @@ class Step(Base, Timer):
pass pass
def execute(self): def execute(self):
print "Step Info"
print "Kettle ID: %s" % self.kettle_id
print "ID: %s" % self.id
self.logger.info("-------------")
self.logger.info("Step Info")
self.logger.info("Kettle ID: %s" % self.kettle_id)
self.logger.info("ID: %s" % self.id)
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):
self.logger = logging.getLogger(__name__)
for a in kwds: for a in kwds:
super(Step, self).__setattr__(a, kwds.get(a)) super(Step, self).__setattr__(a, kwds.get(a))


+ 28
- 17
modules/core/core.py Visa fil

@@ -1,13 +1,16 @@
import json import json
import logging import logging
import logging.config
import os import os
import sqlite3 import sqlite3
import uuid import uuid
import yaml
from datetime import datetime from datetime import datetime
from functools import wraps, update_wrapper from functools import wraps, update_wrapper
from importlib import import_module from importlib import import_module
from time import localtime, strftime from time import localtime, strftime
import time import time
import os.path
from flask import Flask, redirect, json, g, make_response from flask import Flask, redirect, json, g, make_response
from flask_socketio import SocketIO from flask_socketio import SocketIO
@@ -62,6 +65,8 @@ class ActorCore(object):
key = "actor_types" key = "actor_types"
def __init__(self, cbpi): def __init__(self, cbpi):
self.logger = logging.getLogger(__name__)
self.cbpi = cbpi self.cbpi = cbpi
self.cbpi.cache["actors"] = {} self.cbpi.cache["actors"] = {}
self.cbpi.cache[self.key] = {} self.cbpi.cache[self.key] = {}
@@ -82,8 +87,7 @@ class ActorCore(object):
actor.power = 100 actor.power = 100
self.cbpi.emit("INIT_ACTOR", id=id) self.cbpi.emit("INIT_ACTOR", id=id)
except Exception as e: except Exception as e:
print e
self.cbpi._app.logger.error(e)
self.logger.error(e)
def stop_one(self, id): def stop_one(self, id):
self.cbpi.cache["actors"][id]["instance"].stop() self.cbpi.cache["actors"][id]["instance"].stop()
@@ -99,7 +103,7 @@ class ActorCore(object):
self.cbpi.emit("SWITCH_ACTOR_ON", id=id, power=power) self.cbpi.emit("SWITCH_ACTOR_ON", id=id, power=power)
return True return True
except Exception as e: except Exception as e:
print e
self.logger.error(e)
return False return False
def off(self, id): def off(self, id):
@@ -111,7 +115,7 @@ class ActorCore(object):
self.cbpi.emit("SWITCH_ACTOR_OFF", id=id) self.cbpi.emit("SWITCH_ACTOR_OFF", id=id)
return True return True
except Exception as e: except Exception as e:
print e
self.logger.error(e)
return False return False
def toggle(self, id): def toggle(self, id):
@@ -129,7 +133,7 @@ class ActorCore(object):
self.cbpi.emit("SWITCH_ACTOR_POWER_CHANGE", id=id, power=power) self.cbpi.emit("SWITCH_ACTOR_POWER_CHANGE", id=id, power=power)
return True return True
except Exception as e: except Exception as e:
print e
self.logger.error(e)
return False return False
def action(self, id, method): def action(self, id, method):
@@ -154,6 +158,8 @@ class SensorCore(object):
key = "sensor_types" key = "sensor_types"
def __init__(self, cbpi): def __init__(self, cbpi):
self.logger = logging.getLogger(__name__)
self.cbpi = cbpi self.cbpi = cbpi
self.cbpi.cache["sensors"] = {} self.cbpi.cache["sensors"] = {}
self.cbpi.cache["sensor_instances"] = {} self.cbpi.cache["sensor_instances"] = {}
@@ -181,8 +187,7 @@ class SensorCore(object):
self.cbpi.emit("INIT_SENSOR", id=id) self.cbpi.emit("INIT_SENSOR", id=id)
except Exception as e: except Exception as e:
print "ERROR"
self.cbpi._app.logger.error(e)
self.logger.error(e)
def stop_one(self, id): def stop_one(self, id):
@@ -240,7 +245,7 @@ class BrewingCore(object):
# Start controller # Start controller
if kettle.logic is not None: if kettle.logic is not None:
cfg = kettle.config.copy() cfg = kettle.config.copy()
cfg.update(dict(api=cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor))
cfg.update(dict(api=self.cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor))
instance = self.get_controller(kettle.logic).get("class")(**cfg) instance = self.get_controller(kettle.logic).get("class")(**cfg)
instance.init() instance.init()
kettle.instance = instance kettle.instance = instance
@@ -250,13 +255,13 @@ class BrewingCore(object):
t = self.cbpi._socketio.start_background_task(target=run, instance=instance) t = self.cbpi._socketio.start_background_task(target=run, instance=instance)
kettle.state = not kettle.state kettle.state = not kettle.state
self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id))
self.cbpi.ws_emit("UPDATE_KETTLE", self.cbpi.cache.get("kettle").get(id))
self.cbpi.emit("KETTLE_CONTROLLER_STARTED", id=id) self.cbpi.emit("KETTLE_CONTROLLER_STARTED", id=id)
else: else:
# Stop controller # Stop controller
kettle.instance.stop() kettle.instance.stop()
kettle.state = not kettle.state kettle.state = not kettle.state
self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id))
self.cbpi.ws_emit("UPDATE_KETTLE", self.cbpi.cache.get("kettle").get(id))
self.cbpi.emit("KETTLE_CONTROLLER_STOPPED", id=id) self.cbpi.emit("KETTLE_CONTROLLER_STOPPED", id=id)
@@ -271,12 +276,19 @@ class FermentationCore(object):
class CraftBeerPI(object): class CraftBeerPI(object):
_logger_configuration_file = './config/logger.yaml'
cache = {} cache = {}
eventbus = {} eventbus = {}
def __init__(self): def __init__(self):
FORMAT = '%(asctime)-15s - %(levelname)s - %(message)s'
logging.basicConfig(filename='./logs/app.log', level=logging.INFO, format=FORMAT)
if os.path.isfile(self._logger_configuration_file):
logging.config.dictConfig(yaml.load(open(self._logger_configuration_file, 'r')))
self.logger = logging.getLogger(__name__)
self.logger.info("Logger got initialized.")
self.cache["messages"] = [] self.cache["messages"] = []
self.cache["version"] = "3.1" self.cache["version"] = "3.1"
self.modules = {} self.modules = {}
@@ -306,7 +318,7 @@ class CraftBeerPI(object):
port = int(cbpi.get_config_parameter('port', '5000')) port = int(cbpi.get_config_parameter('port', '5000'))
except ValueError: except ValueError:
port = 5000 port = 5000
print port
self.logger.info("port [%s]", port)
self._socketio.run(self._app, host='0.0.0.0', port=port) self._socketio.run(self._app, host='0.0.0.0', port=port)
def beep(self): def beep(self):
@@ -331,7 +343,7 @@ class CraftBeerPI(object):
db.cursor().executescript(f.read()) db.cursor().executescript(f.read())
db.commit() db.commit()
except Exception as e: except Exception as e:
self.logger.error(e)
pass pass
def nocache(self, view): def nocache(self, view):
@@ -388,9 +400,8 @@ class CraftBeerPI(object):
try: try:
self.modules[filename] = import_module("modules.plugins.%s" % (filename)) self.modules[filename] = import_module("modules.plugins.%s" % (filename))
except Exception as e: except Exception as e:
self.logger.error(e)
self.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None) self.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None)
cbpi = CraftBeerPI() cbpi = CraftBeerPI()
addon = cbpi.addon
addon = cbpi.addon

+ 1
- 2
modules/core/db_migrate.py Visa fil

@@ -19,8 +19,7 @@ def execute_file(curernt_version, data):
conn.commit() conn.commit()


except sqlite3.OperationalError as err: except sqlite3.OperationalError as err:

print err
cbpi._app.logger.error(err)


@cbpi.addon.core.initializer(order=-9999) @cbpi.addon.core.initializer(order=-9999)
def init(cbpi): def init(cbpi):


+ 4
- 0
modules/example_plugins/WebViewJquery/__init__.py Visa fil

@@ -5,9 +5,13 @@ from flask_swagger import swagger
from flask import json from flask import json
from flask import Blueprint from flask import Blueprint


import logging

@addon.core.initializer(order=22) @addon.core.initializer(order=22)
def web(cbpi): def web(cbpi):


logger = logging.getLogger(__name__)

s = Blueprint('web_view', __name__, template_folder='templates', static_folder='static') s = Blueprint('web_view', __name__, template_folder='templates', static_folder='static')


@s.route('/', methods=["GET"]) @s.route('/', methods=["GET"])


+ 3
- 0
modules/example_plugins/WebViewReactJs/__init__.py Visa fil

@@ -5,8 +5,11 @@ from flask_swagger import swagger
from flask import json from flask import json
from flask import Blueprint from flask import Blueprint


import logging

@addon.core.initializer(order=22) @addon.core.initializer(order=22)
def web(cbpi): def web(cbpi):
logger = logging.getLogger(__name__)


s = Blueprint('webviewreact', __name__, template_folder='templates', static_folder='static') s = Blueprint('webviewreact', __name__, template_folder='templates', static_folder='static')




+ 3
- 0
modules/fermenter/__init__.py Visa fil

@@ -1,3 +1,4 @@
import logging
import time import time
from flask import request from flask import request
from flask_classy import route from flask_classy import route
@@ -12,6 +13,8 @@ class FermenterView(BaseView):
model = Fermenter model = Fermenter
cache_key = "fermenter" cache_key = "fermenter"


def __init__(self):
self.logger = logging.getLogger(__name__)


def _post_post_callback(self, m): def _post_post_callback(self, m):
m.state = False m.state = False


+ 2
- 0
modules/login/__init__.py Visa fil

@@ -3,6 +3,8 @@ from flask import request


from modules.core.core import cbpi, addon from modules.core.core import cbpi, addon


import logging

class User(flask_login.UserMixin): class User(flask_login.UserMixin):
pass pass




+ 3
- 1
modules/logs/__init__.py Visa fil

@@ -7,6 +7,8 @@ from modules.core.core import cbpi
class LogView(FlaskView): class LogView(FlaskView):
_log_directory = "./logs"
@route('/', methods=['GET']) @route('/', methods=['GET'])
def get_all_logfiles(self): def get_all_logfiles(self):
""" """
@@ -19,7 +21,7 @@ class LogView(FlaskView):
description: List of all log files description: List of all log files
""" """
result = [] result = []
for filename in os.listdir("./logs"):
for filename in os.listdir(self._log_directory):
if filename.endswith(".log"): if filename.endswith(".log"):
result.append(filename) result.append(filename)
return json.dumps(result) return json.dumps(result)


+ 5
- 1
modules/recipe_import/kbh.py Visa fil

@@ -1,3 +1,5 @@
import logging

from flask import json, request from flask import json, request
from flask_classy import FlaskView, route from flask_classy import FlaskView, route
from git import Repo, Git from git import Repo, Git
@@ -11,6 +13,8 @@ from modules.step import Step, StepView




class KBH(FlaskView): class KBH(FlaskView):
def __init__(self):
self.logger = logging.getLogger(__name__)


@route('/', methods=['GET']) @route('/', methods=['GET'])
def get(self): def get(self):
@@ -39,7 +43,7 @@ class KBH(FlaskView):
result.append({"id": row[0], "name": row[1], "brewed": row[2]}) result.append({"id": row[0], "name": row[1], "brewed": row[2]})
return json.dumps(result) return json.dumps(result)
except Exception as e: except Exception as e:
print e
self.logger.error(e)
self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger")
return ('', 500) return ('', 500)
finally: finally:


+ 0
- 6
run.py Visa fil

@@ -1,12 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python


from modules.core.core import * from modules.core.core import *

cbpi = CraftBeerPI()

addon = cbpi.addon


from modules.core.db_migrate import * from modules.core.db_migrate import *
from modules.buzzer import * from modules.buzzer import *
from modules.config import * from modules.config import *


+ 0
- 0
tests/__init__.py Visa fil


+ 0
- 0
tests/logs/__init__.py Visa fil


+ 13
- 0
tests/logs/test_log_view.py Visa fil

@@ -0,0 +1,13 @@
from modules.logs import LogView
from tests.testlib import utils


class TestLogView(object):

def test_get_all_logfiles(self):
LogView._log_directory = utils.get_base_path() + "/logs"

logfiles = LogView().get_all_logfiles()

# if no log file is found then two square brackets "[]" are returned and string length is 2
assert (len(logfiles) > 2)

+ 0
- 0
tests/testlib/__init__.py Visa fil


+ 13
- 0
tests/testlib/utils.py Visa fil

@@ -0,0 +1,13 @@
import os


def get_base_path():
marker_file = "run.py"

current_path = os.getcwd()

while current_path != 0:
if marker_file in os.listdir(current_path):
return current_path

current_path = os.path.dirname(os.path.normpath(current_path))

+ 0
- 0
update/5_kairosdb_config.sql Visa fil


Laddar…
Avbryt
Spara