GPIO added

This commit is contained in:
manuel83 2019-01-04 09:29:09 +01:00
parent 6663a40cef
commit 00c7a465d7
36 changed files with 1129 additions and 1458 deletions

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@ import logging
from asyncio import Future
from cbpi_api import *
from voluptuous import Schema
from core.controller.crud_controller import CRUDController
from core.database.model import ActorModel
@ -29,23 +30,28 @@ class ActorController(CRUDController):
:return:
"""
await super(ActorController, self).init()
for id, value in self.cache.items():
await self._init_actor(value)
def get_state(self):
return dict(items=self.cache,types=self.types)
async def _init_actor(self, actor):
if actor.type in self.types:
try:
if actor.type in self.types:
cfg = actor.config.copy()
cfg.update(dict(cbpi=self.cbpi, id=id, name=actor.name))
clazz = self.types[actor.type]["class"];
self.cache[actor.id].instance = clazz(**cfg)
self.cache[actor.id].instance.init()
await self.cbpi.bus.fire(topic="actor/%s/initialized" % actor.id, id=actor.id)
else:
print("NOT FOUND")
self.logger.error("Actor type '%s' not found (Available Actor Types: %s)" % (actor.type, ', '.join(self.types.keys())))
cfg = actor.config.copy()
cfg.update(dict(cbpi=self.cbpi, id=id, name=actor.name))
clazz = self.types[actor.type]["class"];
self.cache[actor.id].instance = clazz(**cfg)
self.cache[actor.id].instance.init()
await self.cbpi.bus.fire(topic="actor/%s/initialized" % actor.id, id=actor.id)
else:
print("NOT FOUND")
self.logger.error("Actor type '%s' not found (Available Actor Types: %s)" % (actor.type, ', '.join(self.types.keys())))
except Exception as e:
self.logger.error("Failed to init actor %s - Reason %s" % (actor.id, str(e)))
async def _stop_actor(self, actor):
actor.instance.stop()
@ -93,6 +99,7 @@ class ActorController(CRUDController):
else:
actor.on()
@on_event(topic="actor/+/off")
async def off(self, actor_id, **kwargs) -> None:
"""
@ -102,7 +109,6 @@ class ActorController(CRUDController):
:param actor_id: the actor actor_id
:param kwargs:
"""
self.logger.debug("OFF %s" % actor_id)
actor_id = int(actor_id)
@ -110,6 +116,15 @@ class ActorController(CRUDController):
actor = self.cache[actor_id].instance
actor.off()
@on_event(topic="actor/+/action")
async def call_action(self, actor_id, data, **kwargs) -> None:
schema = Schema({"name":str, "parameter":dict})
schema(data)
name = data.get("name")
parameter = data.get("parameter")
actor = self.cache[actor_id].instance.__getattribute__(name)(**parameter)
async def _post_add_callback(self, m):
'''

View file

@ -30,6 +30,9 @@ class KettleController(CRUDController):
'''
await super(KettleController, self).init()
def get_state(self):
return dict(items=self.cache,types=self.types)
async def toggle_automtic(self, id):
'''

View file

@ -17,5 +17,6 @@ class NotificationController(object):
@on_event(topic="notification/#")
async def _on_event(self, key, message, type, **kwargs):
self.cbpi.ws.send("YES")
async def _on_event(self, key, message, type=None, **kwargs):
self.cbpi.ws.send(dict(key=message))

View file

@ -33,6 +33,9 @@ class SensorController(CRUDController):
for id, value in self.cache.items():
await self.init_sensor(value)
def get_state(self):
return dict(items=self.cache,types=self.types)
async def init_sensor(self, sensor):
if sensor.type in self.types:
cfg = sensor.config.copy()

View file

@ -1,4 +1,5 @@
import asyncio
import logging
import time
from cbpi_api import *
@ -17,14 +18,17 @@ class StepController(CRUDController):
def __init__(self, cbpi):
super(StepController, self).__init__(cbpi)
self.caching = False
self.is_stopping = False
self.cbpi = cbpi
self.current_task = None
self.is_next = False
self.types = {}
self.current_step = None
self.current_job = None
self.cbpi.register(self)
self.logger = logging.getLogger(__name__)
self.starttime = None
async def init(self):
'''
@ -54,6 +58,8 @@ class StepController(CRUDController):
self.current_job = await self.cbpi.job.start_job(self.current_step.run(), step.name, "step")
def get_state(self):
return dict(items=self.get_all(),types=self.types,is_running=self.is_running(),current_step=self.current_step)
@on_event("step/action")
async def handle_action(self, action, **kwargs):
@ -72,7 +78,7 @@ class StepController(CRUDController):
@on_event("step/next")
async def handle_next(self, **kwargs):
async def next(self, **kwargs):
'''
Event Handler for "step/next".
It start the next step
@ -80,28 +86,20 @@ class StepController(CRUDController):
:param kwargs:
:return: None
'''
if self.current_step is not None:
self.current_step.next()
pass
print("REQUEST NEXT")
self.starttime = time.time()
if self.current_step is not None and self.is_next is False:
self.logger.info("Request Next Step to start. Stopping current step")
self.is_next = True
self.current_step.stop()
else:
self.logger.info("Can Start Next")
@on_event("step/reset")
async def handle_reset(self, **kwargs):
'''
Event Handler for "step/reset".
Resets the current step
:param kwargs:
:return: None
'''
if self.current_step is not None:
await self.stop()
self.is_stopping = True
await self.model.reset_all_steps()
@on_event("job/step/done")
async def handle_step_done(self, topic, **kwargs):
async def _step_done(self, topic, **kwargs):
'''
Event Handler for "step/+/done".
@ -112,17 +110,23 @@ class StepController(CRUDController):
:return:
'''
# SHUTDONW DO NOTHING
self.logger.info("HANDLE DONE IS SHUTDONW %s IS STOPPING %s IS NEXT %s" % ( self.cbpi.shutdown, self.is_stopping, self.is_next))
if self.cbpi.shutdown:
return
self.cache[self.current_step.id].state = "D"
step_id = self.current_step.id
self.current_step = None
if self.is_stopping:
self.is_stopping = False
return
self.is_next = False
if self.current_step is not None:
await self.model.update_state(self.current_step.id, "D", int(time.time()))
self.current_step = None
await self.start()
if self.is_stopping is not True:
await self.start()
self.is_stopping = False
def _get_manged_fields_as_array(self, type_cfg):
@ -139,7 +143,7 @@ class StepController(CRUDController):
return False
@on_event("step/start")
async def start(self, future, **kwargs):
async def start(self, **kwargs):
'''
Start the first step
@ -147,39 +151,58 @@ class StepController(CRUDController):
:return:None
'''
if self.current_step is None:
loop = asyncio.get_event_loop()
open_step = False
if self.is_running() is False:
next_step = await self.model.get_by_state("I")
inactive = await self.model.get_by_state("I")
active = await self.model.get_by_state("A")
if next_step is not None:
step_type = self.types[next_step.type]
if active is not None:
active.state = 'D'
active.end = int(time.time())
# self.stop_step()
self.current_step = None
await self.model.update(**active.__dict__)
if inactive is not None:
step_type = self.types["CustomStepCBPi"]
config = dict(cbpi=self.cbpi, id=inactive.id, name=inactive.name, managed_fields=self._get_manged_fields_as_array(step_type))
config = dict(cbpi=self.cbpi, id=next_step.id, name=next_step.name, managed_fields=self._get_manged_fields_as_array(step_type))
self.current_step = step_type["class"](**config)
inactive.state = 'A'
inactive.stepstate = inactive.config
inactive.start = int(time.time())
await self.model.update(**inactive.__dict__)
self.current_job = await self.cbpi.job.start_job(self.current_step.run(), inactive.name, "step")
next_step.state = 'A'
next_step.stepstate = next_step.config
next_step.start = int(time.time())
await self.model.update(**next_step.__dict__)
if self.starttime is not None:
end = time.time()
d = end - self.starttime
print("DURATION", d)
else:
print("NORMAL START")
self.current_job = await self.cbpi.job.start_job(self.current_step.run(), next_step.name, "step")
await self.cbpi.bus.fire("step/%s/started" % self.current_step.id)
else:
await self.cbpi.bus.fire("step/berwing/finished")
future.set_result(True)
await self.cbpi.bus.fire("step/brewing/finished")
else:
self.logger.error("Process Already Running")
print("----------- END")
@on_event("step/stop")
async def stop(self, **kwargs):
if self.current_job is not None:
if self.current_step is not None:
self.current_step.stop()
self.is_stopping = True
await self.current_job.close()
await self.model.reset_all_steps()
self.current_step = None
await self.model.reset_all_steps()
await self.cbpi.bus.fire("step/brewing/stopped")
@on_event("step/reset")
async def handle_reset(self, **kwargs):
'''
Event Handler for "step/reset".
Resets the current step
:param kwargs:
:return: None
'''
if self.current_step is not None:
await self.stop()
self.current_step = None
self.is_stopping = True
await self.model.reset_all_steps()

View file

@ -4,6 +4,8 @@ from aiojobs.aiohttp import get_scheduler_from_app
from cbpi_api import *
from utils import json_dumps
class SystemController():
@ -12,6 +14,16 @@ class SystemController():
self.service = cbpi.actor
self.cbpi.register(self, "/system")
@request_mapping("/state", method="GET", auth_required=False)
def state(self, request):
# TODO implement restart
return web.json_response(data=dict(
actor=self.cbpi.actor.get_state(),
sensor=self.cbpi.sensor.get_state(),
kettle=self.cbpi.kettle.get_state(),
step=self.cbpi.step.get_state())
, dumps=json_dumps)
@request_mapping("/restart", method="POST", name="RestartServer", auth_required=False)
def restart(self, request):
# TODO implement restart

View file

@ -35,8 +35,6 @@ from http_endpoints.http_step import StepHttpEndpoints
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
@web.middleware
async def error_middleware(request, handler):
try:
@ -57,7 +55,6 @@ async def error_middleware(request, handler):
class CraftBeerPi():
def __init__(self):
self.static_config = load_config(os.path.join(os.path.dirname(__file__), '../config/config.yaml'))
self.database_file = "./craftbeerpi.db"
@ -117,7 +114,7 @@ class CraftBeerPi():
'''
self.register_http_endpoints(obj, url_prefix, static)
self.bus.register_object(obj)
self.ws.register_object(obj)
#self.ws.register_object(obj)
self.job.register_background_task(obj)
self.register_on_startup(obj)

View file

@ -58,6 +58,15 @@ class StepModel(DBModel):
cursor = await db.execute("UPDATE %s SET stepstate = ? WHERE id = ?" % cls.__table_name__, (json.dumps(state), step_id))
await db.commit()
@classmethod
async def update_state(cls, step_id, state, end=None):
async with aiosqlite.connect(DATABASE_FILE) as db:
if end is not None:
await db.execute("UPDATE %s SET state = ?, end = ? WHERE id = ?" % cls.__table_name__, (state, end, step_id))
else:
await db.execute("UPDATE %s SET state = ? WHERE id = ?" % cls.__table_name__, (state, step_id))
await db.commit()
@classmethod
async def get_by_state(cls, state, order=True):
@ -73,6 +82,7 @@ class StepModel(DBModel):
@classmethod
async def reset_all_steps(cls):
print("RESET ALL STEPS NOW")
async with aiosqlite.connect(DATABASE_FILE) as db:
await db.execute("UPDATE %s SET state = 'I', stepstate = NULL , start = NULL, end = NULL " % cls.__table_name__)
await db.commit()

View file

@ -51,6 +51,7 @@ class CBPiEventBus(object):
if method in self.registry:
raise RuntimeError("Method %s already registerd. Please unregister first!" % method.__name__)
self.logger.info("Topic %s", topic)
node = self._root
for sym in topic.split('/'):
node = node._children.setdefault(sym, self.Node())
@ -104,7 +105,6 @@ class CBPiEventBus(object):
self.loop = asyncio.get_event_loop()
def sync_fire(self,topic: str,timeout=1, **kwargs):
self.loop.create_task(self.fire(topic=topic, timeout=timeout, **kwargs))

View file

@ -1,44 +1,90 @@
import logging
from unittest.mock import MagicMock, patch
from cbpi_api import *
from cbpi_api.exceptions import CBPiException
logger = logging.getLogger(__name__)
try:
import RPi.GPIO as GPIO
except Exception:
logger.error("Failed to load RPi.GPIO. Using Mock")
MockRPi = MagicMock()
modules = {
"RPi": MockRPi,
"RPi.GPIO": MockRPi.GPIO
}
patcher = patch.dict("sys.modules", modules)
patcher.start()
import RPi.GPIO as GPIO
class CustomActor(CBPiActor):
# Custom property which can be configured by the user
gpio = Property.Number(label="Test")
v1 = Property.Text(label="Test")
v2 = Property.Kettle(label="Test")
v3 = Property.Sensor(label="Test")
def init(self):
pass
def stop(self):
pass
@action(key="name", parameters={})
def myAction(self):
pass
def state(self):
super().state()
def on(self, power=0):
logger.info("ACTOR %s ON" % self.id)
self.state = True
def off(self):
print("OFF")
# Code to swtich the actor off goes here
logger.info("ACTOR %s OFF " % self.id)
self.state = False
def on(self, power=100):
print("ON")
# Code to swtich the actor on goes here
class GPIOActor(CBPiActor):
# Custom property which can be configured by the user
gpio = Property.Select("GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], description="GPIO to which the actor is connected")
def init(self):
try:
GPIO.setup(int(self.gpio), GPIO.OUT)
GPIO.output(int(self.gpio), 0)
except Exception as e:
raise CBPiException("FAILD TO INIT ACTOR")
def on(self, power=0):
print("GPIO ON %s" % str(self.gpio))
GPIO.output(int(self.gpio), 1)
self.state = True
def off(self):
print("GPIO OFF %s" % str(self.gpio))
GPIO.output(int(self.gpio), 0)
self.state = False
class GPIORelayBoardActor(CBPiActor):
# Custom property which can be configured by the user
gpio = Property.Select("GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], description="GPIO to which the actor is connected")
def init(self):
try:
GPIO.setup(int(self.gpio), GPIO.OUT)
GPIO.output(int(self.gpio), 1)
except Exception as e:
raise CBPiException("FAILD TO INIT ACTOR")
def on(self, power=0):
print("GPIO ON %s" % str(self.gpio))
GPIO.output(int(self.gpio), 0)
self.state = True
def off(self):
print("GPIO OFF %s" % str(self.gpio))
GPIO.output(int(self.gpio), 1)
self.state = False
def setup(cbpi):

View file

@ -14,14 +14,12 @@ class CustomStepCBPi(CBPiSimpleStep):
self.name="WOOHOO"
async def run_cycle(self):
#await asyncio.sleep(1)
print("RUN", self.name)
self.i = self.i + 1
self.name="HALLO WELT"
if self.i == 20:
if self.i == 5:
# print("NEXT")
self.next()
self.cbpi.notify(key="step", message="HELLO FROM STEP")
#self.cbpi.notify(key="step", message="HELLO FROM STEP")

View file

@ -232,3 +232,38 @@ class ActorHttpEndpoints(HttpCrudEndpoints):
await self.cbpi.bus.fire(topic="actor/%s/toggle" % actor_id, actor_id=actor_id)
return web.Response(status=204)
@request_mapping(path="/{id:\d+}/action", method="POST", auth_required=auth)
async def http_action(self, request) -> web.Response:
"""
---
description: Toogle an actor on or off
tags:
- Actor
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
config:
type: object
responses:
"204":
description: successful operation
"""
actor_id = int(request.match_info['id'])
await self.cbpi.bus.fire(topic="actor/%s/action" % actor_id, actor_id=actor_id, data=await request.json())
return web.Response(status=204)

View file

@ -178,12 +178,10 @@ class StepHttpEndpoints(HttpCrudEndpoints):
"""
if self.controller.is_running():
raise CBPiException("Brewing Process Already Running")
result = await self.cbpi.bus.fire("step/start")
r = result.get("core.controller.step_controller.start")
if r[0] is True:
return web.Response(status=204)
else:
raise CBPiException("Failed to start brewing process")
print("FIRE START FROM HTTP")
await self.cbpi.bus.fire("step/start")
return web.Response(status=204)
@request_mapping(path="/reset", auth_required=False)
async def http_reset(self, request):

View file

@ -2,7 +2,6 @@ from json import JSONEncoder
class ComplexEncoder(JSONEncoder):
def default(self, obj):
from core.database.orm_framework import DBModel
@ -17,7 +16,7 @@ class ComplexEncoder(JSONEncoder):
#elif hasattr(obj, "callback"):
# return obj()
else:
return None
raise TypeError()
except TypeError:
pass
return None

View file

@ -1,11 +1,13 @@
import logging
import weakref
from collections import defaultdict
import json
import aiohttp
from aiohttp import web
from typing import Iterable, Callable
from cbpi_api import *
from voluptuous import Schema
from utils import json_dumps
class CBPiWebSocket:
@ -19,60 +21,53 @@ class CBPiWebSocket:
@on_event(topic="#")
async def listen(self, topic, **kwargs):
from core.utils.encoder import ComplexEncoder
data = json.dumps(dict(topic=topic, data=dict(**kwargs)),skipkeys=True, check_circular=True, cls=ComplexEncoder)
data = dict(topic=topic, data=dict(**kwargs))
self.logger.info("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_str(data)
await ws.send_json(data=data, dumps=json_dumps)
self.cbpi.app.loop.create_task(send_data(ws, data))
def add_callback(self, func: Callable, event: str) -> None:
self._callbacks[event].add(func)
def register_object(self, obj):
for method in [getattr(obj, f) for f in dir(obj) if callable(getattr(obj, f)) and hasattr(getattr(obj, f), "ws")]:
self.add_callback(method, method.__getattribute__("key"))
async def emit(self, event: str, *args, **kwargs) -> None:
for func in self._event_funcs(event):
await func(*args, **kwargs)
def _event_funcs(self, event: str) -> Iterable[Callable]:
for func in self._callbacks[event]:
yield func
async def websocket_handler(self, request):
ws = web.WebSocketResponse()
await ws.prepare(request)
self._clients.add(ws)
peername = request.transport.get_extra_info('peername')
if peername is not None:
host, port = peername
else:
host, port = "Unknowen"
c = len(self._clients) - 1
self.logger.info(ws)
self.logger.info(c)
self.logger.info("Client Connected - Host: %s Port: %s - client count: %s " % (host, port, len(self._clients)))
try:
await ws.send_json(data=dict(topic="connection/success"))
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if msg.data == 'close':
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()
self.logger.info("WS Close")
else:
msg_obj = msg.json()
await self.cbpi.bus.fire(msg_obj["topic"], id=1, power=22)
# await self.fire(msg_obj["key"], ws, msg)
# await ws.send_str(msg.data)
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)

Binary file not shown.

View file

@ -230,7 +230,7 @@
</li>
<li><a href="step.html#core.controller.step_controller.StepController.handle_done">handle_done() (core.controller.step_controller.StepController method)</a>
</li>
<li><a href="step.html#core.controller.step_controller.StepController.handle_next">handle_next() (core.controller.step_controller.StepController method)</a>
<li><a href="step.html#core.controller.step_controller.StepController.handle_next">next() (core.controller.step_controller.StepController method)</a>
</li>
<li><a href="step.html#core.controller.step_controller.StepController.handle_reset">handle_reset() (core.controller.step_controller.StepController method)</a>
</li>

View file

@ -220,7 +220,7 @@ Starts the next step</p>
<dl class="method">
<dt id="core.controller.step_controller.StepController.handle_next">
<code class="descname">handle_next</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.step_controller.StepController.handle_next" title="Permalink to this definition"></a></dt>
<code class="descname">next</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.step_controller.StepController.handle_next" title="Permalink to this definition"></a></dt>
<dd><p>Event Handler for “step/next”.
It start the next step</p>
<table class="docutils field-list" frame="void" rules="none">

View file

@ -1,24 +1,34 @@
2019-01-02 20:34:10,10
2019-01-02 20:34:15,10
2019-01-02 20:34:20,10
2019-01-02 20:34:25,10
2019-01-02 20:34:32,10
2019-01-02 20:34:37,10
2019-01-02 20:34:42,10
2019-01-02 20:34:47,10
2019-01-02 20:34:52,10
2019-01-02 20:34:57,10
2019-01-02 20:35:02,10
2019-01-02 20:35:07,10
2019-01-02 20:35:12,10
2019-01-02 20:35:17,10
2019-01-02 20:35:22,10
2019-01-02 20:35:30,10
2019-01-02 20:35:35,10
2019-01-02 20:35:40,10
2019-01-02 20:35:45,10
2019-01-02 20:35:50,10
2019-01-02 20:35:55,10
2019-01-02 20:36:00,10
2019-01-02 20:36:05,10
2019-01-02 20:36:10,10
2019-01-04 00:44:35,10
2019-01-04 00:44:40,10
2019-01-04 00:44:45,10
2019-01-04 00:44:50,10
2019-01-04 00:44:55,10
2019-01-04 00:45:00,10
2019-01-04 00:45:05,10
2019-01-04 00:45:10,10
2019-01-04 00:45:15,10
2019-01-04 00:45:20,10
2019-01-04 00:45:25,10
2019-01-04 00:45:30,10
2019-01-04 00:45:35,10
2019-01-04 00:45:40,10
2019-01-04 00:45:45,10
2019-01-04 00:45:50,10
2019-01-04 00:45:55,10
2019-01-04 00:46:00,10
2019-01-04 00:46:05,10
2019-01-04 00:46:10,10
2019-01-04 00:46:15,10
2019-01-04 00:46:20,10
2019-01-04 00:46:31,10
2019-01-04 00:46:36,10
2019-01-04 00:46:41,10
2019-01-04 00:46:46,10
2019-01-04 00:46:51,10
2019-01-04 00:46:56,10
2019-01-04 00:47:01,10
2019-01-04 00:47:06,10
2019-01-04 00:47:11,10
2019-01-04 00:47:16,10
2019-01-04 00:47:21,10
2019-01-04 00:47:26,10

View file

@ -1,86 +1,86 @@
2019-01-02 20:26:40,10
2019-01-02 20:26:45,10
2019-01-02 20:26:50,10
2019-01-02 20:26:55,10
2019-01-02 20:27:00,10
2019-01-02 20:27:05,10
2019-01-02 20:27:10,10
2019-01-02 20:27:15,10
2019-01-02 20:27:20,10
2019-01-02 20:27:25,10
2019-01-02 20:27:30,10
2019-01-02 20:27:35,10
2019-01-02 20:27:40,10
2019-01-02 20:27:45,10
2019-01-02 20:27:51,10
2019-01-02 20:27:56,10
2019-01-02 20:28:01,10
2019-01-02 20:28:06,10
2019-01-02 20:28:11,10
2019-01-02 20:28:16,10
2019-01-02 20:28:21,10
2019-01-02 20:28:26,10
2019-01-02 20:28:31,10
2019-01-02 20:28:36,10
2019-01-02 20:28:41,10
2019-01-02 20:28:46,10
2019-01-02 20:28:51,10
2019-01-02 20:28:56,10
2019-01-02 20:29:01,10
2019-01-02 20:29:06,10
2019-01-02 20:29:11,10
2019-01-02 20:29:16,10
2019-01-02 20:29:21,10
2019-01-02 20:29:26,10
2019-01-02 20:29:31,10
2019-01-02 20:29:36,10
2019-01-02 20:29:41,10
2019-01-02 20:29:46,10
2019-01-02 20:29:51,10
2019-01-02 20:29:56,10
2019-01-02 20:30:01,10
2019-01-02 20:30:06,10
2019-01-02 20:30:11,10
2019-01-02 20:30:16,10
2019-01-02 20:30:21,10
2019-01-02 20:30:26,10
2019-01-02 20:30:31,10
2019-01-02 20:30:36,10
2019-01-02 20:30:41,10
2019-01-02 20:30:46,10
2019-01-02 20:30:51,10
2019-01-02 20:30:56,10
2019-01-02 20:31:01,10
2019-01-02 20:31:06,10
2019-01-02 20:31:11,10
2019-01-02 20:31:16,10
2019-01-02 20:31:21,10
2019-01-02 20:31:26,10
2019-01-02 20:31:31,10
2019-01-02 20:31:36,10
2019-01-02 20:31:41,10
2019-01-02 20:31:46,10
2019-01-02 20:31:51,10
2019-01-02 20:31:56,10
2019-01-02 20:32:01,10
2019-01-02 20:32:06,10
2019-01-02 20:32:11,10
2019-01-02 20:32:16,10
2019-01-02 20:32:21,10
2019-01-02 20:32:26,10
2019-01-02 20:32:31,10
2019-01-02 20:32:36,10
2019-01-02 20:32:41,10
2019-01-02 20:33:05,10
2019-01-02 20:33:10,10
2019-01-02 20:33:15,10
2019-01-02 20:33:20,10
2019-01-02 20:33:25,10
2019-01-02 20:33:30,10
2019-01-02 20:33:35,10
2019-01-02 20:33:40,10
2019-01-02 20:33:45,10
2019-01-02 20:33:50,10
2019-01-02 20:33:55,10
2019-01-02 20:34:00,10
2019-01-02 20:34:05,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10
2019-01-04 00:19:48,10
2019-01-04 00:19:53,10
2019-01-04 00:20:04,10
2019-01-04 00:20:09,10
2019-01-04 00:20:14,10
2019-01-04 00:20:19,10
2019-01-04 00:20:24,10
2019-01-04 00:20:29,10
2019-01-04 00:20:34,10
2019-01-04 00:20:39,10
2019-01-04 00:20:44,10
2019-01-04 00:20:49,10
2019-01-04 00:20:54,10
2019-01-04 00:20:59,10
2019-01-04 00:38:43,10
2019-01-04 00:38:48,10
2019-01-04 00:38:53,10
2019-01-04 00:38:58,10
2019-01-04 00:39:03,10
2019-01-04 00:39:08,10
2019-01-04 00:39:13,10
2019-01-04 00:39:18,10
2019-01-04 00:39:23,10
2019-01-04 00:39:28,10
2019-01-04 00:39:33,10
2019-01-04 00:39:38,10
2019-01-04 00:39:45,10
2019-01-04 00:39:54,10
2019-01-04 00:39:59,10
2019-01-04 00:40:04,10
2019-01-04 00:40:09,10
2019-01-04 00:40:14,10
2019-01-04 00:40:21,10
2019-01-04 00:40:31,10
2019-01-04 00:40:36,10
2019-01-04 00:40:41,10
2019-01-04 00:40:46,10
2019-01-04 00:40:51,10
2019-01-04 00:40:56,10
2019-01-04 00:41:01,10
2019-01-04 00:41:06,10
2019-01-04 00:41:11,10
2019-01-04 00:41:16,10
2019-01-04 00:41:21,10
2019-01-04 00:41:26,10
2019-01-04 00:41:31,10
2019-01-04 00:41:36,10
2019-01-04 00:41:41,10
2019-01-04 00:41:46,10
2019-01-04 00:41:51,10
2019-01-04 00:41:56,10
2019-01-04 00:42:01,10
2019-01-04 00:42:06,10
2019-01-04 00:42:11,10
2019-01-04 00:42:16,10
2019-01-04 00:42:21,10
2019-01-04 00:42:26,10
2019-01-04 00:42:31,10
2019-01-04 00:42:36,10
2019-01-04 00:42:41,10
2019-01-04 00:42:46,10
2019-01-04 00:42:51,10
2019-01-04 00:42:56,10
2019-01-04 00:43:05,10
2019-01-04 00:43:10,10
2019-01-04 00:43:15,10
2019-01-04 00:43:20,10
2019-01-04 00:43:25,10
2019-01-04 00:43:30,10
2019-01-04 00:43:35,10
2019-01-04 00:43:40,10
2019-01-04 00:43:45,10
2019-01-04 00:43:50,10
2019-01-04 00:43:55,10
2019-01-04 00:44:00,10
2019-01-04 00:44:05,10
2019-01-04 00:44:10,10
2019-01-04 00:44:15,10
2019-01-04 00:44:20,10
2019-01-04 00:44:25,10
2019-01-04 00:44:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 18:48:13,10
2019-01-02 18:48:18,10
2019-01-02 18:48:23,10
2019-01-02 18:48:28,10
2019-01-02 18:48:33,10
2019-01-02 18:48:38,10
2019-01-02 18:48:43,10
2019-01-02 18:48:48,10
2019-01-02 18:48:53,10
2019-01-02 18:48:58,10
2019-01-02 18:49:03,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:07,10
2019-01-02 18:49:08,10
2019-01-02 18:49:13,10
2019-01-02 18:49:18,10
2019-01-02 18:49:23,10
2019-01-02 18:49:28,10
2019-01-02 18:49:33,10
2019-01-02 18:49:38,10
2019-01-02 18:49:43,10
2019-01-02 18:49:48,10
2019-01-02 18:49:53,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:49:58,10
2019-01-02 18:50:03,10
2019-01-02 18:50:08,10
2019-01-02 18:50:13,10
2019-01-02 18:50:18,10
2019-01-02 18:50:23,10
2019-01-02 18:50:28,10
2019-01-02 18:50:33,10
2019-01-02 18:50:38,10
2019-01-02 18:50:43,10
2019-01-02 18:50:48,10
2019-01-02 18:50:53,10
2019-01-02 18:50:58,10
2019-01-02 18:51:03,10
2019-01-02 18:51:08,10
2019-01-02 18:51:13,10
2019-01-02 18:51:18,10
2019-01-02 18:51:23,10
2019-01-02 18:51:28,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:29,10
2019-01-02 18:51:33,10
2019-01-02 18:51:38,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-02 18:51:43,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:43:47,10
2019-01-02 19:43:52,10
2019-01-02 19:43:57,10
2019-01-02 19:44:02,10
2019-01-02 19:44:07,10
2019-01-02 19:44:12,10
2019-01-02 19:44:17,10
2019-01-02 19:44:22,10
2019-01-02 19:44:27,10
2019-01-02 19:44:32,10
2019-01-02 19:44:37,10
2019-01-02 19:44:42,10
2019-01-02 19:44:47,10
2019-01-02 19:44:52,10
2019-01-02 19:44:57,10
2019-01-02 19:45:02,10
2019-01-02 19:45:07,10
2019-01-02 19:45:12,10
2019-01-02 19:45:17,10
2019-01-02 19:45:22,10
2019-01-02 19:45:27,10
2019-01-02 20:21:15,10
2019-01-02 20:21:20,10
2019-01-02 20:21:25,10
2019-01-02 20:21:30,10
2019-01-02 20:21:35,10
2019-01-02 20:21:40,10
2019-01-02 20:21:45,10
2019-01-02 20:21:50,10
2019-01-02 20:21:55,10
2019-01-02 20:22:00,10
2019-01-02 20:22:05,10
2019-01-02 20:22:10,10
2019-01-02 20:22:15,10
2019-01-02 20:22:20,10
2019-01-02 20:22:25,10
2019-01-02 20:22:30,10
2019-01-02 20:22:35,10
2019-01-02 20:22:40,10
2019-01-02 20:22:45,10
2019-01-02 20:22:50,10
2019-01-02 20:22:55,10
2019-01-02 20:23:00,10
2019-01-02 20:23:05,10
2019-01-02 20:23:10,10
2019-01-02 20:23:15,10
2019-01-02 20:23:20,10
2019-01-02 20:23:25,10
2019-01-02 20:23:30,10
2019-01-02 20:23:35,10
2019-01-02 20:23:40,10
2019-01-02 20:23:45,10
2019-01-02 20:23:50,10
2019-01-02 20:23:55,10
2019-01-02 20:24:00,10
2019-01-02 20:24:05,10
2019-01-02 20:24:10,10
2019-01-02 20:24:15,10
2019-01-02 20:24:20,10
2019-01-02 20:24:25,10
2019-01-02 20:24:30,10
2019-01-02 20:24:35,10
2019-01-02 20:24:40,10
2019-01-02 20:24:45,10
2019-01-02 20:24:50,10
2019-01-02 20:24:55,10
2019-01-02 20:25:00,10
2019-01-02 20:25:05,10
2019-01-02 20:25:10,10
2019-01-02 20:25:15,10
2019-01-02 20:25:20,10
2019-01-02 20:25:25,10
2019-01-02 20:25:30,10
2019-01-02 20:25:35,10
2019-01-02 20:25:40,10
2019-01-02 20:25:45,10
2019-01-02 20:25:50,10
2019-01-02 20:25:55,10
2019-01-02 20:26:00,10
2019-01-02 20:26:05,10
2019-01-02 20:26:10,10
2019-01-02 20:26:15,10
2019-01-02 20:26:20,10
2019-01-02 20:26:25,10
2019-01-02 20:26:30,10
2019-01-02 20:26:35,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:36:04,10
2019-01-02 19:36:09,10
2019-01-02 19:36:14,10
2019-01-02 19:36:19,10
2019-01-02 19:36:24,10
2019-01-02 19:36:29,10
2019-01-02 19:36:34,10
2019-01-02 19:36:39,10
2019-01-02 19:36:44,10
2019-01-02 19:36:49,10
2019-01-02 19:36:54,10
2019-01-02 19:36:59,10
2019-01-02 19:37:04,10
2019-01-02 19:37:09,10
2019-01-02 19:37:14,10
2019-01-02 19:37:19,10
2019-01-02 19:37:24,10
2019-01-02 19:37:30,10
2019-01-02 19:37:35,10
2019-01-02 19:37:40,10
2019-01-02 19:37:45,10
2019-01-02 19:37:50,10
2019-01-02 19:37:55,10
2019-01-02 19:38:00,10
2019-01-02 19:38:05,10
2019-01-02 19:38:10,10
2019-01-02 19:38:15,10
2019-01-02 19:38:20,10
2019-01-02 19:38:25,10
2019-01-02 19:38:30,10
2019-01-02 19:38:35,10
2019-01-02 19:38:44,10
2019-01-02 19:38:49,10
2019-01-02 19:38:54,10
2019-01-02 19:38:59,10
2019-01-02 19:39:04,10
2019-01-02 19:39:09,10
2019-01-02 19:39:14,10
2019-01-02 19:39:22,10
2019-01-02 19:39:27,10
2019-01-02 19:39:32,10
2019-01-02 19:39:37,10
2019-01-02 19:39:42,10
2019-01-02 19:39:47,10
2019-01-02 19:39:52,10
2019-01-02 19:39:58,10
2019-01-02 19:40:03,10
2019-01-02 19:40:08,10
2019-01-02 19:40:13,10
2019-01-02 19:40:18,10
2019-01-02 19:40:23,10
2019-01-02 19:40:28,10
2019-01-02 19:40:33,10
2019-01-02 19:40:43,10
2019-01-02 19:40:48,10
2019-01-02 19:40:53,10
2019-01-02 19:40:58,10
2019-01-02 19:41:03,10
2019-01-02 19:41:08,10
2019-01-02 19:41:20,10
2019-01-02 19:41:25,10
2019-01-02 19:41:36,10
2019-01-02 19:41:41,10
2019-01-02 19:41:46,10
2019-01-02 19:41:51,10
2019-01-02 19:41:56,10
2019-01-02 19:42:01,10
2019-01-02 19:42:06,10
2019-01-02 19:42:11,10
2019-01-02 19:42:16,10
2019-01-02 19:42:21,10
2019-01-02 19:42:26,10
2019-01-02 19:42:31,10
2019-01-02 19:42:36,10
2019-01-02 19:42:41,10
2019-01-02 19:42:46,10
2019-01-02 19:42:51,10
2019-01-02 19:42:56,10
2019-01-02 19:43:01,10
2019-01-02 19:43:06,10
2019-01-02 19:43:11,10
2019-01-02 19:43:22,10
2019-01-02 19:43:27,10
2019-01-02 19:43:32,10
2019-01-02 19:43:37,10
2019-01-02 19:43:42,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:28:35,10
2019-01-02 19:28:40,10
2019-01-02 19:28:47,10
2019-01-02 19:28:52,10
2019-01-02 19:28:57,10
2019-01-02 19:29:02,10
2019-01-02 19:29:07,10
2019-01-02 19:29:12,10
2019-01-02 19:29:17,10
2019-01-02 19:29:22,10
2019-01-02 19:29:27,10
2019-01-02 19:29:32,10
2019-01-02 19:29:44,10
2019-01-02 19:29:49,10
2019-01-02 19:29:54,10
2019-01-02 19:29:59,10
2019-01-02 19:30:04,10
2019-01-02 19:30:09,10
2019-01-02 19:30:14,10
2019-01-02 19:30:19,10
2019-01-02 19:30:24,10
2019-01-02 19:30:29,10
2019-01-02 19:30:34,10
2019-01-02 19:30:39,10
2019-01-02 19:30:46,10
2019-01-02 19:30:51,10
2019-01-02 19:30:56,10
2019-01-02 19:31:01,10
2019-01-02 19:31:09,10
2019-01-02 19:31:14,10
2019-01-02 19:31:19,10
2019-01-02 19:31:24,10
2019-01-02 19:31:29,10
2019-01-02 19:31:34,10
2019-01-02 19:31:39,10
2019-01-02 19:31:44,10
2019-01-02 19:31:49,10
2019-01-02 19:31:54,10
2019-01-02 19:31:59,10
2019-01-02 19:32:04,10
2019-01-02 19:32:13,10
2019-01-02 19:32:18,10
2019-01-02 19:32:23,10
2019-01-02 19:32:28,10
2019-01-02 19:32:33,10
2019-01-02 19:32:38,10
2019-01-02 19:32:43,10
2019-01-02 19:32:48,10
2019-01-02 19:32:53,10
2019-01-02 19:32:58,10
2019-01-02 19:33:03,10
2019-01-02 19:33:08,10
2019-01-02 19:33:13,10
2019-01-02 19:33:18,10
2019-01-02 19:33:23,10
2019-01-02 19:33:28,10
2019-01-02 19:33:33,10
2019-01-02 19:33:38,10
2019-01-02 19:33:43,10
2019-01-02 19:33:48,10
2019-01-02 19:33:53,10
2019-01-02 19:33:58,10
2019-01-02 19:34:03,10
2019-01-02 19:34:08,10
2019-01-02 19:34:13,10
2019-01-02 19:34:18,10
2019-01-02 19:34:23,10
2019-01-02 19:34:28,10
2019-01-02 19:34:33,10
2019-01-02 19:34:38,10
2019-01-02 19:34:44,10
2019-01-02 19:34:49,10
2019-01-02 19:34:54,10
2019-01-02 19:34:59,10
2019-01-02 19:35:04,10
2019-01-02 19:35:09,10
2019-01-02 19:35:14,10
2019-01-02 19:35:19,10
2019-01-02 19:35:24,10
2019-01-02 19:35:29,10
2019-01-02 19:35:34,10
2019-01-02 19:35:39,10
2019-01-02 19:35:44,10
2019-01-02 19:35:49,10
2019-01-02 19:35:54,10
2019-01-02 19:35:59,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:21:17,10
2019-01-02 19:21:22,10
2019-01-02 19:21:27,10
2019-01-02 19:21:32,10
2019-01-02 19:21:37,10
2019-01-02 19:21:42,10
2019-01-02 19:21:47,10
2019-01-02 19:21:52,10
2019-01-02 19:21:57,10
2019-01-02 19:22:02,10
2019-01-02 19:22:07,10
2019-01-02 19:22:12,10
2019-01-02 19:22:19,10
2019-01-02 19:22:24,10
2019-01-02 19:22:29,10
2019-01-02 19:22:34,10
2019-01-02 19:22:39,10
2019-01-02 19:22:44,10
2019-01-02 19:22:49,10
2019-01-02 19:22:54,10
2019-01-02 19:22:59,10
2019-01-02 19:23:04,10
2019-01-02 19:23:09,10
2019-01-02 19:23:14,10
2019-01-02 19:23:19,10
2019-01-02 19:23:24,10
2019-01-02 19:23:29,10
2019-01-02 19:23:34,10
2019-01-02 19:23:39,10
2019-01-02 19:23:44,10
2019-01-02 19:23:49,10
2019-01-02 19:23:54,10
2019-01-02 19:24:05,10
2019-01-02 19:24:10,10
2019-01-02 19:24:15,10
2019-01-02 19:24:20,10
2019-01-02 19:24:25,10
2019-01-02 19:24:30,10
2019-01-02 19:24:35,10
2019-01-02 19:24:40,10
2019-01-02 19:24:45,10
2019-01-02 19:24:50,10
2019-01-02 19:24:55,10
2019-01-02 19:25:00,10
2019-01-02 19:25:05,10
2019-01-02 19:25:10,10
2019-01-02 19:25:15,10
2019-01-02 19:25:20,10
2019-01-02 19:25:25,10
2019-01-02 19:25:30,10
2019-01-02 19:25:35,10
2019-01-02 19:25:40,10
2019-01-02 19:25:45,10
2019-01-02 19:25:50,10
2019-01-02 19:25:55,10
2019-01-02 19:26:00,10
2019-01-02 19:26:05,10
2019-01-02 19:26:10,10
2019-01-02 19:26:15,10
2019-01-02 19:26:20,10
2019-01-02 19:26:25,10
2019-01-02 19:26:30,10
2019-01-02 19:26:35,10
2019-01-02 19:26:40,10
2019-01-02 19:26:45,10
2019-01-02 19:26:50,10
2019-01-02 19:26:55,10
2019-01-02 19:27:00,10
2019-01-02 19:27:05,10
2019-01-02 19:27:10,10
2019-01-02 19:27:15,10
2019-01-02 19:27:20,10
2019-01-02 19:27:25,10
2019-01-02 19:27:30,10
2019-01-02 19:27:35,10
2019-01-02 19:27:40,10
2019-01-02 19:27:45,10
2019-01-02 19:27:50,10
2019-01-02 19:27:55,10
2019-01-02 19:28:00,10
2019-01-02 19:28:05,10
2019-01-02 19:28:10,10
2019-01-02 19:28:15,10
2019-01-02 19:28:20,10
2019-01-02 19:28:25,10
2019-01-02 19:28:30,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:14:06,10
2019-01-02 19:14:11,10
2019-01-02 19:14:16,10
2019-01-02 19:14:21,10
2019-01-02 19:14:26,10
2019-01-02 19:14:32,10
2019-01-02 19:14:37,10
2019-01-02 19:14:42,10
2019-01-02 19:14:47,10
2019-01-02 19:14:52,10
2019-01-02 19:14:57,10
2019-01-02 19:15:02,10
2019-01-02 19:15:07,10
2019-01-02 19:15:12,10
2019-01-02 19:15:17,10
2019-01-02 19:15:22,10
2019-01-02 19:15:27,10
2019-01-02 19:15:32,10
2019-01-02 19:15:37,10
2019-01-02 19:15:42,10
2019-01-02 19:15:47,10
2019-01-02 19:15:52,10
2019-01-02 19:15:57,10
2019-01-02 19:16:02,10
2019-01-02 19:16:07,10
2019-01-02 19:16:12,10
2019-01-02 19:16:17,10
2019-01-02 19:16:22,10
2019-01-02 19:16:27,10
2019-01-02 19:16:32,10
2019-01-02 19:16:37,10
2019-01-02 19:16:42,10
2019-01-02 19:16:47,10
2019-01-02 19:16:52,10
2019-01-02 19:16:57,10
2019-01-02 19:17:02,10
2019-01-02 19:17:07,10
2019-01-02 19:17:12,10
2019-01-02 19:17:17,10
2019-01-02 19:17:22,10
2019-01-02 19:17:27,10
2019-01-02 19:17:32,10
2019-01-02 19:17:37,10
2019-01-02 19:17:42,10
2019-01-02 19:17:47,10
2019-01-02 19:17:52,10
2019-01-02 19:17:57,10
2019-01-02 19:18:02,10
2019-01-02 19:18:07,10
2019-01-02 19:18:12,10
2019-01-02 19:18:17,10
2019-01-02 19:18:22,10
2019-01-02 19:18:27,10
2019-01-02 19:18:32,10
2019-01-02 19:18:37,10
2019-01-02 19:18:42,10
2019-01-02 19:18:47,10
2019-01-02 19:18:52,10
2019-01-02 19:18:57,10
2019-01-02 19:19:02,10
2019-01-02 19:19:07,10
2019-01-02 19:19:12,10
2019-01-02 19:19:17,10
2019-01-02 19:19:22,10
2019-01-02 19:19:27,10
2019-01-02 19:19:32,10
2019-01-02 19:19:37,10
2019-01-02 19:19:42,10
2019-01-02 19:19:47,10
2019-01-02 19:19:52,10
2019-01-02 19:19:57,10
2019-01-02 19:20:02,10
2019-01-02 19:20:07,10
2019-01-02 19:20:12,10
2019-01-02 19:20:17,10
2019-01-02 19:20:22,10
2019-01-02 19:20:27,10
2019-01-02 19:20:32,10
2019-01-02 19:20:37,10
2019-01-02 19:20:42,10
2019-01-02 19:20:47,10
2019-01-02 19:20:52,10
2019-01-02 19:20:57,10
2019-01-02 19:21:02,10
2019-01-02 19:21:07,10
2019-01-02 19:21:12,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 19:02:41,10
2019-01-02 19:02:46,10
2019-01-02 19:02:51,10
2019-01-02 19:02:56,10
2019-01-02 19:03:01,10
2019-01-02 19:03:06,10
2019-01-02 19:03:11,10
2019-01-02 19:03:16,10
2019-01-02 19:03:21,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:03:33,10
2019-01-02 19:08:33,10
2019-01-02 19:08:38,10
2019-01-02 19:08:43,10
2019-01-02 19:08:48,10
2019-01-02 19:08:53,10
2019-01-02 19:08:58,10
2019-01-02 19:09:03,10
2019-01-02 19:09:08,10
2019-01-02 19:09:16,10
2019-01-02 19:09:21,10
2019-01-02 19:09:26,10
2019-01-02 19:09:31,10
2019-01-02 19:09:36,10
2019-01-02 19:09:41,10
2019-01-02 19:09:46,10
2019-01-02 19:09:51,10
2019-01-02 19:09:56,10
2019-01-02 19:10:01,10
2019-01-02 19:10:06,10
2019-01-02 19:10:11,10
2019-01-02 19:10:16,10
2019-01-02 19:10:21,10
2019-01-02 19:10:26,10
2019-01-02 19:10:31,10
2019-01-02 19:10:36,10
2019-01-02 19:10:41,10
2019-01-02 19:10:46,10
2019-01-02 19:10:51,10
2019-01-02 19:10:56,10
2019-01-02 19:11:01,10
2019-01-02 19:11:06,10
2019-01-02 19:11:11,10
2019-01-02 19:11:16,10
2019-01-02 19:11:21,10
2019-01-02 19:11:26,10
2019-01-02 19:11:31,10
2019-01-02 19:11:36,10
2019-01-02 19:11:41,10
2019-01-02 19:11:46,10
2019-01-02 19:11:51,10
2019-01-02 19:11:56,10
2019-01-02 19:12:01,10
2019-01-02 19:12:06,10
2019-01-02 19:12:11,10
2019-01-02 19:12:16,10
2019-01-02 19:12:21,10
2019-01-02 19:12:26,10
2019-01-02 19:12:31,10
2019-01-02 19:12:36,10
2019-01-02 19:12:41,10
2019-01-02 19:12:46,10
2019-01-02 19:12:51,10
2019-01-02 19:12:56,10
2019-01-02 19:13:01,10
2019-01-02 19:13:06,10
2019-01-02 19:13:11,10
2019-01-02 19:13:16,10
2019-01-02 19:13:21,10
2019-01-02 19:13:26,10
2019-01-02 19:13:31,10
2019-01-02 19:13:36,10
2019-01-02 19:13:41,10
2019-01-02 19:13:46,10
2019-01-02 19:13:51,10
2019-01-02 19:13:56,10
2019-01-02 19:14:01,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,86 +1,5 @@
2019-01-02 18:51:48,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:58,10
2019-01-02 18:52:03,10
2019-01-02 18:52:08,10
2019-01-02 18:52:13,10
2019-01-02 18:52:18,10
2019-01-02 18:52:23,10
2019-01-02 18:52:28,10
2019-01-02 18:52:33,10
2019-01-02 18:52:38,10
2019-01-02 18:52:43,10
2019-01-02 18:52:48,10
2019-01-02 18:52:53,10
2019-01-02 18:52:58,10
2019-01-02 18:53:03,10
2019-01-02 18:53:08,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:13,10
2019-01-02 18:53:22,10
2019-01-02 18:53:27,10
2019-01-02 18:53:32,10
2019-01-02 18:53:37,10
2019-01-02 18:53:42,10
2019-01-02 18:53:47,10
2019-01-02 18:53:52,10
2019-01-02 18:53:57,10
2019-01-02 18:54:02,10
2019-01-02 18:54:07,10
2019-01-02 18:54:12,10
2019-01-02 18:54:17,10
2019-01-02 18:54:22,10
2019-01-02 18:54:27,10
2019-01-02 18:54:32,10
2019-01-02 18:54:37,10
2019-01-02 18:54:42,10
2019-01-02 18:54:47,10
2019-01-02 18:54:52,10
2019-01-02 18:54:57,10
2019-01-02 18:55:02,10
2019-01-02 18:55:07,10
2019-01-02 18:55:12,10
2019-01-02 18:55:17,10
2019-01-02 18:55:22,10
2019-01-02 18:55:27,10
2019-01-02 18:55:32,10
2019-01-02 18:55:37,10
2019-01-02 18:55:42,10
2019-01-02 18:55:47,10
2019-01-02 18:55:52,10
2019-01-02 18:55:57,10
2019-01-02 18:56:02,10
2019-01-02 18:56:07,10
2019-01-02 18:56:12,10
2019-01-02 18:56:17,10
2019-01-02 18:56:22,10
2019-01-02 18:56:27,10
2019-01-02 18:56:32,10
2019-01-02 18:56:37,10
2019-01-02 18:56:42,10
2019-01-02 18:56:47,10
2019-01-02 18:56:52,10
2019-01-02 18:56:57,10
2019-01-02 18:57:02,10
2019-01-02 18:57:07,10
2019-01-02 18:57:12,10
2019-01-02 18:57:17,10
2019-01-02 18:57:22,10
2019-01-02 18:57:27,10
2019-01-02 18:57:32,10
2019-01-02 18:57:37,10
2019-01-02 19:02:31,10
2019-01-02 19:02:36,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

View file

@ -1,9 +1,5 @@
2019-01-02 18:51:43,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-02 18:51:53,10
2019-01-04 00:19:10,10
2019-01-04 00:19:15,10
2019-01-04 00:19:20,10
2019-01-04 00:19:25,10
2019-01-04 00:19:30,10

BIN
tests/craftbeerpi.db Normal file

Binary file not shown.

View file

@ -1,4 +1,5 @@
import aiohttp
from unittest import mock
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
from core.craftbeerpi import CraftBeerPi
@ -6,14 +7,21 @@ from core.craftbeerpi import CraftBeerPi
class ActorTestCase(AioHTTPTestCase):
async def get_application(self):
self.cbpi = CraftBeerPi()
await self.cbpi.init_serivces()
return self.cbpi.app
@unittest_run_loop
async def test_actor_mock(self):
with mock.patch.object(self.cbpi.bus, 'fire', wraps=self.cbpi.bus.fire) as mock_obj:
# Send HTTP POST
resp = await self.client.request("POST", "/actor/1/on")
# Check Result
assert resp.status == 204
# Check if Event are fired
assert mock_obj.call_count == 2
@unittest_run_loop
async def test_actor_switch(self):
@ -92,3 +100,8 @@ class ActorTestCase(AioHTTPTestCase):
# Update not existing actor
resp = await self.client.put(path="/actor/%s" % 9999, json=data)
assert resp.status == 500
@unittest_run_loop
async def test_actor_action(self):
resp = await self.client.post(path="/actor/1/action", json=dict(name="myAction", parameter=dict(name="Manuel")))
assert resp.status == 204

49
tests/test_gpio.py Normal file
View file

@ -0,0 +1,49 @@
import unittest
from unittest import mock
from unittest.mock import MagicMock, patch
try:
import RPi.GPIO as GPIO
except Exception:
print("Error importing RPi.GPIO!")
MockRPi = MagicMock()
modules = {
"RPi": MockRPi,
"RPi.GPIO": MockRPi.GPIO
}
patcher = patch.dict("sys.modules", modules)
patcher.start()
import RPi.GPIO as GPIO
class HelloWorld(object):
def test(self, a):
return a
class TestSwitch(unittest.TestCase):
GPIO_NUM = 22
@patch("RPi.GPIO.setup")
def test_switch_inits_gpio(self, patched_setup):
GPIO.setmode(GPIO.BCM)
GPIO.setup(self.GPIO_NUM, GPIO.OUT)
patched_setup.assert_called_once_with(self.GPIO_NUM, GPIO.OUT)
@patch("RPi.GPIO.output")
def test_switch_without_scheduler_starts_disabled(self, patched_output):
GPIO.output(self.GPIO_NUM, GPIO.LOW)
patched_output.assert_called_once_with(self.GPIO_NUM, GPIO.LOW)
def test_hello_world(self):
h = HelloWorld()
with mock.patch.object(HelloWorld, 'test', wraps=h.test) as fake_increment:
#print(h.test("HALLO"))
print(h.test("ABC"))
print(fake_increment.call_args)
print(h.test("HALLO"))
print(fake_increment.call_args_list)

View file

@ -18,6 +18,12 @@ class IndexTestCase(AioHTTPTestCase):
resp = await self.client.get(path="/")
assert resp.status == 200
@unittest_run_loop
async def test_404(self):
# Test Index Page
resp = await self.client.get(path="/abc")
assert resp.status == 200
@unittest_run_loop
async def test_wrong_login(self):
resp = await self.client.post(path="/login", data={"username": "beer", "password": "123"})

View file

@ -1,4 +1,6 @@
import asyncio
from unittest import mock
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
from core.craftbeerpi import CraftBeerPi
@ -51,20 +53,46 @@ class StepTestCase(AioHTTPTestCase):
resp = await self.client.delete(path="/step/%s" % sensor_id)
assert resp.status == 204
def create_wait_callback(self, topic):
future = self.cbpi.app.loop.create_future()
async def test(**kwargs):
print("GOON")
future.set_result("OK")
self.cbpi.bus.register(topic, test, once=True)
return future
async def wait(self, future):
done, pending = await asyncio.wait({future})
if future in done:
pass
@unittest_run_loop
async def test_process(self):
resp = await self.client.request("GET", "/step/stop")
assert resp.status == 204
await self.cbpi.step.stop()
resp = await self.client.request("GET", "/step/start")
assert resp.status == 204
with mock.patch.object(self.cbpi.step, 'start', wraps=self.cbpi.step.start) as mock_obj:
resp = await self.client.request("GET", "/step/next")
assert resp.status == 204
future = self.create_wait_callback("step/+/started")
await self.cbpi.step.start()
await self.wait(future)
resp = await self.client.request("GET", "/step/stop")
assert resp.status == 204
future = self.create_wait_callback("step/+/started")
await self.cbpi.step.next()
await self.wait(future)
future = self.create_wait_callback("step/+/started")
await self.cbpi.step.next()
await self.wait(future)
future = self.create_wait_callback("step/+/started")
await self.cbpi.step.next()
await self.wait(future)
future = self.create_wait_callback("job/step/done")
await self.cbpi.step.stop()
await self.wait(future)
print("COUNT", mock_obj.call_count)
print("ARGS", mock_obj.call_args_list)

56
tests/test_ws.py Normal file
View file

@ -0,0 +1,56 @@
import asyncio
import aiohttp
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
from core.craftbeerpi import CraftBeerPi
class WebSocketTestCase(AioHTTPTestCase):
async def get_application(self):
self.cbpi = CraftBeerPi()
await self.cbpi.init_serivces()
return self.cbpi.app
@unittest_run_loop
async def test_brewing_process(self):
count_step_done = 0
async with self.client.ws_connect('/ws') as ws:
await ws.send_json(data=dict(topic="step/stop"))
await ws.send_json(data=dict(topic="step/start"))
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
try:
msg_obj = msg.json()
topic = msg_obj.get("topic")
if topic == "job/step/done":
count_step_done = count_step_done + 1
if topic == "step/brewing/finished":
await ws.send_json(data=dict(topic="close"))
except Exception as e:
print(e)
break
elif msg.type == aiohttp.WSMsgType.ERROR:
break
assert count_step_done == 4
@unittest_run_loop
async def test_wrong_format(self):
async with self.client.ws_connect('/ws') as ws:
await ws.send_json(data=dict(a="close"))
async for msg in ws:
print("MSG TYP", msg.type, msg.data)
if msg.type == aiohttp.WSMsgType.TEXT:
msg_obj = msg.json()
if msg_obj["topic"] != "connection/success":
print(msg.data)
raise Exception()
else:
raise Exception()