mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-09 17:07:43 +01:00
test cases extended
This commit is contained in:
parent
b800fed933
commit
1d85dc7c15
57 changed files with 3161 additions and 2496 deletions
1204
.idea/workspace.xml
1204
.idea/workspace.xml
File diff suppressed because it is too large
Load diff
|
@ -1,239 +1,13 @@
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from asyncio import Future
|
from asyncio import Future
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from cbpi_api import *
|
from cbpi_api import *
|
||||||
|
|
||||||
from core.controller.crud_controller import CRUDController
|
from core.controller.crud_controller import CRUDController
|
||||||
from core.database.model import ActorModel
|
from core.database.model import ActorModel
|
||||||
from core.http_endpoints.http_api import HttpAPI
|
|
||||||
from utils.encoder import ComplexEncoder
|
|
||||||
|
|
||||||
auth = False
|
|
||||||
|
|
||||||
class ActorHttp(HttpAPI):
|
|
||||||
|
|
||||||
@request_mapping(path="/types", auth_required=False)
|
|
||||||
async def get_types(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get all actor types
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().get_types(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", auth_required=False)
|
|
||||||
async def http_get_all(self, request):
|
|
||||||
"""
|
|
||||||
|
|
||||||
---
|
|
||||||
description: Switch actor on
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Actor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
return await super().http_get_all(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}", auth_required=False)
|
|
||||||
async def http_get_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get one Actor
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Actor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
return await super().http_get_one(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", method="POST", auth_required=False)
|
|
||||||
async def http_add(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get one Actor
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Created an actor
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_add(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
|
||||||
async def http_update(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Update an actor
|
|
||||||
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
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_update(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
|
||||||
async def http_delete_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Delete an actor
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Actor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_delete_one(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/on", method="POST", auth_required=auth)
|
|
||||||
async def http_on(self, request) -> web.Response:
|
|
||||||
"""
|
|
||||||
|
|
||||||
---
|
|
||||||
description: Switch actor on
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Actor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
id = int(request.match_info['id'])
|
|
||||||
result = await self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
|
|
||||||
for key, value in result.results.items():
|
|
||||||
pass
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/off", method="POST", auth_required=auth)
|
class ActorController(CRUDController):
|
||||||
async def http_off(self, request) -> web.Response:
|
|
||||||
"""
|
|
||||||
|
|
||||||
---
|
|
||||||
description: Switch actor off
|
|
||||||
tags:
|
|
||||||
- Actor
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Actor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
id = int(request.match_info['id'])
|
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/off" % id, id=id)
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/toggle", method="POST", auth_required=auth)
|
|
||||||
async def http_toggle(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"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
id = int(request.match_info['id'])
|
|
||||||
|
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/toggle" % id, id=id)
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
class ActorController(ActorHttp, CRUDController):
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
The main actor controller
|
The main actor controller
|
||||||
'''
|
'''
|
||||||
|
@ -244,21 +18,16 @@ class ActorController(ActorHttp, CRUDController):
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
self.state = False;
|
self.state = False;
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.cbpi.register(self, "/actor")
|
self.cbpi.register(self)
|
||||||
self.types = {}
|
self.types = {}
|
||||||
self.actors = {}
|
self.actors = {}
|
||||||
|
|
||||||
def info(self):
|
|
||||||
|
|
||||||
return json.dumps(dict(name="ActorController", types=self.types), cls=ComplexEncoder)
|
|
||||||
|
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
'''
|
"""
|
||||||
This method initializes all actors during startup. It creates actor instances
|
This method initializes all actors during startup. It creates actor instances
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
await super(ActorController, self).init()
|
await super(ActorController, self).init()
|
||||||
|
|
||||||
for id, value in self.cache.items():
|
for id, value in self.cache.items():
|
||||||
|
@ -278,71 +47,67 @@ class ActorController(ActorHttp, CRUDController):
|
||||||
print("NOT FOUND")
|
print("NOT FOUND")
|
||||||
self.logger.error("Actor type '%s' not found (Available Actor Types: %s)" % (actor.type, ', '.join(self.types.keys())))
|
self.logger.error("Actor type '%s' not found (Available Actor Types: %s)" % (actor.type, ', '.join(self.types.keys())))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def _stop_actor(self, actor):
|
async def _stop_actor(self, actor):
|
||||||
actor.instance.stop()
|
actor.instance.stop()
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/stopped" % actor.id, id=actor.id)
|
await self.cbpi.bus.fire(topic="actor/%s/stopped" % actor.id, id=actor.id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@on_event(topic="actor/+/switch/on")
|
@on_event(topic="actor/+/switch/on")
|
||||||
async def on(self, id , future: Future, power=100, **kwargs) -> None:
|
async def on(self, actor_id, future: Future, power=100, **kwargs) -> None:
|
||||||
'''
|
"""
|
||||||
Method to switch an actor on.
|
Method to switch an actor on.
|
||||||
Supporting Event Topic "actor/+/on"
|
Supporting Event Topic "actor/+/on"
|
||||||
|
|
||||||
:param actor_id: the actor id
|
:param actor_id: the actor id
|
||||||
|
:param future
|
||||||
:param power: as integer value between 1 and 100
|
:param power: as integer value between 1 and 100
|
||||||
:param kwargs:
|
:param kwargs:
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
|
|
||||||
id = int(id)
|
actor_id = int(actor_id)
|
||||||
if id in self.cache:
|
if actor_id in self.cache:
|
||||||
self.logger.debug("ON %s" % id)
|
self.logger.debug("ON %s" % actor_id)
|
||||||
actor = self.cache[id].instance
|
actor = self.cache[actor_id].instance
|
||||||
await self.cbpi.bus.fire("actor/%s/on/ok" % id)
|
await self.cbpi.bus.fire("actor/%s/on/ok" % actor_id)
|
||||||
actor.on(power)
|
actor.on(power)
|
||||||
|
|
||||||
future.set_result("OK")
|
future.set_result("OK")
|
||||||
|
|
||||||
@on_event(topic="actor/+/toggle")
|
@on_event(topic="actor/+/toggle")
|
||||||
async def toggle(self, id, power=100, **kwargs) -> None:
|
async def toggle(self, actor_id, power=100, **kwargs) -> None:
|
||||||
'''
|
"""
|
||||||
Method to toggle an actor on or off
|
Method to toggle an actor on or off
|
||||||
Supporting Event Topic "actor/+/toggle"
|
Supporting Event Topic "actor/+/toggle"
|
||||||
|
|
||||||
:param id: the actor id
|
:param actor_id: the actor actor_id
|
||||||
:param power: the power as interger between 0 and 100
|
:param power: the power as integer between 0 and 100
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
|
|
||||||
self.logger.debug("TOGGLE %s" % id)
|
self.logger.debug("TOGGLE %s" % actor_id)
|
||||||
id = int(id)
|
actor_id = int(actor_id)
|
||||||
if id in self.cache:
|
if actor_id in self.cache:
|
||||||
actor = self.cache[id].instance
|
actor = self.cache[actor_id].instance
|
||||||
if actor.state is True:
|
if actor.state is True:
|
||||||
actor.off()
|
actor.off()
|
||||||
else:
|
else:
|
||||||
actor.on()
|
actor.on()
|
||||||
|
|
||||||
@on_event(topic="actor/+/off")
|
@on_event(topic="actor/+/off")
|
||||||
async def off(self, id, **kwargs) -> None:
|
async def off(self, actor_id, **kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Method to switch and actor off
|
Method to switch and actor off
|
||||||
Supporting Event Topic "actor/+/off"
|
Supporting Event Topic "actor/+/off"
|
||||||
|
|
||||||
:param id: the actor id
|
:param actor_id: the actor actor_id
|
||||||
:param kwargs:
|
:param kwargs:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.debug("OFF %s" % id)
|
self.logger.debug("OFF %s" % actor_id)
|
||||||
id = int(id)
|
actor_id = int(actor_id)
|
||||||
|
|
||||||
if id in self.cache:
|
if actor_id in self.cache:
|
||||||
actor = self.cache[id].instance
|
actor = self.cache[actor_id].instance
|
||||||
actor.off()
|
actor.off()
|
||||||
|
|
||||||
async def _post_add_callback(self, m):
|
async def _post_add_callback(self, m):
|
||||||
|
@ -355,14 +120,12 @@ class ActorController(ActorHttp, CRUDController):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _pre_delete_callback(self, actor_id):
|
async def _pre_delete_callback(self, actor_id):
|
||||||
if int(actor_id) not in self.cache:
|
#if int(actor_id) not in self.cache:
|
||||||
return
|
# return
|
||||||
|
|
||||||
if self.cache[int(actor_id)].instance is not None:
|
if self.cache[int(actor_id)].instance is not None:
|
||||||
await self._stop_actor(self.cache[int(actor_id)])
|
await self._stop_actor(self.cache[int(actor_id)])
|
||||||
|
|
||||||
async def _pre_update_callback(self, actor):
|
async def _pre_update_callback(self, actor):
|
||||||
|
|
||||||
if actor.instance is not None:
|
if actor.instance is not None:
|
||||||
await self._stop_actor(actor)
|
await self._stop_actor(actor)
|
||||||
|
|
||||||
|
|
|
@ -1,77 +1,13 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from cbpi_api import request_mapping
|
|
||||||
from cbpi_api.exceptions import CBPiException
|
|
||||||
|
|
||||||
from core.controller.crud_controller import CRUDController
|
|
||||||
from core.database.model import ConfigModel
|
|
||||||
from utils import load_config, json_dumps
|
|
||||||
from cbpi_api.config import ConfigType
|
from cbpi_api.config import ConfigType
|
||||||
|
|
||||||
class ConfigHTTPController():
|
from core.database.model import ConfigModel
|
||||||
@request_mapping(path="/{name}/", method="POST", auth_required=False)
|
from utils import load_config
|
||||||
async def http_post(self, request) -> web.Response:
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Set config parameter
|
|
||||||
tags:
|
|
||||||
- Config
|
|
||||||
parameters:
|
|
||||||
- name: "name"
|
|
||||||
in: "path"
|
|
||||||
description: "Parameter name"
|
|
||||||
required: true
|
|
||||||
type: "string"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
name = request.match_info['name']
|
|
||||||
data = await request.json()
|
|
||||||
print(data)
|
|
||||||
await self.set(name=name, value=data.get("value"))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/", auth_required=False)
|
|
||||||
async def http_get_all(self, request) -> web.Response:
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get all config parameters
|
|
||||||
tags:
|
|
||||||
- Config
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return web.json_response(self.cache, dumps=json_dumps)
|
|
||||||
|
|
||||||
@request_mapping(path="/{name}/", auth_required=False)
|
|
||||||
async def http_paramter(self, request) -> web.Response:
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get all config parameters
|
|
||||||
tags:
|
|
||||||
- Config
|
|
||||||
parameters:
|
|
||||||
- name: "name"
|
|
||||||
in: "path"
|
|
||||||
description: "Parameter name"
|
|
||||||
required: true
|
|
||||||
type: "string"
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
name = request.match_info['name']
|
|
||||||
if name not in self.cache:
|
|
||||||
raise CBPiException("Parameter %s not found" % name)
|
|
||||||
|
|
||||||
return web.json_response(self.cache.get(name), dumps=json_dumps)
|
|
||||||
|
|
||||||
class ConfigController(ConfigHTTPController):
|
|
||||||
|
|
||||||
|
class ConfigController():
|
||||||
'''
|
'''
|
||||||
The main actor controller
|
The main actor controller
|
||||||
'''
|
'''
|
||||||
|
@ -81,7 +17,7 @@ class ConfigController(ConfigHTTPController):
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
self.cbpi.register(self, "/config")
|
self.cbpi.register(self)
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
this_directory = os.path.dirname(__file__)
|
this_directory = os.path.dirname(__file__)
|
||||||
|
@ -90,7 +26,6 @@ class ConfigController(ConfigHTTPController):
|
||||||
for key, value in items.items():
|
for key, value in items.items():
|
||||||
self.cache[value.name] = value
|
self.cache[value.name] = value
|
||||||
|
|
||||||
|
|
||||||
def get(self, name, default=None):
|
def get(self, name, default=None):
|
||||||
self.logger.info("GET CONFIG VALUE %s (default %s)" % (name, default))
|
self.logger.info("GET CONFIG VALUE %s (default %s)" % (name, default))
|
||||||
if name in self.cache and self.cache[name].value is not None:
|
if name in self.cache and self.cache[name].value is not None:
|
||||||
|
@ -101,12 +36,10 @@ class ConfigController(ConfigHTTPController):
|
||||||
async def set(self, name, value):
|
async def set(self, name, value):
|
||||||
self.logger.debug("SET %s = %s" % (name, value))
|
self.logger.debug("SET %s = %s" % (name, value))
|
||||||
if name in self.cache:
|
if name in self.cache:
|
||||||
|
|
||||||
self.cache[name].value = value
|
self.cache[name].value = value
|
||||||
m = await self.model.update(**self.cache[name].__dict__)
|
await self.model.update(**self.cache[name].__dict__)
|
||||||
await self.cbpi.bus.fire(topic="config/%s/update" % name, name=name, value=value)
|
await self.cbpi.bus.fire(topic="config/%s/update" % name, name=name, value=value)
|
||||||
|
|
||||||
|
|
||||||
async def add(self, name, value, type: ConfigType, description, options=None):
|
async def add(self, name, value, type: ConfigType, description, options=None):
|
||||||
m = await self.model.insert(name=name, value=value, type=type.value, description=description, options=options)
|
await self.model.insert(name=name, value=value, type=type.value, description=description, options=options)
|
||||||
await self.cbpi.bus.fire(topic="config/%s/add" % name, name=name, value=value)
|
await self.cbpi.bus.fire(topic="config/%s/add" % name, name=name, value=value)
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import pprint
|
import pprint
|
||||||
from abc import ABCMeta
|
from abc import ABCMeta
|
||||||
|
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
|
||||||
|
|
||||||
class CRUDController(metaclass=ABCMeta):
|
class CRUDController(metaclass=ABCMeta):
|
||||||
|
|
||||||
|
|
||||||
cache = {}
|
cache = {}
|
||||||
caching = True
|
caching = True
|
||||||
|
name = None
|
||||||
|
|
||||||
def __init__(self, cbpi):
|
def __init__(self, cbpi):
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
|
@ -17,6 +20,7 @@ class CRUDController(metaclass=ABCMeta):
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if self.caching is True:
|
if self.caching is True:
|
||||||
self.cache = await self.model.get_all()
|
self.cache = await self.model.get_all()
|
||||||
|
|
||||||
|
@ -37,6 +41,8 @@ class CRUDController(metaclass=ABCMeta):
|
||||||
:param id:
|
:param id:
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
|
if id not in self.cache:
|
||||||
|
raise CBPiException("%s with id %s not found" % (self.name,id))
|
||||||
return self.cache.get(id)
|
return self.cache.get(id)
|
||||||
|
|
||||||
async def _pre_add_callback(self, data):
|
async def _pre_add_callback(self, data):
|
||||||
|
@ -61,8 +67,13 @@ class CRUDController(metaclass=ABCMeta):
|
||||||
:param data:
|
:param data:
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
await self._pre_add_callback(data)
|
await self._pre_add_callback(data)
|
||||||
|
print("INSSERT ADD", data)
|
||||||
|
|
||||||
m = await self.model.insert(**data)
|
m = await self.model.insert(**data)
|
||||||
|
|
||||||
self.cache[m.id] = m
|
self.cache[m.id] = m
|
||||||
await self._post_add_callback(m)
|
await self._post_add_callback(m)
|
||||||
|
|
||||||
|
@ -83,7 +94,14 @@ class CRUDController(metaclass=ABCMeta):
|
||||||
:param data:
|
:param data:
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
id = int(id)
|
id = int(id)
|
||||||
|
|
||||||
|
if id not in self.cache:
|
||||||
|
raise CBPiException("%s with id %s not found" % (self.name,id))
|
||||||
|
|
||||||
data["id"] = id
|
data["id"] = id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -121,19 +139,16 @@ class CRUDController(metaclass=ABCMeta):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def delete(self, id):
|
async def delete(self, id):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
:param id:
|
:param id:
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
await self._pre_delete_callback(id)
|
|
||||||
|
|
||||||
if id not in self.cache:
|
if id not in self.cache:
|
||||||
|
raise CBPiException("%s with id %s not found" % (self.name,id))
|
||||||
|
|
||||||
return
|
await self._pre_delete_callback(id)
|
||||||
m = await self.model.delete(id)
|
m = await self.model.delete(id)
|
||||||
await self._post_delete_callback(id)
|
await self._post_delete_callback(id)
|
||||||
try:
|
try:
|
||||||
|
|
30
core/controller/dashboard_controller.py
Normal file
30
core/controller/dashboard_controller.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from voluptuous import Schema, MultipleInvalid
|
||||||
|
|
||||||
|
from core.controller.crud_controller import CRUDController
|
||||||
|
from core.database.model import DashboardModel, DashboardContentModel
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardController(CRUDController):
|
||||||
|
|
||||||
|
model = DashboardModel
|
||||||
|
name = "Dashboard"
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super(DashboardController, self).__init__(cbpi)
|
||||||
|
self.cbpi = cbpi
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
self.cbpi.register(self)
|
||||||
|
|
||||||
|
async def get_content(self, dashboard_id):
|
||||||
|
return await DashboardContentModel.get_by_dashboard_id(dashboard_id)
|
||||||
|
|
||||||
|
async def add_content(self, data):
|
||||||
|
return await DashboardContentModel.insert(**data)
|
||||||
|
|
||||||
|
async def delete_content(self, content_id):
|
||||||
|
await DashboardContentModel.delete(content_id)
|
||||||
|
|
||||||
|
async def move_content(self,content_id, x, y):
|
||||||
|
await DashboardContentModel.update_coordinates(content_id, x, y)
|
|
@ -1,9 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from cbpi_api import request_mapping
|
|
||||||
|
|
||||||
from job.aiohttp import setup, get_scheduler_from_app
|
from job.aiohttp import setup, get_scheduler_from_app
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
|
@ -1,56 +1,16 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from cbpi_api import *
|
from cbpi_api import *
|
||||||
from cbpi_api.exceptions import KettleException, ActorException, SensorException
|
from cbpi_api.exceptions import KettleException, ActorException, SensorException
|
||||||
|
|
||||||
from core.controller.crud_controller import CRUDController
|
from core.controller.crud_controller import CRUDController
|
||||||
from core.database.model import KettleModel
|
from core.database.model import KettleModel
|
||||||
from core.http_endpoints.http_api import HttpAPI
|
|
||||||
from core.job.aiohttp import get_scheduler_from_app
|
from core.job.aiohttp import get_scheduler_from_app
|
||||||
|
|
||||||
|
|
||||||
class KettleHttp(HttpAPI):
|
class KettleController(CRUDController):
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/automatic", auth_required=False)
|
|
||||||
async def http_automatic(self, request):
|
|
||||||
await self.cbpi.kettle.toggle_automtic(int(request.match_info['id']))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/heater/on", auth_required=False)
|
|
||||||
async def http_heater_on(self, request):
|
|
||||||
await self.cbpi.kettle.heater_on(int(request.match_info['id']))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/heater/off", auth_required=False)
|
|
||||||
async def http_heater_off(self, request):
|
|
||||||
await self.cbpi.kettle.heater_off(int(request.match_info['id']))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/agitator/on", auth_required=False)
|
|
||||||
async def http_agitator_on(self, request):
|
|
||||||
await self.cbpi.kettle.agitator_on(int(request.match_info['id']))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/agitator/off", auth_required=False)
|
|
||||||
async def http_agitator_off(self, request):
|
|
||||||
await self.cbpi.kettle.agitator_off(int(request.match_info['id']))
|
|
||||||
return web.Response(status=204)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/targettemp", auth_required=False)
|
|
||||||
async def http_taget_temp(self, request):
|
|
||||||
kettle_id = int(request.match_info['id'])
|
|
||||||
temp = await self.cbpi.kettle.get_traget_temp(kettle_id)
|
|
||||||
return web.json_response(data=dict(target_temp=temp, kettle_id=kettle_id))
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}/temp", auth_required=False)
|
|
||||||
async def http_temp(self, request):
|
|
||||||
kettle_id = int(request.match_info['id'])
|
|
||||||
temp = await self.cbpi.kettle.get_temp(kettle_id)
|
|
||||||
return web.json_response(data=dict(temp=temp, kettle_id=kettle_id))
|
|
||||||
|
|
||||||
|
|
||||||
class KettleController(CRUDController, KettleHttp):
|
|
||||||
'''
|
'''
|
||||||
The main kettle controller
|
The main kettle controller
|
||||||
'''
|
'''
|
||||||
|
@ -60,7 +20,7 @@ class KettleController(CRUDController, KettleHttp):
|
||||||
super(KettleController, self).__init__(cbpi)
|
super(KettleController, self).__init__(cbpi)
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
self.types = {}
|
self.types = {}
|
||||||
self.cbpi.register(self, "/kettle")
|
self.cbpi.register(self)
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
'''
|
'''
|
||||||
|
@ -142,8 +102,8 @@ class KettleController(CRUDController, KettleHttp):
|
||||||
raise KettleException("Kettle not found")
|
raise KettleException("Kettle not found")
|
||||||
if kettle.sensor is None:
|
if kettle.sensor is None:
|
||||||
raise ActorException("Actor not defined for kettle id %s" % id)
|
raise ActorException("Actor not defined for kettle id %s" % id)
|
||||||
id = kettle.heater
|
heater_id = kettle.heater
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
|
await self.cbpi.bus.fire(topic="actor/%s/switch/on" % heater_id, actor_id=heater_id, power=99)
|
||||||
|
|
||||||
async def heater_off(self, id):
|
async def heater_off(self, id):
|
||||||
'''
|
'''
|
||||||
|
@ -158,8 +118,8 @@ class KettleController(CRUDController, KettleHttp):
|
||||||
raise KettleException("Kettle not found")
|
raise KettleException("Kettle not found")
|
||||||
if kettle.sensor is None:
|
if kettle.sensor is None:
|
||||||
raise ActorException("Actor not defined for kettle id %s" % id)
|
raise ActorException("Actor not defined for kettle id %s" % id)
|
||||||
id = kettle.heater
|
heater_id = kettle.heater
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/switch/off" % id, id=id, power=99)
|
await self.cbpi.bus.fire(topic="actor/%s/switch/off" % heater_id, actor_id=heater_id, power=99)
|
||||||
|
|
||||||
async def agitator_on(self, id):
|
async def agitator_on(self, id):
|
||||||
kettle = await self.get_one(id)
|
kettle = await self.get_one(id)
|
||||||
|
@ -168,7 +128,7 @@ class KettleController(CRUDController, KettleHttp):
|
||||||
if kettle.sensor is None:
|
if kettle.sensor is None:
|
||||||
raise ActorException("Actor not defined for kettle id %s" % id)
|
raise ActorException("Actor not defined for kettle id %s" % id)
|
||||||
agitator_id = kettle.agitator
|
agitator_id = kettle.agitator
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/switch/on" % agitator_id, id=agitator_id, power=99)
|
await self.cbpi.bus.fire(topic="actor/%s/switch/on" % agitator_id, actor_id=agitator_id, power=99)
|
||||||
|
|
||||||
async def agitator_off(self, id):
|
async def agitator_off(self, id):
|
||||||
kettle = await self.get_one(id)
|
kettle = await self.get_one(id)
|
||||||
|
@ -177,7 +137,7 @@ class KettleController(CRUDController, KettleHttp):
|
||||||
if kettle.sensor is None:
|
if kettle.sensor is None:
|
||||||
raise ActorException("Actor not defined for kettle id %s" % id)
|
raise ActorException("Actor not defined for kettle id %s" % id)
|
||||||
agitator_id = kettle.agitator
|
agitator_id = kettle.agitator
|
||||||
await self.cbpi.bus.fire(topic="actor/%s/switch/off" % agitator_id, id=agitator_id, power=99)
|
await self.cbpi.bus.fire(topic="actor/%s/switch/off" % agitator_id, actor_id=agitator_id, power=99)
|
||||||
|
|
||||||
async def get_traget_temp(self, id):
|
async def get_traget_temp(self, id):
|
||||||
kettle = await self.get_one(id)
|
kettle = await self.get_one(id)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from cbpi_api import *
|
from cbpi_api import *
|
||||||
|
|
||||||
class NotificationController():
|
|
||||||
|
class NotificationController(object):
|
||||||
'''
|
'''
|
||||||
This the notification controller
|
This the notification controller
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -5,161 +5,30 @@ from cbpi_api import request_mapping
|
||||||
|
|
||||||
from core.controller.crud_controller import CRUDController
|
from core.controller.crud_controller import CRUDController
|
||||||
from core.database.model import SensorModel
|
from core.database.model import SensorModel
|
||||||
from core.http_endpoints.http_api import HttpAPI
|
|
||||||
from core.job.aiohttp import get_scheduler_from_app
|
from core.job.aiohttp import get_scheduler_from_app
|
||||||
from core.utils.encoder import ComplexEncoder
|
from core.utils.encoder import ComplexEncoder
|
||||||
|
|
||||||
|
|
||||||
class SensorController(CRUDController, HttpAPI):
|
class SensorController(CRUDController):
|
||||||
|
|
||||||
model = SensorModel
|
model = SensorModel
|
||||||
|
|
||||||
def __init__(self, cbpi):
|
def __init__(self, cbpi):
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
self.cbpi.register(self, "/sensor")
|
self.cbpi.register(self)
|
||||||
self.service = self
|
self.service = self
|
||||||
self.types = {}
|
self.types = {}
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.sensors = {}
|
self.sensors = {}
|
||||||
|
|
||||||
def info(self):
|
|
||||||
return json.dumps(dict(name="SensorController", types=self.types), cls=ComplexEncoder)
|
|
||||||
|
|
||||||
@request_mapping(path="/types", auth_required=False)
|
|
||||||
async def get_types(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get all sensor types
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().get_types(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", auth_required=False)
|
|
||||||
async def http_get_all(self, request):
|
|
||||||
"""
|
|
||||||
|
|
||||||
---
|
|
||||||
description: Get all sensor
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_get_all(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}", auth_required=False)
|
|
||||||
async def http_get_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get an sensor
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Sensor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
return await super().http_get_one(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", method="POST", auth_required=False)
|
|
||||||
async def http_add(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get one sensor
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Created an sensor
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_add(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
|
||||||
async def http_update(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Update an sensor
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Sensor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Update an sensor
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_update(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
|
||||||
async def http_delete_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Delete an sensor
|
|
||||||
tags:
|
|
||||||
- Sensor
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Sensor ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_delete_one(request)
|
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
'''
|
'''
|
||||||
This method initializes all actors during startup. It creates actor instances
|
This method initializes all actors during startup. It creates actor instances
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
await super(SensorController, self).init()
|
await super(SensorController, self).init()
|
||||||
for id, value in self.cache.items():
|
for id, value in self.cache.items():
|
||||||
await self.init_sensor(value)
|
await self.init_sensor(value)
|
||||||
|
@ -198,7 +67,6 @@ class SensorController(CRUDController, HttpAPI):
|
||||||
async def _pre_delete_callback(self, sensor_id):
|
async def _pre_delete_callback(self, sensor_id):
|
||||||
if int(sensor_id) not in self.cache:
|
if int(sensor_id) not in self.cache:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.cache[int(sensor_id)].instance is not None:
|
if self.cache[int(sensor_id)].instance is not None:
|
||||||
await self.stop_sensor(self.cache[int(sensor_id)])
|
await self.stop_sensor(self.cache[int(sensor_id)])
|
||||||
|
|
||||||
|
|
|
@ -1,233 +1,13 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from cbpi_api import *
|
from cbpi_api import *
|
||||||
from cbpi_api.exceptions import CBPiException
|
|
||||||
|
|
||||||
from core.controller.crud_controller import CRUDController
|
from core.controller.crud_controller import CRUDController
|
||||||
from core.database.model import StepModel
|
from core.database.model import StepModel
|
||||||
from core.http_endpoints.http_api import HttpAPI
|
|
||||||
|
|
||||||
|
|
||||||
class StepHttpAPI(HttpAPI):
|
class StepController(CRUDController):
|
||||||
@request_mapping(path="/types", auth_required=False)
|
|
||||||
async def get_types(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get all step types
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().get_types(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", auth_required=False)
|
|
||||||
async def http_get_all(self, request):
|
|
||||||
"""
|
|
||||||
|
|
||||||
---
|
|
||||||
description: Switch step on
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "step ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
return await super().http_get_all(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}", auth_required=False)
|
|
||||||
async def http_get_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get one step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "step ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"405":
|
|
||||||
description: invalid HTTP Met
|
|
||||||
"""
|
|
||||||
return await super().http_get_one(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/", method="POST", auth_required=False)
|
|
||||||
async def http_add(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Get one step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Created an step
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_add(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
|
||||||
async def http_update(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Update an step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "step ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Update an step
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
config:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_update(request)
|
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
|
||||||
async def http_delete_one(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Delete a step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
parameters:
|
|
||||||
- name: "id"
|
|
||||||
in: "path"
|
|
||||||
description: "Step ID"
|
|
||||||
required: true
|
|
||||||
type: "integer"
|
|
||||||
format: "int64"
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
return await super().http_delete_one(request)
|
|
||||||
|
|
||||||
|
|
||||||
@request_mapping(path="/action", auth_required=False)
|
|
||||||
async def http_action(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Call step action
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
await self.cbpi.bus.fire("step/action", action="test")
|
|
||||||
return web.Response(text="OK")
|
|
||||||
|
|
||||||
@request_mapping(path="/start", auth_required=False)
|
|
||||||
async def http_start(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Start Brewing Process
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
if self.is_running():
|
|
||||||
raise CBPiException("Brewing Process Already Running")
|
|
||||||
result = await self.cbpi.bus.fire("step/start")
|
|
||||||
r = result.get("core.controller.step_controller.handle_start")
|
|
||||||
if r[0] is True:
|
|
||||||
return web.Response(status=204)
|
|
||||||
else:
|
|
||||||
raise CBPiException("Failed to start brewing process")
|
|
||||||
|
|
||||||
|
|
||||||
@request_mapping(path="/reset", auth_required=False)
|
|
||||||
async def http_reset(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Reset Brewing Process
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
await self.cbpi.bus.fire("step/reset")
|
|
||||||
return web.Response(text="OK")
|
|
||||||
|
|
||||||
@request_mapping(path="/next", auth_required=False)
|
|
||||||
async def http_next(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Start next step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
await self.cbpi.bus.fire("step/next")
|
|
||||||
return web.Response(text="OK")
|
|
||||||
|
|
||||||
@request_mapping(path="/stop", auth_required=False)
|
|
||||||
async def http_stop(self, request):
|
|
||||||
"""
|
|
||||||
---
|
|
||||||
description: Stop next step
|
|
||||||
tags:
|
|
||||||
- Step
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: successful operation
|
|
||||||
"""
|
|
||||||
await self.cbpi.bus.fire("step/stop")
|
|
||||||
return web.Response(text="OK")
|
|
||||||
|
|
||||||
class StepController(StepHttpAPI, CRUDController):
|
|
||||||
'''
|
'''
|
||||||
The Step Controller. This controller is responsible to start and stop the brewing steps.
|
The Step Controller. This controller is responsible to start and stop the brewing steps.
|
||||||
|
|
||||||
|
@ -243,7 +23,7 @@ class StepController(StepHttpAPI, CRUDController):
|
||||||
self.types = {}
|
self.types = {}
|
||||||
self.current_step = None
|
self.current_step = None
|
||||||
self.current_job = None
|
self.current_job = None
|
||||||
self.cbpi.register(self, "/step")
|
self.cbpi.register(self)
|
||||||
|
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
|
|
|
@ -28,11 +28,9 @@ class SystemController():
|
||||||
result = []
|
result = []
|
||||||
for j in scheduler:
|
for j in scheduler:
|
||||||
try:
|
try:
|
||||||
|
|
||||||
result.append(dict(name=j.name, type=j.type, time=j.start_time))
|
result.append(dict(name=j.name, type=j.type, time=j.start_time))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
# await j.close()
|
|
||||||
return web.json_response(data=result)
|
return web.json_response(data=result)
|
||||||
|
|
||||||
@request_mapping("/events", method="GET", name="get_all_events", auth_required=False)
|
@request_mapping("/events", method="GET", name="get_all_events", auth_required=False)
|
||||||
|
|
|
@ -8,9 +8,10 @@ from aiohttp_session import session_middleware
|
||||||
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
||||||
from aiohttp_swagger import setup_swagger
|
from aiohttp_swagger import setup_swagger
|
||||||
from cbpi_api.exceptions import CBPiException
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
from voluptuous import MultipleInvalid
|
||||||
|
|
||||||
|
from controller.dashboard_controller import DashboardController
|
||||||
from controller.job_controller import JobController
|
from controller.job_controller import JobController
|
||||||
from core.websocket import CBPiWebSocket
|
|
||||||
from core.controller.actor_controller import ActorController
|
from core.controller.actor_controller import ActorController
|
||||||
from core.controller.config_controller import ConfigController
|
from core.controller.config_controller import ConfigController
|
||||||
from core.controller.kettle_controller import KettleController
|
from core.controller.kettle_controller import KettleController
|
||||||
|
@ -23,6 +24,13 @@ from core.database.model import DBModel
|
||||||
from core.eventbus import CBPiEventBus
|
from core.eventbus import CBPiEventBus
|
||||||
from core.http_endpoints.http_login import Login
|
from core.http_endpoints.http_login import Login
|
||||||
from core.utils import *
|
from core.utils import *
|
||||||
|
from core.websocket import CBPiWebSocket
|
||||||
|
from http_endpoints.http_actor import ActorHttpEndpoints
|
||||||
|
from http_endpoints.http_config import ConfigHttpEndpoints
|
||||||
|
from http_endpoints.http_dashboard import DashBoardHttpEndpoints
|
||||||
|
from http_endpoints.http_kettle import KettleHttpEndpoints
|
||||||
|
from http_endpoints.http_sensor import SensorHttpEndpoints
|
||||||
|
from http_endpoints.http_step import StepHttpEndpoints
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
@ -43,6 +51,8 @@ async def error_middleware(request, handler):
|
||||||
except CBPiException as ex:
|
except CBPiException as ex:
|
||||||
message = str(ex)
|
message = str(ex)
|
||||||
return web.json_response(status=500, data={'error': message})
|
return web.json_response(status=500, data={'error': message})
|
||||||
|
except MultipleInvalid as ex:
|
||||||
|
return web.json_response(status=500, data={'error': str(ex)})
|
||||||
return web.json_response({'error': message})
|
return web.json_response({'error': message})
|
||||||
|
|
||||||
class CraftBeerPi():
|
class CraftBeerPi():
|
||||||
|
@ -69,6 +79,15 @@ class CraftBeerPi():
|
||||||
self.config = ConfigController(self)
|
self.config = ConfigController(self)
|
||||||
self.kettle = KettleController(self)
|
self.kettle = KettleController(self)
|
||||||
self.step = StepController(self)
|
self.step = StepController(self)
|
||||||
|
self.dashboard = DashboardController(self)
|
||||||
|
|
||||||
|
self.http_step = StepHttpEndpoints(self)
|
||||||
|
self.http_sensor = SensorHttpEndpoints(self)
|
||||||
|
self.http_config = ConfigHttpEndpoints(self)
|
||||||
|
self.http_actor = ActorHttpEndpoints(self)
|
||||||
|
self.http_kettle = KettleHttpEndpoints(self)
|
||||||
|
self.http_dashboard = DashBoardHttpEndpoints(self)
|
||||||
|
|
||||||
self.notification = NotificationController(self)
|
self.notification = NotificationController(self)
|
||||||
self.login = Login(self)
|
self.login = Login(self)
|
||||||
|
|
||||||
|
@ -104,6 +123,10 @@ class CraftBeerPi():
|
||||||
|
|
||||||
def register_http_endpoints(self, obj, url_prefix=None, static=None):
|
def register_http_endpoints(self, obj, url_prefix=None, static=None):
|
||||||
|
|
||||||
|
if url_prefix is None:
|
||||||
|
logger.debug("URL Prefix is None for %s. No endpoints will be registered. Please set / explicit if you want to add it to the root path" % obj)
|
||||||
|
return
|
||||||
|
|
||||||
routes = []
|
routes = []
|
||||||
for method in [getattr(obj, f) for f in dir(obj) if callable(getattr(obj, f)) and hasattr(getattr(obj, f), "route")]:
|
for method in [getattr(obj, f) for f in dir(obj) if callable(getattr(obj, f)) and hasattr(getattr(obj, f), "route")]:
|
||||||
http_method = method.__getattribute__("method")
|
http_method = method.__getattribute__("method")
|
||||||
|
@ -131,7 +154,7 @@ class CraftBeerPi():
|
||||||
}
|
}
|
||||||
switcher[http_method]()
|
switcher[http_method]()
|
||||||
|
|
||||||
if url_prefix is not None:
|
if url_prefix != "/":
|
||||||
logger.debug("URL Prefix: %s " % (url_prefix,))
|
logger.debug("URL Prefix: %s " % (url_prefix,))
|
||||||
sub = web.Application()
|
sub = web.Application()
|
||||||
sub.add_routes(routes)
|
sub.add_routes(routes)
|
||||||
|
@ -206,6 +229,7 @@ class CraftBeerPi():
|
||||||
await self.actor.init()
|
await self.actor.init()
|
||||||
await self.kettle.init()
|
await self.kettle.init()
|
||||||
await self.call_initializer(self.app)
|
await self.call_initializer(self.app)
|
||||||
|
await self.dashboard.init()
|
||||||
self._swagger_setup()
|
self._swagger_setup()
|
||||||
|
|
||||||
return self.app
|
return self.app
|
||||||
|
|
|
@ -1,18 +1,38 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
from voluptuous import Schema, MultipleInvalid
|
||||||
|
|
||||||
from core.database.orm_framework import DBModel
|
from core.database.orm_framework import DBModel
|
||||||
|
|
||||||
DATABASE_FILE = "./craftbeerpi.db"
|
DATABASE_FILE = "./craftbeerpi.db"
|
||||||
|
|
||||||
|
|
||||||
class ActorModel(DBModel):
|
class ActorModel(DBModel):
|
||||||
__fields__ = ["name", "type", "config"]
|
__fields__ = ["name", "type", "config"]
|
||||||
__table_name__ = "actor"
|
__table_name__ = "actor"
|
||||||
__json_fields__ = ["config"]
|
__json_fields__ = ["config"]
|
||||||
|
|
||||||
|
__validation_schema__ = {
|
||||||
|
'id': int,
|
||||||
|
'name': str,
|
||||||
|
'type': str,
|
||||||
|
'config': dict
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class SensorModel(DBModel):
|
class SensorModel(DBModel):
|
||||||
__fields__ = ["name", "type", "config"]
|
__fields__ = ["name", "type", "config"]
|
||||||
__table_name__ = "sensor"
|
__table_name__ = "sensor"
|
||||||
__json_fields__ = ["config"]
|
__json_fields__ = ["config"]
|
||||||
|
__validation_schema__ = {
|
||||||
|
'id': int,
|
||||||
|
'name': str,
|
||||||
|
'type': str,
|
||||||
|
'config': dict
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfigModel(DBModel):
|
class ConfigModel(DBModel):
|
||||||
__fields__ = ["type", "value", "description", "options"]
|
__fields__ = ["type", "value", "description", "options"]
|
||||||
|
@ -20,6 +40,7 @@ class ConfigModel(DBModel):
|
||||||
__json_fields__ = ["options"]
|
__json_fields__ = ["options"]
|
||||||
__priamry_key__ = "name"
|
__priamry_key__ = "name"
|
||||||
|
|
||||||
|
|
||||||
class KettleModel(DBModel):
|
class KettleModel(DBModel):
|
||||||
__fields__ = ["name", "sensor", "heater", "automatic", "logic", "config", "agitator", "target_temp"]
|
__fields__ = ["name", "sensor", "heater", "automatic", "logic", "config", "agitator", "target_temp"]
|
||||||
__table_name__ = "kettle"
|
__table_name__ = "kettle"
|
||||||
|
@ -40,7 +61,6 @@ class StepModel(DBModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_by_state(cls, state, order=True):
|
async def get_by_state(cls, state, order=True):
|
||||||
|
|
||||||
|
|
||||||
async with aiosqlite.connect(DATABASE_FILE) as db:
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
db.row_factory = aiosqlite.Row
|
db.row_factory = aiosqlite.Row
|
||||||
db.row_factory = DBModel.dict_factory
|
db.row_factory = DBModel.dict_factory
|
||||||
|
@ -54,6 +74,50 @@ class StepModel(DBModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reset_all_steps(cls):
|
async def reset_all_steps(cls):
|
||||||
async with aiosqlite.connect(DATABASE_FILE) as db:
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
cursor = await db.execute("UPDATE %s SET state = 'I', stepstate = NULL , start = NULL, end = NULL " % cls.__table_name__)
|
await db.execute("UPDATE %s SET state = 'I', stepstate = NULL , start = NULL, end = NULL " % cls.__table_name__)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
|
class DashboardModel(DBModel):
|
||||||
|
__fields__ = ["name"]
|
||||||
|
__table_name__ = "dashboard"
|
||||||
|
__json_fields__ = []
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardContentModel(DBModel):
|
||||||
|
__fields__ = ["dbid", "type", "element_id", "x", "y","config"]
|
||||||
|
__table_name__ = "dashboard_content"
|
||||||
|
__json_fields__ = ["config"]
|
||||||
|
|
||||||
|
__validation_schema__ = {
|
||||||
|
'dbid': int,
|
||||||
|
'element_id': int,
|
||||||
|
'type': str,
|
||||||
|
'x': int,
|
||||||
|
'y': int,
|
||||||
|
'config': dict
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_by_dashboard_id(cls, id, as_array=False):
|
||||||
|
|
||||||
|
result = []
|
||||||
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
|
db.row_factory = DBModel.dict_factory
|
||||||
|
async with db.execute("SELECT * FROM %s WHERE dbid = ?" % (cls.__table_name__), (id,)) as cursor:
|
||||||
|
async for row in cursor:
|
||||||
|
result.append(cls(row))
|
||||||
|
await cursor.close()
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def update_coordinates(cls, id, x, y):
|
||||||
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
|
await db.execute("UPDATE %s SET x = ?, y = ? WHERE id = ?" % (cls.__table_name__), (x, y, id,))
|
||||||
|
await db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def delete_by_dashboard_id(cls, id):
|
||||||
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
|
await db.execute("DELETE FROM %s WHERE dbid = ?" % (cls.__table_name__), (id,))
|
||||||
|
await db.commit()
|
||||||
|
|
|
@ -2,6 +2,9 @@ import json
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
from voluptuous import MultipleInvalid, Schema
|
||||||
|
|
||||||
DATABASE_FILE = "./craftbeerpi.db"
|
DATABASE_FILE = "./craftbeerpi.db"
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +13,7 @@ class DBModel(object):
|
||||||
__as_array__ = False
|
__as_array__ = False
|
||||||
__order_by__ = None
|
__order_by__ = None
|
||||||
__json_fields__ = []
|
__json_fields__ = []
|
||||||
|
__validation_schema__ = None
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.__setattr__(self.__priamry_key__, args[self.__priamry_key__])
|
self.__setattr__(self.__priamry_key__, args[self.__priamry_key__])
|
||||||
|
@ -37,6 +41,15 @@ class DBModel(object):
|
||||||
qry = open(os.path.join(this_directory, '../../config/create_database.sql'), 'r').read()
|
qry = open(os.path.join(this_directory, '../../config/create_database.sql'), 'r').read()
|
||||||
cursor = await db.executescript(qry)
|
cursor = await db.executescript(qry)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, data):
|
||||||
|
if cls.__validation_schema__ is not None:
|
||||||
|
try:
|
||||||
|
schema = Schema(cls.__validation_schema__)
|
||||||
|
schema(data)
|
||||||
|
except MultipleInvalid as e:
|
||||||
|
raise CBPiException(str(e))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_all(cls):
|
async def get_all(cls):
|
||||||
|
|
||||||
|
@ -85,6 +98,9 @@ class DBModel(object):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def insert(cls, **kwargs):
|
async def insert(cls, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
|
cls.validate(kwargs)
|
||||||
|
|
||||||
async with aiosqlite.connect(DATABASE_FILE) as db:
|
async with aiosqlite.connect(DATABASE_FILE) as db:
|
||||||
if cls.__priamry_key__ is not None and cls.__priamry_key__ in kwargs:
|
if cls.__priamry_key__ is not None and cls.__priamry_key__ in kwargs:
|
||||||
query = "INSERT INTO %s (%s, %s) VALUES (?, %s)" % (
|
query = "INSERT INTO %s (%s, %s) VALUES (?, %s)" % (
|
||||||
|
|
|
@ -124,9 +124,7 @@ class CBPiEventBus(object):
|
||||||
|
|
||||||
if inspect.iscoroutinefunction(content_obj.method):
|
if inspect.iscoroutinefunction(content_obj.method):
|
||||||
if content_obj.supports_future is True:
|
if content_obj.supports_future is True:
|
||||||
|
|
||||||
fut = self.loop.create_future()
|
fut = self.loop.create_future()
|
||||||
|
|
||||||
futures["%s.%s" % (content_obj.method.__module__, content_obj.name)] = fut
|
futures["%s.%s" % (content_obj.method.__module__, content_obj.name)] = fut
|
||||||
self.loop.create_task(content_obj.method(**kwargs, topic = topic, future=fut))
|
self.loop.create_task(content_obj.method(**kwargs, topic = topic, future=fut))
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ class CustomActor(CBPiActor):
|
||||||
|
|
||||||
# Custom property which can be configured by the user
|
# Custom property which can be configured by the user
|
||||||
gpio = Property.Number(label="Test")
|
gpio = Property.Number(label="Test")
|
||||||
|
v1 = Property.Text(label="Test")
|
||||||
|
v2 = Property.Kettle(label="Test")
|
||||||
|
v3 = Property.Sensor(label="Test")
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
pass
|
pass
|
||||||
|
|
234
core/http_endpoints/http_actor.py
Normal file
234
core/http_endpoints/http_actor.py
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
auth = False
|
||||||
|
|
||||||
|
class ActorHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super().__init__(cbpi)
|
||||||
|
self.controller = cbpi.actor
|
||||||
|
self.cbpi.register(self, "/actor")
|
||||||
|
|
||||||
|
@request_mapping(path="/types", auth_required=False)
|
||||||
|
async def get_types(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get all actor types
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().get_types(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", auth_required=False)
|
||||||
|
async def http_get_all(self, request):
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Switch actor on
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
return await super().http_get_all(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", auth_required=False)
|
||||||
|
async def http_get_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one Actor
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
return await super().http_get_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", method="POST", auth_required=False)
|
||||||
|
async def http_add(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one Actor
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Created an actor
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
|
||||||
|
return await super().http_add(request)
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
||||||
|
async def http_update(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Update an actor
|
||||||
|
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
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_update(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
||||||
|
async def http_delete_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Delete an actor
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_delete_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/on", method="POST", auth_required=auth)
|
||||||
|
async def http_on(self, request) -> web.Response:
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Switch actor on
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
actor_id = int(request.match_info['id'])
|
||||||
|
result = await self.cbpi.bus.fire(topic="actor/%s/switch/on" % actor_id, actor_id=actor_id, power=99)
|
||||||
|
for key, value in result.results.items():
|
||||||
|
pass
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/off", method="POST", auth_required=auth)
|
||||||
|
async def http_off(self, request) -> web.Response:
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Switch actor off
|
||||||
|
tags:
|
||||||
|
- Actor
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
actor_id = int(request.match_info['id'])
|
||||||
|
await self.cbpi.bus.fire(topic="actor/%s/off" % actor_id, actor_id=actor_id)
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/toggle", method="POST", auth_required=auth)
|
||||||
|
async def http_toggle(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"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
actor_id = int(request.match_info['id'])
|
||||||
|
|
||||||
|
await self.cbpi.bus.fire(topic="actor/%s/toggle" % actor_id, actor_id=actor_id)
|
||||||
|
return web.Response(status=204)
|
72
core/http_endpoints/http_config.py
Normal file
72
core/http_endpoints/http_config.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
from utils import json_dumps
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super().__init__(cbpi)
|
||||||
|
self.controller = cbpi.config
|
||||||
|
self.cbpi.register(self, "/config")
|
||||||
|
|
||||||
|
@request_mapping(path="/{name}/", method="POST", auth_required=False)
|
||||||
|
async def http_post(self, request) -> web.Response:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Set config parameter
|
||||||
|
tags:
|
||||||
|
- Config
|
||||||
|
parameters:
|
||||||
|
- name: "name"
|
||||||
|
in: "path"
|
||||||
|
description: "Parameter name"
|
||||||
|
required: true
|
||||||
|
type: "string"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
name = request.match_info['name']
|
||||||
|
data = await request.json()
|
||||||
|
await self.controller.set(name=name, value=data.get("value"))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/", auth_required=False)
|
||||||
|
async def http_get_all(self, request) -> web.Response:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get all config parameters
|
||||||
|
tags:
|
||||||
|
- Config
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return web.json_response(self.controller.cache, dumps=json_dumps)
|
||||||
|
|
||||||
|
@request_mapping(path="/{name}/", auth_required=False)
|
||||||
|
async def http_paramter(self, request) -> web.Response:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get all config parameters
|
||||||
|
tags:
|
||||||
|
- Config
|
||||||
|
parameters:
|
||||||
|
- name: "name"
|
||||||
|
in: "path"
|
||||||
|
description: "Parameter name"
|
||||||
|
required: true
|
||||||
|
type: "string"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
name = request.match_info['name']
|
||||||
|
if name not in self.cache:
|
||||||
|
raise CBPiException("Parameter %s not found" % name)
|
||||||
|
|
||||||
|
return web.json_response(self.cache.get(name), dumps=json_dumps)
|
|
@ -1,45 +1,51 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp_swagger import swagger_path
|
|
||||||
from cbpi_api import *
|
from cbpi_api import *
|
||||||
|
|
||||||
from core.utils.utils import json_dumps
|
from core.utils.utils import json_dumps
|
||||||
|
|
||||||
class HttpAPI():
|
|
||||||
|
class HttpCrudEndpoints():
|
||||||
|
|
||||||
def __init__(self, cbpi):
|
def __init__(self, cbpi):
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
|
|
||||||
|
|
||||||
@request_mapping(path="/types", auth_required=False)
|
@request_mapping(path="/types", auth_required=False)
|
||||||
async def get_types(self, request):
|
async def get_types(self, request):
|
||||||
if self.types is not None:
|
if self.controller.types is not None:
|
||||||
return web.json_response(data=self.types, dumps=json_dumps)
|
return web.json_response(data=self.controller.types, dumps=json_dumps)
|
||||||
else:
|
else:
|
||||||
return web.Response(status=404, text="Types not supported by endpoint")
|
return web.Response(status=404, text="Types not supported by endpoint")
|
||||||
|
|
||||||
@request_mapping(path="/", auth_required=False)
|
@request_mapping(path="/", auth_required=False)
|
||||||
async def http_get_all(self, request):
|
async def http_get_all(self, request):
|
||||||
return web.json_response(await self.get_all(force_db_update=True), dumps=json_dumps)
|
return web.json_response(await self.controller.get_all(force_db_update=True), dumps=json_dumps)
|
||||||
|
|
||||||
@request_mapping(path="/{id:\d+}", auth_required=False)
|
@request_mapping(path="/{id:\d+}", auth_required=False)
|
||||||
async def http_get_one(self, request):
|
async def http_get_one(self, request):
|
||||||
id = int(request.match_info['id'])
|
id = int(request.match_info['id'])
|
||||||
return web.json_response(await self.get_one(id), dumps=json_dumps)
|
return web.json_response(await self.controller.get_one(id), dumps=json_dumps)
|
||||||
|
|
||||||
@request_mapping(path="/", method="POST", auth_required=False)
|
@request_mapping(path="/", method="POST", auth_required=False)
|
||||||
async def http_add(self, request):
|
async def http_add(self, request):
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
obj = await self.add(**data)
|
print(data)
|
||||||
|
|
||||||
|
obj = await self.controller.add(**data)
|
||||||
return web.json_response(obj, dumps=json_dumps)
|
return web.json_response(obj, dumps=json_dumps)
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
||||||
async def http_update(self, request):
|
async def http_update(self, request):
|
||||||
id = request.match_info['id']
|
id = request.match_info['id']
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
obj = await self.update(id, data)
|
obj = await self.controller.update(id, data)
|
||||||
return web.json_response(obj, dumps=json_dumps)
|
return web.json_response(obj, dumps=json_dumps)
|
||||||
|
|
||||||
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
||||||
async def http_delete_one(self, request):
|
async def http_delete_one(self, request):
|
||||||
id = request.match_info['id']
|
id = request.match_info['id']
|
||||||
await self.delete(int(id))
|
await self.controller.delete(int(id))
|
||||||
return web.Response(status=204)
|
return web.Response(status=204)
|
260
core/http_endpoints/http_dashboard.py
Normal file
260
core/http_endpoints/http_dashboard.py
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
from voluptuous import Schema
|
||||||
|
|
||||||
|
from database.model import DashboardContentModel
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
from utils import json_dumps
|
||||||
|
|
||||||
|
|
||||||
|
class DashBoardHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
self.cbpi = cbpi
|
||||||
|
self.controller = cbpi.dashboard
|
||||||
|
self.cbpi.register(self, "/dashboard")
|
||||||
|
|
||||||
|
@request_mapping(path="/", auth_required=False)
|
||||||
|
async def http_get_all(self, request):
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Get all dashboards
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_get_all(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", auth_required=False)
|
||||||
|
async def http_get_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one Dashboard by id
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Actor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_get_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", method="POST", auth_required=False)
|
||||||
|
async def http_add(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Create a new Dashboard
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Create a new Dashboard
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
|
||||||
|
return await super().http_add(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", method="PUT", auth_required=False)
|
||||||
|
async def http_update(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Update a Dashboard
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Update a dashboard
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_update(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", method="DELETE", auth_required=False)
|
||||||
|
async def http_delete_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Delete a Dashboard
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_delete_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/content", auth_required=False)
|
||||||
|
async def get_content(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get Dashboard Content
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
dashboard_id = int(request.match_info['id'])
|
||||||
|
return web.json_response(await self.cbpi.dashboard.get_content(dashboard_id), dumps=json_dumps)
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/content", method="POST", auth_required=False)
|
||||||
|
async def add_content(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Add Dashboard Content
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- name: body
|
||||||
|
in: body
|
||||||
|
description: Dashboard Content
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
element_id:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
x:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
y:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
data = await request.json()
|
||||||
|
return web.json_response(await self.cbpi.dashboard.add_content(data), dumps=json_dumps)
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/content/{content_id:\d+}", method="DELETE", auth_required=False)
|
||||||
|
async def delete_content(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Delete Dashboard Content
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- name: "content_id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard Content ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
content_id = int(request.match_info['content_id'])
|
||||||
|
|
||||||
|
await self.cbpi.dashboard.delete_content(content_id)
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/content/{content_id:\d+}/move", method="PUT", auth_required=False)
|
||||||
|
async def move_content(self,request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get Dashboard Content
|
||||||
|
tags:
|
||||||
|
- Dashboard
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Dashboard ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- name: "content_id"
|
||||||
|
in: "path"
|
||||||
|
description: "Content ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- name: body
|
||||||
|
in: body
|
||||||
|
description: Dashboard Content
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
x:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
y:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
data = await request.json()
|
||||||
|
schema = Schema({"x": int, "y": int})
|
||||||
|
schema(data)
|
||||||
|
content_id = int(request.match_info['content_id'])
|
||||||
|
return web.json_response(await self.cbpi.dashboard.move_content(content_id,data["x"], data["y"]), dumps=json_dumps)
|
||||||
|
|
52
core/http_endpoints/http_kettle.py
Normal file
52
core/http_endpoints/http_kettle.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
|
||||||
|
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
auth = False
|
||||||
|
|
||||||
|
|
||||||
|
class KettleHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super().__init__(cbpi)
|
||||||
|
self.controller = cbpi.kettle
|
||||||
|
self.cbpi.register(self, "/kettle")
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/automatic", auth_required=False)
|
||||||
|
async def http_automatic(self, request):
|
||||||
|
await self.controller.toggle_automtic(int(request.match_info['id']))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/heater/on", auth_required=False)
|
||||||
|
async def http_heater_on(self, request):
|
||||||
|
await self.controller.heater_on(int(request.match_info['id']))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/heater/off", auth_required=False)
|
||||||
|
async def http_heater_off(self, request):
|
||||||
|
await self.controller.heater_off(int(request.match_info['id']))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/agitator/on", auth_required=False)
|
||||||
|
async def http_agitator_on(self, request):
|
||||||
|
await self.controller.agitator_on(int(request.match_info['id']))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/agitator/off", auth_required=False)
|
||||||
|
async def http_agitator_off(self, request):
|
||||||
|
await self.controller.agitator_off(int(request.match_info['id']))
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/targettemp", auth_required=False)
|
||||||
|
async def http_taget_temp(self, request):
|
||||||
|
kettle_id = int(request.match_info['id'])
|
||||||
|
temp = await self.controller.get_traget_temp(kettle_id)
|
||||||
|
return web.json_response(data=dict(target_temp=temp, kettle_id=kettle_id))
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}/temp", auth_required=False)
|
||||||
|
async def http_temp(self, request):
|
||||||
|
kettle_id = int(request.match_info['id'])
|
||||||
|
temp = await self.controller.get_temp(kettle_id)
|
||||||
|
return web.json_response(data=dict(temp=temp, kettle_id=kettle_id))
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Login():
|
||||||
|
|
||||||
def __init__(self,cbpi):
|
def __init__(self,cbpi):
|
||||||
self.cbpi = cbpi
|
self.cbpi = cbpi
|
||||||
self.cbpi.register(self)
|
self.cbpi.register(self, url_prefix="/")
|
||||||
|
|
||||||
self.db = {cbpi.static_config.get("username", "cbpi"): cbpi.static_config.get("password", "cbpi")}
|
self.db = {cbpi.static_config.get("username", "cbpi"): cbpi.static_config.get("password", "cbpi")}
|
||||||
|
|
||||||
|
@ -23,11 +23,8 @@ class Login():
|
||||||
params = await request.post()
|
params = await request.post()
|
||||||
|
|
||||||
user = params.get('username', None)
|
user = params.get('username', None)
|
||||||
password = params.get('password', None)
|
|
||||||
print("UUSEr", user, password, str(self.db[user]))
|
|
||||||
if (user in self.db and
|
|
||||||
params.get('password', None) == str(self.db[user])):
|
|
||||||
|
|
||||||
|
if (user in self.db and params.get('password', None) == str(self.db[user])):
|
||||||
# User is in our database, remember their login details
|
# User is in our database, remember their login details
|
||||||
await auth.remember(request, user)
|
await auth.remember(request, user)
|
||||||
return web.Response(body='OK'.encode('utf-8'))
|
return web.Response(body='OK'.encode('utf-8'))
|
||||||
|
|
142
core/http_endpoints/http_sensor.py
Normal file
142
core/http_endpoints/http_sensor.py
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
|
||||||
|
|
||||||
|
class SensorHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super().__init__(cbpi)
|
||||||
|
self.controller = cbpi.sensor
|
||||||
|
self.cbpi.register(self, "/sensor")
|
||||||
|
|
||||||
|
@request_mapping(path="/types", auth_required=False)
|
||||||
|
async def get_types(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get all sensor types
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().get_types(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", auth_required=False)
|
||||||
|
async def http_get_all(self, request):
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Get all sensor
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_get_all(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", auth_required=False)
|
||||||
|
async def http_get_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get an sensor
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Sensor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
return await super().http_get_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", method="POST", auth_required=False)
|
||||||
|
async def http_add(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one sensor
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Created an sensor
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_add(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
||||||
|
async def http_update(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Update an sensor
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Sensor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Update an sensor
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_update(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
||||||
|
async def http_delete_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Delete an sensor
|
||||||
|
tags:
|
||||||
|
- Sensor
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Sensor ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_delete_one(request)
|
228
core/http_endpoints/http_step.py
Normal file
228
core/http_endpoints/http_step.py
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
from aiohttp import web
|
||||||
|
from cbpi_api import request_mapping
|
||||||
|
from cbpi_api.exceptions import CBPiException
|
||||||
|
|
||||||
|
from http_endpoints.http_curd_endpoints import HttpCrudEndpoints
|
||||||
|
|
||||||
|
|
||||||
|
class StepHttpEndpoints(HttpCrudEndpoints):
|
||||||
|
|
||||||
|
def __init__(self, cbpi):
|
||||||
|
super().__init__(cbpi)
|
||||||
|
self.controller = cbpi.step
|
||||||
|
self.cbpi.register(self, "/step")
|
||||||
|
|
||||||
|
|
||||||
|
@request_mapping(path="/types", auth_required=False)
|
||||||
|
async def get_types(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get all step types
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().get_types(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", auth_required=False)
|
||||||
|
async def http_get_all(self, request):
|
||||||
|
"""
|
||||||
|
|
||||||
|
---
|
||||||
|
description: Switch step on
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "step ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
return await super().http_get_all(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id:\d+}", auth_required=False)
|
||||||
|
async def http_get_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "step ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"405":
|
||||||
|
description: invalid HTTP Met
|
||||||
|
"""
|
||||||
|
return await super().http_get_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/", method="POST", auth_required=False)
|
||||||
|
async def http_add(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Get one step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Created an step
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_add(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="PUT", auth_required=False)
|
||||||
|
async def http_update(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Update an step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "step ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: Update an step
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
config:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_update(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/{id}", method="DELETE", auth_required=False)
|
||||||
|
async def http_delete_one(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Delete a step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
parameters:
|
||||||
|
- name: "id"
|
||||||
|
in: "path"
|
||||||
|
description: "Step ID"
|
||||||
|
required: true
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
return await super().http_delete_one(request)
|
||||||
|
|
||||||
|
@request_mapping(path="/action", auth_required=False)
|
||||||
|
async def http_action(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Call step action
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
await self.cbpi.bus.fire("step/action", action="test")
|
||||||
|
return web.Response(text="OK")
|
||||||
|
|
||||||
|
@request_mapping(path="/start", auth_required=False)
|
||||||
|
async def http_start(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Start Brewing Process
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
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")
|
||||||
|
|
||||||
|
@request_mapping(path="/reset", auth_required=False)
|
||||||
|
async def http_reset(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Reset Brewing Process
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
await self.cbpi.bus.fire("step/reset")
|
||||||
|
return web.Response(text="OK")
|
||||||
|
|
||||||
|
@request_mapping(path="/next", auth_required=False)
|
||||||
|
async def http_next(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Start next step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
await self.cbpi.bus.fire("step/next")
|
||||||
|
return web.Response(status=204)
|
||||||
|
|
||||||
|
@request_mapping(path="/stop", auth_required=False)
|
||||||
|
async def http_stop(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Stop next step
|
||||||
|
tags:
|
||||||
|
- Step
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
await self.cbpi.bus.fire("step/stop")
|
||||||
|
return web.Response(status=204)
|
|
@ -1,39 +0,0 @@
|
||||||
tags:
|
|
||||||
- user
|
|
||||||
summary: Create user111
|
|
||||||
description: This can only be done by the logged in user.
|
|
||||||
operationId: examples.api.api.createUser
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
description: Created user object
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
username:
|
|
||||||
type:
|
|
||||||
- "string"
|
|
||||||
- "null"
|
|
||||||
firstName:
|
|
||||||
type: string
|
|
||||||
lastName:
|
|
||||||
type: string
|
|
||||||
email:
|
|
||||||
type: string
|
|
||||||
password:
|
|
||||||
type: string
|
|
||||||
phone:
|
|
||||||
type: string
|
|
||||||
userStatus:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
description: User Status
|
|
||||||
responses:
|
|
||||||
"201":
|
|
||||||
description: successful operation
|
|
|
@ -1,7 +1,5 @@
|
||||||
from json import JSONEncoder
|
from json import JSONEncoder
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ComplexEncoder(JSONEncoder):
|
class ComplexEncoder(JSONEncoder):
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,10 +14,10 @@ class ComplexEncoder(JSONEncoder):
|
||||||
# return obj.reprJSON()
|
# return obj.reprJSON()
|
||||||
#elif isinstance(obj, ActorModel):
|
#elif isinstance(obj, ActorModel):
|
||||||
# return None
|
# return None
|
||||||
elif hasattr(obj, "callback"):
|
#elif hasattr(obj, "callback"):
|
||||||
return obj()
|
# return obj()
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
except TypeError as e:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1,72 +1,18 @@
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
from cbpi_api import *
|
|
||||||
from core.utils.encoder import ComplexEncoder
|
from core.utils.encoder import ComplexEncoder
|
||||||
|
|
||||||
__all__ = ['load_config',"json_dumps", "parse_props"]
|
__all__ = ['load_config',"json_dumps"]
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from json import JSONEncoder
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from core.database.model import DBModel, ActorModel
|
|
||||||
|
|
||||||
|
|
||||||
def load_config(fname):
|
def load_config(fname):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
with open(fname, 'rt') as f:
|
with open(fname, 'rt') as f:
|
||||||
data = yaml.load(f)
|
data = yaml.load(f)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def json_dumps(obj):
|
def json_dumps(obj):
|
||||||
return json.dumps(obj, cls=ComplexEncoder)
|
return json.dumps(obj, cls=ComplexEncoder)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse_props(self, cls):
|
|
||||||
name = cls.__name__
|
|
||||||
result = {"name": name, "class": cls, "properties": [], "actions": []}
|
|
||||||
tmpObj = cls()
|
|
||||||
members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")]
|
|
||||||
for m in members:
|
|
||||||
if isinstance(tmpObj.__getattribute__(m), Property.Number):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append(
|
|
||||||
{"name": m, "label": t.label, "type": "number", "configurable": t.configurable, "description": t.description, "default_value": t.default_value})
|
|
||||||
elif isinstance(tmpObj.__getattribute__(m), Property.Text):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append(
|
|
||||||
{"name": m, "label": t.label, "type": "text", "configurable": t.configurable, "default_value": t.default_value, "description": t.description})
|
|
||||||
elif isinstance(tmpObj.__getattribute__(m), Property.Select):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append(
|
|
||||||
{"name": m, "label": t.label, "type": "select", "configurable": True, "options": t.options, "description": t.description})
|
|
||||||
elif isinstance(tmpObj.__getattribute__(m), Property.Actor):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append({"name": m, "label": t.label, "type": "actor", "configurable": t.configurable, "description": t.description})
|
|
||||||
elif isinstance(tmpObj.__getattribute__(m), Property.Sensor):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append({"name": m, "label": t.label, "type": "sensor", "configurable": t.configurable, "description": t.description})
|
|
||||||
elif isinstance(tmpObj.__getattribute__(m), Property.Kettle):
|
|
||||||
t = tmpObj.__getattribute__(m)
|
|
||||||
result["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable, "description": t.description})
|
|
||||||
for method_name, method in cls.__dict__.items():
|
|
||||||
if hasattr(method, "action"):
|
|
||||||
key = method.__getattribute__("key")
|
|
||||||
parameters = method.__getattribute__("parameters")
|
|
||||||
result["actions"].append({"method": method_name, "label": key, "parameters": parameters})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ class CBPiWebSocket:
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
|
|
||||||
for ws in self._clients:
|
for ws in self._clients:
|
||||||
|
|
||||||
async def send_data(ws, data):
|
async def send_data(ws, data):
|
||||||
await ws.send_str(data)
|
await ws.send_str(data)
|
||||||
self.cbpi.app.loop.create_task(send_data(ws, data))
|
self.cbpi.app.loop.create_task(send_data(ws, data))
|
||||||
|
|
BIN
craftbeerpi.db
BIN
craftbeerpi.db
Binary file not shown.
|
@ -162,7 +162,7 @@
|
||||||
<dl class="class">
|
<dl class="class">
|
||||||
<dt id="core.controller.sensor_controller.SensorController">
|
<dt id="core.controller.sensor_controller.SensorController">
|
||||||
<em class="property">class </em><code class="descclassname">core.controller.sensor_controller.</code><code class="descname">SensorController</code><span class="sig-paren">(</span><em>cbpi</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.sensor_controller.SensorController" title="Permalink to this definition">¶</a></dt>
|
<em class="property">class </em><code class="descclassname">core.controller.sensor_controller.</code><code class="descname">SensorController</code><span class="sig-paren">(</span><em>cbpi</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.sensor_controller.SensorController" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">core.controller.crud_controller.CRUDController</span></code>, <code class="xref py py-class docutils literal notranslate"><span class="pre">core.http_endpoints.http_api.HttpAPI</span></code></p>
|
<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">core.controller.crud_controller.CRUDController</span></code>, <code class="xref py py-class docutils literal notranslate"><span class="pre">core.http_endpoints.http_api.HttpCrudEndpoints</span></code></p>
|
||||||
<dl class="method">
|
<dl class="method">
|
||||||
<dt id="core.controller.sensor_controller.SensorController.get_value">
|
<dt id="core.controller.sensor_controller.SensorController.get_value">
|
||||||
<code class="descname">get_value</code><span class="sig-paren">(</span><em>id</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.sensor_controller.SensorController.get_value" title="Permalink to this definition">¶</a></dt>
|
<code class="descname">get_value</code><span class="sig-paren">(</span><em>id</em><span class="sig-paren">)</span><a class="headerlink" href="#core.controller.sensor_controller.SensorController.get_value" title="Permalink to this definition">¶</a></dt>
|
||||||
|
|
|
@ -1,49 +1,24 @@
|
||||||
2019-01-02 00:44:06,10
|
2019-01-02 20:34:10,10
|
||||||
2019-01-02 00:44:11,10
|
2019-01-02 20:34:15,10
|
||||||
2019-01-02 00:44:16,10
|
2019-01-02 20:34:20,10
|
||||||
2019-01-02 00:44:21,10
|
2019-01-02 20:34:25,10
|
||||||
2019-01-02 00:44:26,10
|
2019-01-02 20:34:32,10
|
||||||
2019-01-02 00:44:31,10
|
2019-01-02 20:34:37,10
|
||||||
2019-01-02 00:44:36,10
|
2019-01-02 20:34:42,10
|
||||||
2019-01-02 00:44:41,10
|
2019-01-02 20:34:47,10
|
||||||
2019-01-02 00:44:46,10
|
2019-01-02 20:34:52,10
|
||||||
2019-01-02 00:44:51,10
|
2019-01-02 20:34:57,10
|
||||||
2019-01-02 00:44:56,10
|
2019-01-02 20:35:02,10
|
||||||
2019-01-02 00:45:01,10
|
2019-01-02 20:35:07,10
|
||||||
2019-01-02 00:45:06,10
|
2019-01-02 20:35:12,10
|
||||||
2019-01-02 00:45:11,10
|
2019-01-02 20:35:17,10
|
||||||
2019-01-02 00:45:16,10
|
2019-01-02 20:35:22,10
|
||||||
2019-01-02 00:45:21,10
|
2019-01-02 20:35:30,10
|
||||||
2019-01-02 00:45:26,10
|
2019-01-02 20:35:35,10
|
||||||
2019-01-02 00:45:31,10
|
2019-01-02 20:35:40,10
|
||||||
2019-01-02 00:45:36,10
|
2019-01-02 20:35:45,10
|
||||||
2019-01-02 00:45:41,10
|
2019-01-02 20:35:50,10
|
||||||
2019-01-02 00:45:46,10
|
2019-01-02 20:35:55,10
|
||||||
2019-01-02 00:45:51,10
|
2019-01-02 20:36:00,10
|
||||||
2019-01-02 00:45:56,10
|
2019-01-02 20:36:05,10
|
||||||
2019-01-02 00:46:01,10
|
2019-01-02 20:36:10,10
|
||||||
2019-01-02 00:46:06,10
|
|
||||||
2019-01-02 00:46:11,10
|
|
||||||
2019-01-02 00:46:16,10
|
|
||||||
2019-01-02 00:46:21,10
|
|
||||||
2019-01-02 00:46:26,10
|
|
||||||
2019-01-02 00:46:31,10
|
|
||||||
2019-01-02 00:46:36,10
|
|
||||||
2019-01-02 00:46:41,10
|
|
||||||
2019-01-02 00:46:46,10
|
|
||||||
2019-01-02 00:46:51,10
|
|
||||||
2019-01-02 00:46:56,10
|
|
||||||
2019-01-02 00:47:01,10
|
|
||||||
2019-01-02 00:47:06,10
|
|
||||||
2019-01-02 00:47:11,10
|
|
||||||
2019-01-02 00:47:16,10
|
|
||||||
2019-01-02 00:47:21,10
|
|
||||||
2019-01-02 00:47:26,10
|
|
||||||
2019-01-02 00:47:31,10
|
|
||||||
2019-01-02 00:47:36,10
|
|
||||||
2019-01-02 00:47:41,10
|
|
||||||
2019-01-02 00:47:46,10
|
|
||||||
2019-01-02 00:47:51,10
|
|
||||||
2019-01-02 00:47:56,10
|
|
||||||
2019-01-02 00:48:01,10
|
|
||||||
2019-01-02 00:48:06,10
|
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-02 00:36:56,10
|
2019-01-02 20:26:40,10
|
||||||
2019-01-02 00:37:01,10
|
2019-01-02 20:26:45,10
|
||||||
2019-01-02 00:37:06,10
|
2019-01-02 20:26:50,10
|
||||||
2019-01-02 00:37:11,10
|
2019-01-02 20:26:55,10
|
||||||
2019-01-02 00:37:16,10
|
2019-01-02 20:27:00,10
|
||||||
2019-01-02 00:37:21,10
|
2019-01-02 20:27:05,10
|
||||||
2019-01-02 00:37:26,10
|
2019-01-02 20:27:10,10
|
||||||
2019-01-02 00:37:31,10
|
2019-01-02 20:27:15,10
|
||||||
2019-01-02 00:37:36,10
|
2019-01-02 20:27:20,10
|
||||||
2019-01-02 00:37:41,10
|
2019-01-02 20:27:25,10
|
||||||
2019-01-02 00:37:46,10
|
2019-01-02 20:27:30,10
|
||||||
2019-01-02 00:37:51,10
|
2019-01-02 20:27:35,10
|
||||||
2019-01-02 00:37:56,10
|
2019-01-02 20:27:40,10
|
||||||
2019-01-02 00:38:01,10
|
2019-01-02 20:27:45,10
|
||||||
2019-01-02 00:38:06,10
|
2019-01-02 20:27:51,10
|
||||||
2019-01-02 00:38:11,10
|
2019-01-02 20:27:56,10
|
||||||
2019-01-02 00:38:16,10
|
2019-01-02 20:28:01,10
|
||||||
2019-01-02 00:38:21,10
|
2019-01-02 20:28:06,10
|
||||||
2019-01-02 00:38:26,10
|
2019-01-02 20:28:11,10
|
||||||
2019-01-02 00:38:31,10
|
2019-01-02 20:28:16,10
|
||||||
2019-01-02 00:38:36,10
|
2019-01-02 20:28:21,10
|
||||||
2019-01-02 00:38:41,10
|
2019-01-02 20:28:26,10
|
||||||
2019-01-02 00:38:46,10
|
2019-01-02 20:28:31,10
|
||||||
2019-01-02 00:38:51,10
|
2019-01-02 20:28:36,10
|
||||||
2019-01-02 00:38:56,10
|
2019-01-02 20:28:41,10
|
||||||
2019-01-02 00:39:01,10
|
2019-01-02 20:28:46,10
|
||||||
2019-01-02 00:39:06,10
|
2019-01-02 20:28:51,10
|
||||||
2019-01-02 00:39:11,10
|
2019-01-02 20:28:56,10
|
||||||
2019-01-02 00:39:16,10
|
2019-01-02 20:29:01,10
|
||||||
2019-01-02 00:39:21,10
|
2019-01-02 20:29:06,10
|
||||||
2019-01-02 00:39:26,10
|
2019-01-02 20:29:11,10
|
||||||
2019-01-02 00:39:31,10
|
2019-01-02 20:29:16,10
|
||||||
2019-01-02 00:39:36,10
|
2019-01-02 20:29:21,10
|
||||||
2019-01-02 00:39:41,10
|
2019-01-02 20:29:26,10
|
||||||
2019-01-02 00:39:46,10
|
2019-01-02 20:29:31,10
|
||||||
2019-01-02 00:39:51,10
|
2019-01-02 20:29:36,10
|
||||||
2019-01-02 00:39:56,10
|
2019-01-02 20:29:41,10
|
||||||
2019-01-02 00:40:01,10
|
2019-01-02 20:29:46,10
|
||||||
2019-01-02 00:40:06,10
|
2019-01-02 20:29:51,10
|
||||||
2019-01-02 00:40:11,10
|
2019-01-02 20:29:56,10
|
||||||
2019-01-02 00:40:16,10
|
2019-01-02 20:30:01,10
|
||||||
2019-01-02 00:40:21,10
|
2019-01-02 20:30:06,10
|
||||||
2019-01-02 00:40:26,10
|
2019-01-02 20:30:11,10
|
||||||
2019-01-02 00:40:31,10
|
2019-01-02 20:30:16,10
|
||||||
2019-01-02 00:40:36,10
|
2019-01-02 20:30:21,10
|
||||||
2019-01-02 00:40:41,10
|
2019-01-02 20:30:26,10
|
||||||
2019-01-02 00:40:46,10
|
2019-01-02 20:30:31,10
|
||||||
2019-01-02 00:40:51,10
|
2019-01-02 20:30:36,10
|
||||||
2019-01-02 00:40:56,10
|
2019-01-02 20:30:41,10
|
||||||
2019-01-02 00:41:01,10
|
2019-01-02 20:30:46,10
|
||||||
2019-01-02 00:41:06,10
|
2019-01-02 20:30:51,10
|
||||||
2019-01-02 00:41:11,10
|
2019-01-02 20:30:56,10
|
||||||
2019-01-02 00:41:16,10
|
2019-01-02 20:31:01,10
|
||||||
2019-01-02 00:41:21,10
|
2019-01-02 20:31:06,10
|
||||||
2019-01-02 00:41:26,10
|
2019-01-02 20:31:11,10
|
||||||
2019-01-02 00:41:31,10
|
2019-01-02 20:31:16,10
|
||||||
2019-01-02 00:41:36,10
|
2019-01-02 20:31:21,10
|
||||||
2019-01-02 00:41:41,10
|
2019-01-02 20:31:26,10
|
||||||
2019-01-02 00:41:46,10
|
2019-01-02 20:31:31,10
|
||||||
2019-01-02 00:41:51,10
|
2019-01-02 20:31:36,10
|
||||||
2019-01-02 00:41:56,10
|
2019-01-02 20:31:41,10
|
||||||
2019-01-02 00:42:01,10
|
2019-01-02 20:31:46,10
|
||||||
2019-01-02 00:42:06,10
|
2019-01-02 20:31:51,10
|
||||||
2019-01-02 00:42:11,10
|
2019-01-02 20:31:56,10
|
||||||
2019-01-02 00:42:16,10
|
2019-01-02 20:32:01,10
|
||||||
2019-01-02 00:42:21,10
|
2019-01-02 20:32:06,10
|
||||||
2019-01-02 00:42:26,10
|
2019-01-02 20:32:11,10
|
||||||
2019-01-02 00:42:31,10
|
2019-01-02 20:32:16,10
|
||||||
2019-01-02 00:42:36,10
|
2019-01-02 20:32:21,10
|
||||||
2019-01-02 00:42:41,10
|
2019-01-02 20:32:26,10
|
||||||
2019-01-02 00:42:46,10
|
2019-01-02 20:32:31,10
|
||||||
2019-01-02 00:42:51,10
|
2019-01-02 20:32:36,10
|
||||||
2019-01-02 00:42:56,10
|
2019-01-02 20:32:41,10
|
||||||
2019-01-02 00:43:01,10
|
2019-01-02 20:33:05,10
|
||||||
2019-01-02 00:43:06,10
|
2019-01-02 20:33:10,10
|
||||||
2019-01-02 00:43:11,10
|
2019-01-02 20:33:15,10
|
||||||
2019-01-02 00:43:16,10
|
2019-01-02 20:33:20,10
|
||||||
2019-01-02 00:43:21,10
|
2019-01-02 20:33:25,10
|
||||||
2019-01-02 00:43:26,10
|
2019-01-02 20:33:30,10
|
||||||
2019-01-02 00:43:31,10
|
2019-01-02 20:33:35,10
|
||||||
2019-01-02 00:43:36,10
|
2019-01-02 20:33:40,10
|
||||||
2019-01-02 00:43:41,10
|
2019-01-02 20:33:45,10
|
||||||
2019-01-02 00:43:46,10
|
2019-01-02 20:33:50,10
|
||||||
2019-01-02 00:43:51,10
|
2019-01-02 20:33:55,10
|
||||||
2019-01-02 00:43:56,10
|
2019-01-02 20:34:00,10
|
||||||
2019-01-02 00:44:01,10
|
2019-01-02 20:34:05,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-01 23:05:37,10
|
2019-01-02 18:48:13,10
|
||||||
2019-01-01 23:19:02,10
|
2019-01-02 18:48:18,10
|
||||||
2019-01-01 23:19:07,10
|
2019-01-02 18:48:23,10
|
||||||
2019-01-01 23:19:12,10
|
2019-01-02 18:48:28,10
|
||||||
2019-01-01 23:19:17,10
|
2019-01-02 18:48:33,10
|
||||||
2019-01-01 23:19:22,10
|
2019-01-02 18:48:38,10
|
||||||
2019-01-01 23:19:27,10
|
2019-01-02 18:48:43,10
|
||||||
2019-01-01 23:19:32,10
|
2019-01-02 18:48:48,10
|
||||||
2019-01-01 23:19:37,10
|
2019-01-02 18:48:53,10
|
||||||
2019-01-01 23:19:42,10
|
2019-01-02 18:48:58,10
|
||||||
2019-01-01 23:19:47,10
|
2019-01-02 18:49:03,10
|
||||||
2019-01-01 23:19:52,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:19:57,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:20:02,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:20:07,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:20:12,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:07,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:12,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:17,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:22,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:27,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:32,10
|
2019-01-02 18:49:07,10
|
||||||
2019-01-01 23:21:37,10
|
2019-01-02 18:49:08,10
|
||||||
2019-01-01 23:21:42,10
|
2019-01-02 18:49:13,10
|
||||||
2019-01-01 23:21:47,10
|
2019-01-02 18:49:18,10
|
||||||
2019-01-01 23:21:52,10
|
2019-01-02 18:49:23,10
|
||||||
2019-01-01 23:21:57,10
|
2019-01-02 18:49:28,10
|
||||||
2019-01-01 23:22:02,10
|
2019-01-02 18:49:33,10
|
||||||
2019-01-01 23:22:07,10
|
2019-01-02 18:49:38,10
|
||||||
2019-01-01 23:22:12,10
|
2019-01-02 18:49:43,10
|
||||||
2019-01-01 23:22:17,10
|
2019-01-02 18:49:48,10
|
||||||
2019-01-01 23:22:22,10
|
2019-01-02 18:49:53,10
|
||||||
2019-01-01 23:22:27,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:32,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:37,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:42,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:47,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:52,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:22:57,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:02,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:10,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:15,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:20,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:25,10
|
2019-01-02 18:49:58,10
|
||||||
2019-01-01 23:23:30,10
|
2019-01-02 18:50:03,10
|
||||||
2019-01-01 23:23:35,10
|
2019-01-02 18:50:08,10
|
||||||
2019-01-01 23:23:40,10
|
2019-01-02 18:50:13,10
|
||||||
2019-01-01 23:23:45,10
|
2019-01-02 18:50:18,10
|
||||||
2019-01-01 23:23:50,10
|
2019-01-02 18:50:23,10
|
||||||
2019-01-01 23:23:55,10
|
2019-01-02 18:50:28,10
|
||||||
2019-01-01 23:24:00,10
|
2019-01-02 18:50:33,10
|
||||||
2019-01-01 23:24:05,10
|
2019-01-02 18:50:38,10
|
||||||
2019-01-01 23:24:10,10
|
2019-01-02 18:50:43,10
|
||||||
2019-01-01 23:24:15,10
|
2019-01-02 18:50:48,10
|
||||||
2019-01-01 23:24:20,10
|
2019-01-02 18:50:53,10
|
||||||
2019-01-01 23:24:25,10
|
2019-01-02 18:50:58,10
|
||||||
2019-01-01 23:24:30,10
|
2019-01-02 18:51:03,10
|
||||||
2019-01-01 23:24:35,10
|
2019-01-02 18:51:08,10
|
||||||
2019-01-01 23:24:40,10
|
2019-01-02 18:51:13,10
|
||||||
2019-01-01 23:24:45,10
|
2019-01-02 18:51:18,10
|
||||||
2019-01-01 23:24:50,10
|
2019-01-02 18:51:23,10
|
||||||
2019-01-01 23:24:55,10
|
2019-01-02 18:51:28,10
|
||||||
2019-01-01 23:25:00,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:05,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:10,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:15,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:20,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:25,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:30,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:42,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:47,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:52,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:25:57,10
|
2019-01-02 18:51:29,10
|
||||||
2019-01-01 23:26:02,10
|
2019-01-02 18:51:33,10
|
||||||
2019-01-01 23:26:07,10
|
2019-01-02 18:51:38,10
|
||||||
2019-01-01 23:26:12,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:17,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:22,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:27,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:32,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:37,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:42,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:47,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:52,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:26:57,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:27:02,10
|
2019-01-02 18:51:43,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-02 00:29:45,10
|
2019-01-02 19:43:47,10
|
||||||
2019-01-02 00:29:50,10
|
2019-01-02 19:43:52,10
|
||||||
2019-01-02 00:29:55,10
|
2019-01-02 19:43:57,10
|
||||||
2019-01-02 00:30:00,10
|
2019-01-02 19:44:02,10
|
||||||
2019-01-02 00:30:05,10
|
2019-01-02 19:44:07,10
|
||||||
2019-01-02 00:30:10,10
|
2019-01-02 19:44:12,10
|
||||||
2019-01-02 00:30:15,10
|
2019-01-02 19:44:17,10
|
||||||
2019-01-02 00:30:20,10
|
2019-01-02 19:44:22,10
|
||||||
2019-01-02 00:30:25,10
|
2019-01-02 19:44:27,10
|
||||||
2019-01-02 00:30:30,10
|
2019-01-02 19:44:32,10
|
||||||
2019-01-02 00:30:35,10
|
2019-01-02 19:44:37,10
|
||||||
2019-01-02 00:30:40,10
|
2019-01-02 19:44:42,10
|
||||||
2019-01-02 00:30:45,10
|
2019-01-02 19:44:47,10
|
||||||
2019-01-02 00:30:50,10
|
2019-01-02 19:44:52,10
|
||||||
2019-01-02 00:30:55,10
|
2019-01-02 19:44:57,10
|
||||||
2019-01-02 00:31:00,10
|
2019-01-02 19:45:02,10
|
||||||
2019-01-02 00:31:05,10
|
2019-01-02 19:45:07,10
|
||||||
2019-01-02 00:31:10,10
|
2019-01-02 19:45:12,10
|
||||||
2019-01-02 00:31:15,10
|
2019-01-02 19:45:17,10
|
||||||
2019-01-02 00:31:20,10
|
2019-01-02 19:45:22,10
|
||||||
2019-01-02 00:31:25,10
|
2019-01-02 19:45:27,10
|
||||||
2019-01-02 00:31:30,10
|
2019-01-02 20:21:15,10
|
||||||
2019-01-02 00:31:35,10
|
2019-01-02 20:21:20,10
|
||||||
2019-01-02 00:31:40,10
|
2019-01-02 20:21:25,10
|
||||||
2019-01-02 00:31:45,10
|
2019-01-02 20:21:30,10
|
||||||
2019-01-02 00:31:50,10
|
2019-01-02 20:21:35,10
|
||||||
2019-01-02 00:31:55,10
|
2019-01-02 20:21:40,10
|
||||||
2019-01-02 00:32:00,10
|
2019-01-02 20:21:45,10
|
||||||
2019-01-02 00:32:05,10
|
2019-01-02 20:21:50,10
|
||||||
2019-01-02 00:32:10,10
|
2019-01-02 20:21:55,10
|
||||||
2019-01-02 00:32:15,10
|
2019-01-02 20:22:00,10
|
||||||
2019-01-02 00:32:20,10
|
2019-01-02 20:22:05,10
|
||||||
2019-01-02 00:32:25,10
|
2019-01-02 20:22:10,10
|
||||||
2019-01-02 00:32:30,10
|
2019-01-02 20:22:15,10
|
||||||
2019-01-02 00:32:35,10
|
2019-01-02 20:22:20,10
|
||||||
2019-01-02 00:32:40,10
|
2019-01-02 20:22:25,10
|
||||||
2019-01-02 00:32:45,10
|
2019-01-02 20:22:30,10
|
||||||
2019-01-02 00:32:51,10
|
2019-01-02 20:22:35,10
|
||||||
2019-01-02 00:32:56,10
|
2019-01-02 20:22:40,10
|
||||||
2019-01-02 00:33:01,10
|
2019-01-02 20:22:45,10
|
||||||
2019-01-02 00:33:06,10
|
2019-01-02 20:22:50,10
|
||||||
2019-01-02 00:33:11,10
|
2019-01-02 20:22:55,10
|
||||||
2019-01-02 00:33:16,10
|
2019-01-02 20:23:00,10
|
||||||
2019-01-02 00:33:21,10
|
2019-01-02 20:23:05,10
|
||||||
2019-01-02 00:33:26,10
|
2019-01-02 20:23:10,10
|
||||||
2019-01-02 00:33:31,10
|
2019-01-02 20:23:15,10
|
||||||
2019-01-02 00:33:36,10
|
2019-01-02 20:23:20,10
|
||||||
2019-01-02 00:33:41,10
|
2019-01-02 20:23:25,10
|
||||||
2019-01-02 00:33:46,10
|
2019-01-02 20:23:30,10
|
||||||
2019-01-02 00:33:51,10
|
2019-01-02 20:23:35,10
|
||||||
2019-01-02 00:33:56,10
|
2019-01-02 20:23:40,10
|
||||||
2019-01-02 00:34:01,10
|
2019-01-02 20:23:45,10
|
||||||
2019-01-02 00:34:06,10
|
2019-01-02 20:23:50,10
|
||||||
2019-01-02 00:34:11,10
|
2019-01-02 20:23:55,10
|
||||||
2019-01-02 00:34:16,10
|
2019-01-02 20:24:00,10
|
||||||
2019-01-02 00:34:21,10
|
2019-01-02 20:24:05,10
|
||||||
2019-01-02 00:34:26,10
|
2019-01-02 20:24:10,10
|
||||||
2019-01-02 00:34:31,10
|
2019-01-02 20:24:15,10
|
||||||
2019-01-02 00:34:36,10
|
2019-01-02 20:24:20,10
|
||||||
2019-01-02 00:34:41,10
|
2019-01-02 20:24:25,10
|
||||||
2019-01-02 00:34:46,10
|
2019-01-02 20:24:30,10
|
||||||
2019-01-02 00:34:51,10
|
2019-01-02 20:24:35,10
|
||||||
2019-01-02 00:34:56,10
|
2019-01-02 20:24:40,10
|
||||||
2019-01-02 00:35:01,10
|
2019-01-02 20:24:45,10
|
||||||
2019-01-02 00:35:06,10
|
2019-01-02 20:24:50,10
|
||||||
2019-01-02 00:35:11,10
|
2019-01-02 20:24:55,10
|
||||||
2019-01-02 00:35:16,10
|
2019-01-02 20:25:00,10
|
||||||
2019-01-02 00:35:21,10
|
2019-01-02 20:25:05,10
|
||||||
2019-01-02 00:35:26,10
|
2019-01-02 20:25:10,10
|
||||||
2019-01-02 00:35:31,10
|
2019-01-02 20:25:15,10
|
||||||
2019-01-02 00:35:36,10
|
2019-01-02 20:25:20,10
|
||||||
2019-01-02 00:35:41,10
|
2019-01-02 20:25:25,10
|
||||||
2019-01-02 00:35:46,10
|
2019-01-02 20:25:30,10
|
||||||
2019-01-02 00:35:51,10
|
2019-01-02 20:25:35,10
|
||||||
2019-01-02 00:35:56,10
|
2019-01-02 20:25:40,10
|
||||||
2019-01-02 00:36:01,10
|
2019-01-02 20:25:45,10
|
||||||
2019-01-02 00:36:06,10
|
2019-01-02 20:25:50,10
|
||||||
2019-01-02 00:36:11,10
|
2019-01-02 20:25:55,10
|
||||||
2019-01-02 00:36:16,10
|
2019-01-02 20:26:00,10
|
||||||
2019-01-02 00:36:21,10
|
2019-01-02 20:26:05,10
|
||||||
2019-01-02 00:36:26,10
|
2019-01-02 20:26:10,10
|
||||||
2019-01-02 00:36:31,10
|
2019-01-02 20:26:15,10
|
||||||
2019-01-02 00:36:36,10
|
2019-01-02 20:26:20,10
|
||||||
2019-01-02 00:36:41,10
|
2019-01-02 20:26:25,10
|
||||||
2019-01-02 00:36:46,10
|
2019-01-02 20:26:30,10
|
||||||
2019-01-02 00:36:51,10
|
2019-01-02 20:26:35,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-02 00:22:01,10
|
2019-01-02 19:36:04,10
|
||||||
2019-01-02 00:22:06,10
|
2019-01-02 19:36:09,10
|
||||||
2019-01-02 00:22:11,10
|
2019-01-02 19:36:14,10
|
||||||
2019-01-02 00:22:16,10
|
2019-01-02 19:36:19,10
|
||||||
2019-01-02 00:22:21,10
|
2019-01-02 19:36:24,10
|
||||||
2019-01-02 00:22:26,10
|
2019-01-02 19:36:29,10
|
||||||
2019-01-02 00:22:31,10
|
2019-01-02 19:36:34,10
|
||||||
2019-01-02 00:22:36,10
|
2019-01-02 19:36:39,10
|
||||||
2019-01-02 00:22:41,10
|
2019-01-02 19:36:44,10
|
||||||
2019-01-02 00:22:46,10
|
2019-01-02 19:36:49,10
|
||||||
2019-01-02 00:22:51,10
|
2019-01-02 19:36:54,10
|
||||||
2019-01-02 00:23:30,10
|
2019-01-02 19:36:59,10
|
||||||
2019-01-02 00:23:35,10
|
2019-01-02 19:37:04,10
|
||||||
2019-01-02 00:23:40,10
|
2019-01-02 19:37:09,10
|
||||||
2019-01-02 00:23:45,10
|
2019-01-02 19:37:14,10
|
||||||
2019-01-02 00:23:50,10
|
2019-01-02 19:37:19,10
|
||||||
2019-01-02 00:23:55,10
|
2019-01-02 19:37:24,10
|
||||||
2019-01-02 00:24:00,10
|
2019-01-02 19:37:30,10
|
||||||
2019-01-02 00:24:05,10
|
2019-01-02 19:37:35,10
|
||||||
2019-01-02 00:24:10,10
|
2019-01-02 19:37:40,10
|
||||||
2019-01-02 00:24:15,10
|
2019-01-02 19:37:45,10
|
||||||
2019-01-02 00:24:20,10
|
2019-01-02 19:37:50,10
|
||||||
2019-01-02 00:24:25,10
|
2019-01-02 19:37:55,10
|
||||||
2019-01-02 00:24:30,10
|
2019-01-02 19:38:00,10
|
||||||
2019-01-02 00:24:35,10
|
2019-01-02 19:38:05,10
|
||||||
2019-01-02 00:24:40,10
|
2019-01-02 19:38:10,10
|
||||||
2019-01-02 00:24:45,10
|
2019-01-02 19:38:15,10
|
||||||
2019-01-02 00:24:50,10
|
2019-01-02 19:38:20,10
|
||||||
2019-01-02 00:24:55,10
|
2019-01-02 19:38:25,10
|
||||||
2019-01-02 00:25:00,10
|
2019-01-02 19:38:30,10
|
||||||
2019-01-02 00:25:05,10
|
2019-01-02 19:38:35,10
|
||||||
2019-01-02 00:25:10,10
|
2019-01-02 19:38:44,10
|
||||||
2019-01-02 00:25:15,10
|
2019-01-02 19:38:49,10
|
||||||
2019-01-02 00:25:20,10
|
2019-01-02 19:38:54,10
|
||||||
2019-01-02 00:25:25,10
|
2019-01-02 19:38:59,10
|
||||||
2019-01-02 00:25:30,10
|
2019-01-02 19:39:04,10
|
||||||
2019-01-02 00:25:35,10
|
2019-01-02 19:39:09,10
|
||||||
2019-01-02 00:25:40,10
|
2019-01-02 19:39:14,10
|
||||||
2019-01-02 00:25:45,10
|
2019-01-02 19:39:22,10
|
||||||
2019-01-02 00:25:50,10
|
2019-01-02 19:39:27,10
|
||||||
2019-01-02 00:25:55,10
|
2019-01-02 19:39:32,10
|
||||||
2019-01-02 00:26:00,10
|
2019-01-02 19:39:37,10
|
||||||
2019-01-02 00:26:05,10
|
2019-01-02 19:39:42,10
|
||||||
2019-01-02 00:26:10,10
|
2019-01-02 19:39:47,10
|
||||||
2019-01-02 00:26:15,10
|
2019-01-02 19:39:52,10
|
||||||
2019-01-02 00:26:20,10
|
2019-01-02 19:39:58,10
|
||||||
2019-01-02 00:26:25,10
|
2019-01-02 19:40:03,10
|
||||||
2019-01-02 00:26:30,10
|
2019-01-02 19:40:08,10
|
||||||
2019-01-02 00:26:35,10
|
2019-01-02 19:40:13,10
|
||||||
2019-01-02 00:26:40,10
|
2019-01-02 19:40:18,10
|
||||||
2019-01-02 00:26:45,10
|
2019-01-02 19:40:23,10
|
||||||
2019-01-02 00:26:50,10
|
2019-01-02 19:40:28,10
|
||||||
2019-01-02 00:26:55,10
|
2019-01-02 19:40:33,10
|
||||||
2019-01-02 00:27:00,10
|
2019-01-02 19:40:43,10
|
||||||
2019-01-02 00:27:05,10
|
2019-01-02 19:40:48,10
|
||||||
2019-01-02 00:27:10,10
|
2019-01-02 19:40:53,10
|
||||||
2019-01-02 00:27:15,10
|
2019-01-02 19:40:58,10
|
||||||
2019-01-02 00:27:20,10
|
2019-01-02 19:41:03,10
|
||||||
2019-01-02 00:27:25,10
|
2019-01-02 19:41:08,10
|
||||||
2019-01-02 00:27:30,10
|
2019-01-02 19:41:20,10
|
||||||
2019-01-02 00:27:35,10
|
2019-01-02 19:41:25,10
|
||||||
2019-01-02 00:27:40,10
|
2019-01-02 19:41:36,10
|
||||||
2019-01-02 00:27:45,10
|
2019-01-02 19:41:41,10
|
||||||
2019-01-02 00:27:50,10
|
2019-01-02 19:41:46,10
|
||||||
2019-01-02 00:27:55,10
|
2019-01-02 19:41:51,10
|
||||||
2019-01-02 00:28:00,10
|
2019-01-02 19:41:56,10
|
||||||
2019-01-02 00:28:05,10
|
2019-01-02 19:42:01,10
|
||||||
2019-01-02 00:28:10,10
|
2019-01-02 19:42:06,10
|
||||||
2019-01-02 00:28:15,10
|
2019-01-02 19:42:11,10
|
||||||
2019-01-02 00:28:20,10
|
2019-01-02 19:42:16,10
|
||||||
2019-01-02 00:28:25,10
|
2019-01-02 19:42:21,10
|
||||||
2019-01-02 00:28:30,10
|
2019-01-02 19:42:26,10
|
||||||
2019-01-02 00:28:35,10
|
2019-01-02 19:42:31,10
|
||||||
2019-01-02 00:28:40,10
|
2019-01-02 19:42:36,10
|
||||||
2019-01-02 00:28:45,10
|
2019-01-02 19:42:41,10
|
||||||
2019-01-02 00:28:50,10
|
2019-01-02 19:42:46,10
|
||||||
2019-01-02 00:28:55,10
|
2019-01-02 19:42:51,10
|
||||||
2019-01-02 00:29:00,10
|
2019-01-02 19:42:56,10
|
||||||
2019-01-02 00:29:05,10
|
2019-01-02 19:43:01,10
|
||||||
2019-01-02 00:29:10,10
|
2019-01-02 19:43:06,10
|
||||||
2019-01-02 00:29:15,10
|
2019-01-02 19:43:11,10
|
||||||
2019-01-02 00:29:20,10
|
2019-01-02 19:43:22,10
|
||||||
2019-01-02 00:29:25,10
|
2019-01-02 19:43:27,10
|
||||||
2019-01-02 00:29:30,10
|
2019-01-02 19:43:32,10
|
||||||
2019-01-02 00:29:35,10
|
2019-01-02 19:43:37,10
|
||||||
2019-01-02 00:29:40,10
|
2019-01-02 19:43:42,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-02 00:14:36,10
|
2019-01-02 19:28:35,10
|
||||||
2019-01-02 00:14:41,10
|
2019-01-02 19:28:40,10
|
||||||
2019-01-02 00:14:46,10
|
2019-01-02 19:28:47,10
|
||||||
2019-01-02 00:14:51,10
|
2019-01-02 19:28:52,10
|
||||||
2019-01-02 00:14:56,10
|
2019-01-02 19:28:57,10
|
||||||
2019-01-02 00:15:01,10
|
2019-01-02 19:29:02,10
|
||||||
2019-01-02 00:15:06,10
|
2019-01-02 19:29:07,10
|
||||||
2019-01-02 00:15:11,10
|
2019-01-02 19:29:12,10
|
||||||
2019-01-02 00:15:16,10
|
2019-01-02 19:29:17,10
|
||||||
2019-01-02 00:15:21,10
|
2019-01-02 19:29:22,10
|
||||||
2019-01-02 00:15:26,10
|
2019-01-02 19:29:27,10
|
||||||
2019-01-02 00:15:31,10
|
2019-01-02 19:29:32,10
|
||||||
2019-01-02 00:15:36,10
|
2019-01-02 19:29:44,10
|
||||||
2019-01-02 00:15:41,10
|
2019-01-02 19:29:49,10
|
||||||
2019-01-02 00:15:46,10
|
2019-01-02 19:29:54,10
|
||||||
2019-01-02 00:15:51,10
|
2019-01-02 19:29:59,10
|
||||||
2019-01-02 00:15:56,10
|
2019-01-02 19:30:04,10
|
||||||
2019-01-02 00:16:01,10
|
2019-01-02 19:30:09,10
|
||||||
2019-01-02 00:16:06,10
|
2019-01-02 19:30:14,10
|
||||||
2019-01-02 00:16:11,10
|
2019-01-02 19:30:19,10
|
||||||
2019-01-02 00:16:16,10
|
2019-01-02 19:30:24,10
|
||||||
2019-01-02 00:16:21,10
|
2019-01-02 19:30:29,10
|
||||||
2019-01-02 00:16:26,10
|
2019-01-02 19:30:34,10
|
||||||
2019-01-02 00:16:31,10
|
2019-01-02 19:30:39,10
|
||||||
2019-01-02 00:16:36,10
|
2019-01-02 19:30:46,10
|
||||||
2019-01-02 00:16:41,10
|
2019-01-02 19:30:51,10
|
||||||
2019-01-02 00:16:46,10
|
2019-01-02 19:30:56,10
|
||||||
2019-01-02 00:16:51,10
|
2019-01-02 19:31:01,10
|
||||||
2019-01-02 00:16:56,10
|
2019-01-02 19:31:09,10
|
||||||
2019-01-02 00:17:04,10
|
2019-01-02 19:31:14,10
|
||||||
2019-01-02 00:17:09,10
|
2019-01-02 19:31:19,10
|
||||||
2019-01-02 00:17:14,10
|
2019-01-02 19:31:24,10
|
||||||
2019-01-02 00:17:19,10
|
2019-01-02 19:31:29,10
|
||||||
2019-01-02 00:17:24,10
|
2019-01-02 19:31:34,10
|
||||||
2019-01-02 00:17:29,10
|
2019-01-02 19:31:39,10
|
||||||
2019-01-02 00:17:34,10
|
2019-01-02 19:31:44,10
|
||||||
2019-01-02 00:17:45,10
|
2019-01-02 19:31:49,10
|
||||||
2019-01-02 00:17:50,10
|
2019-01-02 19:31:54,10
|
||||||
2019-01-02 00:17:55,10
|
2019-01-02 19:31:59,10
|
||||||
2019-01-02 00:18:00,10
|
2019-01-02 19:32:04,10
|
||||||
2019-01-02 00:18:05,10
|
2019-01-02 19:32:13,10
|
||||||
2019-01-02 00:18:10,10
|
2019-01-02 19:32:18,10
|
||||||
2019-01-02 00:18:15,10
|
2019-01-02 19:32:23,10
|
||||||
2019-01-02 00:18:20,10
|
2019-01-02 19:32:28,10
|
||||||
2019-01-02 00:18:25,10
|
2019-01-02 19:32:33,10
|
||||||
2019-01-02 00:18:30,10
|
2019-01-02 19:32:38,10
|
||||||
2019-01-02 00:18:35,10
|
2019-01-02 19:32:43,10
|
||||||
2019-01-02 00:18:40,10
|
2019-01-02 19:32:48,10
|
||||||
2019-01-02 00:18:45,10
|
2019-01-02 19:32:53,10
|
||||||
2019-01-02 00:18:50,10
|
2019-01-02 19:32:58,10
|
||||||
2019-01-02 00:18:55,10
|
2019-01-02 19:33:03,10
|
||||||
2019-01-02 00:19:00,10
|
2019-01-02 19:33:08,10
|
||||||
2019-01-02 00:19:05,10
|
2019-01-02 19:33:13,10
|
||||||
2019-01-02 00:19:10,10
|
2019-01-02 19:33:18,10
|
||||||
2019-01-02 00:19:15,10
|
2019-01-02 19:33:23,10
|
||||||
2019-01-02 00:19:20,10
|
2019-01-02 19:33:28,10
|
||||||
2019-01-02 00:19:25,10
|
2019-01-02 19:33:33,10
|
||||||
2019-01-02 00:19:30,10
|
2019-01-02 19:33:38,10
|
||||||
2019-01-02 00:19:35,10
|
2019-01-02 19:33:43,10
|
||||||
2019-01-02 00:19:40,10
|
2019-01-02 19:33:48,10
|
||||||
2019-01-02 00:19:51,10
|
2019-01-02 19:33:53,10
|
||||||
2019-01-02 00:19:56,10
|
2019-01-02 19:33:58,10
|
||||||
2019-01-02 00:20:01,10
|
2019-01-02 19:34:03,10
|
||||||
2019-01-02 00:20:06,10
|
2019-01-02 19:34:08,10
|
||||||
2019-01-02 00:20:11,10
|
2019-01-02 19:34:13,10
|
||||||
2019-01-02 00:20:16,10
|
2019-01-02 19:34:18,10
|
||||||
2019-01-02 00:20:21,10
|
2019-01-02 19:34:23,10
|
||||||
2019-01-02 00:20:26,10
|
2019-01-02 19:34:28,10
|
||||||
2019-01-02 00:20:31,10
|
2019-01-02 19:34:33,10
|
||||||
2019-01-02 00:20:36,10
|
2019-01-02 19:34:38,10
|
||||||
2019-01-02 00:20:41,10
|
2019-01-02 19:34:44,10
|
||||||
2019-01-02 00:20:46,10
|
2019-01-02 19:34:49,10
|
||||||
2019-01-02 00:20:51,10
|
2019-01-02 19:34:54,10
|
||||||
2019-01-02 00:20:56,10
|
2019-01-02 19:34:59,10
|
||||||
2019-01-02 00:21:01,10
|
2019-01-02 19:35:04,10
|
||||||
2019-01-02 00:21:06,10
|
2019-01-02 19:35:09,10
|
||||||
2019-01-02 00:21:11,10
|
2019-01-02 19:35:14,10
|
||||||
2019-01-02 00:21:16,10
|
2019-01-02 19:35:19,10
|
||||||
2019-01-02 00:21:21,10
|
2019-01-02 19:35:24,10
|
||||||
2019-01-02 00:21:26,10
|
2019-01-02 19:35:29,10
|
||||||
2019-01-02 00:21:31,10
|
2019-01-02 19:35:34,10
|
||||||
2019-01-02 00:21:36,10
|
2019-01-02 19:35:39,10
|
||||||
2019-01-02 00:21:41,10
|
2019-01-02 19:35:44,10
|
||||||
2019-01-02 00:21:46,10
|
2019-01-02 19:35:49,10
|
||||||
2019-01-02 00:21:51,10
|
2019-01-02 19:35:54,10
|
||||||
2019-01-02 00:21:56,10
|
2019-01-02 19:35:59,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-02 00:07:03,10
|
2019-01-02 19:21:17,10
|
||||||
2019-01-02 00:07:08,10
|
2019-01-02 19:21:22,10
|
||||||
2019-01-02 00:07:13,10
|
2019-01-02 19:21:27,10
|
||||||
2019-01-02 00:07:18,10
|
2019-01-02 19:21:32,10
|
||||||
2019-01-02 00:07:23,10
|
2019-01-02 19:21:37,10
|
||||||
2019-01-02 00:07:28,10
|
2019-01-02 19:21:42,10
|
||||||
2019-01-02 00:07:33,10
|
2019-01-02 19:21:47,10
|
||||||
2019-01-02 00:07:38,10
|
2019-01-02 19:21:52,10
|
||||||
2019-01-02 00:07:43,10
|
2019-01-02 19:21:57,10
|
||||||
2019-01-02 00:07:48,10
|
2019-01-02 19:22:02,10
|
||||||
2019-01-02 00:07:53,10
|
2019-01-02 19:22:07,10
|
||||||
2019-01-02 00:07:58,10
|
2019-01-02 19:22:12,10
|
||||||
2019-01-02 00:08:03,10
|
2019-01-02 19:22:19,10
|
||||||
2019-01-02 00:08:08,10
|
2019-01-02 19:22:24,10
|
||||||
2019-01-02 00:08:13,10
|
2019-01-02 19:22:29,10
|
||||||
2019-01-02 00:08:18,10
|
2019-01-02 19:22:34,10
|
||||||
2019-01-02 00:08:23,10
|
2019-01-02 19:22:39,10
|
||||||
2019-01-02 00:08:28,10
|
2019-01-02 19:22:44,10
|
||||||
2019-01-02 00:08:33,10
|
2019-01-02 19:22:49,10
|
||||||
2019-01-02 00:08:38,10
|
2019-01-02 19:22:54,10
|
||||||
2019-01-02 00:08:43,10
|
2019-01-02 19:22:59,10
|
||||||
2019-01-02 00:08:48,10
|
2019-01-02 19:23:04,10
|
||||||
2019-01-02 00:08:53,10
|
2019-01-02 19:23:09,10
|
||||||
2019-01-02 00:08:58,10
|
2019-01-02 19:23:14,10
|
||||||
2019-01-02 00:09:03,10
|
2019-01-02 19:23:19,10
|
||||||
2019-01-02 00:09:08,10
|
2019-01-02 19:23:24,10
|
||||||
2019-01-02 00:09:13,10
|
2019-01-02 19:23:29,10
|
||||||
2019-01-02 00:09:18,10
|
2019-01-02 19:23:34,10
|
||||||
2019-01-02 00:09:23,10
|
2019-01-02 19:23:39,10
|
||||||
2019-01-02 00:09:28,10
|
2019-01-02 19:23:44,10
|
||||||
2019-01-02 00:09:33,10
|
2019-01-02 19:23:49,10
|
||||||
2019-01-02 00:09:38,10
|
2019-01-02 19:23:54,10
|
||||||
2019-01-02 00:09:43,10
|
2019-01-02 19:24:05,10
|
||||||
2019-01-02 00:09:48,10
|
2019-01-02 19:24:10,10
|
||||||
2019-01-02 00:09:53,10
|
2019-01-02 19:24:15,10
|
||||||
2019-01-02 00:09:58,10
|
2019-01-02 19:24:20,10
|
||||||
2019-01-02 00:10:03,10
|
2019-01-02 19:24:25,10
|
||||||
2019-01-02 00:10:08,10
|
2019-01-02 19:24:30,10
|
||||||
2019-01-02 00:10:13,10
|
2019-01-02 19:24:35,10
|
||||||
2019-01-02 00:10:18,10
|
2019-01-02 19:24:40,10
|
||||||
2019-01-02 00:10:23,10
|
2019-01-02 19:24:45,10
|
||||||
2019-01-02 00:10:28,10
|
2019-01-02 19:24:50,10
|
||||||
2019-01-02 00:10:33,10
|
2019-01-02 19:24:55,10
|
||||||
2019-01-02 00:10:38,10
|
2019-01-02 19:25:00,10
|
||||||
2019-01-02 00:10:43,10
|
2019-01-02 19:25:05,10
|
||||||
2019-01-02 00:10:48,10
|
2019-01-02 19:25:10,10
|
||||||
2019-01-02 00:10:53,10
|
2019-01-02 19:25:15,10
|
||||||
2019-01-02 00:10:58,10
|
2019-01-02 19:25:20,10
|
||||||
2019-01-02 00:11:03,10
|
2019-01-02 19:25:25,10
|
||||||
2019-01-02 00:11:08,10
|
2019-01-02 19:25:30,10
|
||||||
2019-01-02 00:11:13,10
|
2019-01-02 19:25:35,10
|
||||||
2019-01-02 00:11:18,10
|
2019-01-02 19:25:40,10
|
||||||
2019-01-02 00:11:23,10
|
2019-01-02 19:25:45,10
|
||||||
2019-01-02 00:11:28,10
|
2019-01-02 19:25:50,10
|
||||||
2019-01-02 00:11:33,10
|
2019-01-02 19:25:55,10
|
||||||
2019-01-02 00:11:38,10
|
2019-01-02 19:26:00,10
|
||||||
2019-01-02 00:11:43,10
|
2019-01-02 19:26:05,10
|
||||||
2019-01-02 00:11:48,10
|
2019-01-02 19:26:10,10
|
||||||
2019-01-02 00:11:53,10
|
2019-01-02 19:26:15,10
|
||||||
2019-01-02 00:11:58,10
|
2019-01-02 19:26:20,10
|
||||||
2019-01-02 00:12:03,10
|
2019-01-02 19:26:25,10
|
||||||
2019-01-02 00:12:08,10
|
2019-01-02 19:26:30,10
|
||||||
2019-01-02 00:12:13,10
|
2019-01-02 19:26:35,10
|
||||||
2019-01-02 00:12:18,10
|
2019-01-02 19:26:40,10
|
||||||
2019-01-02 00:12:23,10
|
2019-01-02 19:26:45,10
|
||||||
2019-01-02 00:12:28,10
|
2019-01-02 19:26:50,10
|
||||||
2019-01-02 00:12:33,10
|
2019-01-02 19:26:55,10
|
||||||
2019-01-02 00:12:38,10
|
2019-01-02 19:27:00,10
|
||||||
2019-01-02 00:12:43,10
|
2019-01-02 19:27:05,10
|
||||||
2019-01-02 00:12:48,10
|
2019-01-02 19:27:10,10
|
||||||
2019-01-02 00:12:53,10
|
2019-01-02 19:27:15,10
|
||||||
2019-01-02 00:12:58,10
|
2019-01-02 19:27:20,10
|
||||||
2019-01-02 00:13:03,10
|
2019-01-02 19:27:25,10
|
||||||
2019-01-02 00:13:08,10
|
2019-01-02 19:27:30,10
|
||||||
2019-01-02 00:13:13,10
|
2019-01-02 19:27:35,10
|
||||||
2019-01-02 00:13:18,10
|
2019-01-02 19:27:40,10
|
||||||
2019-01-02 00:13:23,10
|
2019-01-02 19:27:45,10
|
||||||
2019-01-02 00:13:28,10
|
2019-01-02 19:27:50,10
|
||||||
2019-01-02 00:13:33,10
|
2019-01-02 19:27:55,10
|
||||||
2019-01-02 00:13:38,10
|
2019-01-02 19:28:00,10
|
||||||
2019-01-02 00:13:43,10
|
2019-01-02 19:28:05,10
|
||||||
2019-01-02 00:13:48,10
|
2019-01-02 19:28:10,10
|
||||||
2019-01-02 00:13:53,10
|
2019-01-02 19:28:15,10
|
||||||
2019-01-02 00:14:19,10
|
2019-01-02 19:28:20,10
|
||||||
2019-01-02 00:14:24,10
|
2019-01-02 19:28:25,10
|
||||||
2019-01-02 00:14:31,10
|
2019-01-02 19:28:30,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-01 23:59:47,10
|
2019-01-02 19:14:06,10
|
||||||
2019-01-01 23:59:52,10
|
2019-01-02 19:14:11,10
|
||||||
2019-01-01 23:59:57,10
|
2019-01-02 19:14:16,10
|
||||||
2019-01-02 00:00:02,10
|
2019-01-02 19:14:21,10
|
||||||
2019-01-02 00:00:07,10
|
2019-01-02 19:14:26,10
|
||||||
2019-01-02 00:00:12,10
|
2019-01-02 19:14:32,10
|
||||||
2019-01-02 00:00:17,10
|
2019-01-02 19:14:37,10
|
||||||
2019-01-02 00:00:22,10
|
2019-01-02 19:14:42,10
|
||||||
2019-01-02 00:00:27,10
|
2019-01-02 19:14:47,10
|
||||||
2019-01-02 00:00:32,10
|
2019-01-02 19:14:52,10
|
||||||
2019-01-02 00:00:37,10
|
2019-01-02 19:14:57,10
|
||||||
2019-01-02 00:00:42,10
|
2019-01-02 19:15:02,10
|
||||||
2019-01-02 00:00:47,10
|
2019-01-02 19:15:07,10
|
||||||
2019-01-02 00:00:52,10
|
2019-01-02 19:15:12,10
|
||||||
2019-01-02 00:00:57,10
|
2019-01-02 19:15:17,10
|
||||||
2019-01-02 00:01:02,10
|
2019-01-02 19:15:22,10
|
||||||
2019-01-02 00:01:07,10
|
2019-01-02 19:15:27,10
|
||||||
2019-01-02 00:01:12,10
|
2019-01-02 19:15:32,10
|
||||||
2019-01-02 00:01:17,10
|
2019-01-02 19:15:37,10
|
||||||
2019-01-02 00:01:28,10
|
2019-01-02 19:15:42,10
|
||||||
2019-01-02 00:01:33,10
|
2019-01-02 19:15:47,10
|
||||||
2019-01-02 00:01:38,10
|
2019-01-02 19:15:52,10
|
||||||
2019-01-02 00:01:43,10
|
2019-01-02 19:15:57,10
|
||||||
2019-01-02 00:01:48,10
|
2019-01-02 19:16:02,10
|
||||||
2019-01-02 00:01:53,10
|
2019-01-02 19:16:07,10
|
||||||
2019-01-02 00:01:58,10
|
2019-01-02 19:16:12,10
|
||||||
2019-01-02 00:02:03,10
|
2019-01-02 19:16:17,10
|
||||||
2019-01-02 00:02:08,10
|
2019-01-02 19:16:22,10
|
||||||
2019-01-02 00:02:13,10
|
2019-01-02 19:16:27,10
|
||||||
2019-01-02 00:02:18,10
|
2019-01-02 19:16:32,10
|
||||||
2019-01-02 00:02:23,10
|
2019-01-02 19:16:37,10
|
||||||
2019-01-02 00:02:28,10
|
2019-01-02 19:16:42,10
|
||||||
2019-01-02 00:02:33,10
|
2019-01-02 19:16:47,10
|
||||||
2019-01-02 00:02:38,10
|
2019-01-02 19:16:52,10
|
||||||
2019-01-02 00:02:43,10
|
2019-01-02 19:16:57,10
|
||||||
2019-01-02 00:02:48,10
|
2019-01-02 19:17:02,10
|
||||||
2019-01-02 00:02:53,10
|
2019-01-02 19:17:07,10
|
||||||
2019-01-02 00:02:58,10
|
2019-01-02 19:17:12,10
|
||||||
2019-01-02 00:03:03,10
|
2019-01-02 19:17:17,10
|
||||||
2019-01-02 00:03:08,10
|
2019-01-02 19:17:22,10
|
||||||
2019-01-02 00:03:13,10
|
2019-01-02 19:17:27,10
|
||||||
2019-01-02 00:03:18,10
|
2019-01-02 19:17:32,10
|
||||||
2019-01-02 00:03:23,10
|
2019-01-02 19:17:37,10
|
||||||
2019-01-02 00:03:28,10
|
2019-01-02 19:17:42,10
|
||||||
2019-01-02 00:03:33,10
|
2019-01-02 19:17:47,10
|
||||||
2019-01-02 00:03:38,10
|
2019-01-02 19:17:52,10
|
||||||
2019-01-02 00:03:43,10
|
2019-01-02 19:17:57,10
|
||||||
2019-01-02 00:03:48,10
|
2019-01-02 19:18:02,10
|
||||||
2019-01-02 00:03:53,10
|
2019-01-02 19:18:07,10
|
||||||
2019-01-02 00:03:58,10
|
2019-01-02 19:18:12,10
|
||||||
2019-01-02 00:04:03,10
|
2019-01-02 19:18:17,10
|
||||||
2019-01-02 00:04:08,10
|
2019-01-02 19:18:22,10
|
||||||
2019-01-02 00:04:13,10
|
2019-01-02 19:18:27,10
|
||||||
2019-01-02 00:04:18,10
|
2019-01-02 19:18:32,10
|
||||||
2019-01-02 00:04:23,10
|
2019-01-02 19:18:37,10
|
||||||
2019-01-02 00:04:28,10
|
2019-01-02 19:18:42,10
|
||||||
2019-01-02 00:04:33,10
|
2019-01-02 19:18:47,10
|
||||||
2019-01-02 00:04:38,10
|
2019-01-02 19:18:52,10
|
||||||
2019-01-02 00:04:43,10
|
2019-01-02 19:18:57,10
|
||||||
2019-01-02 00:04:48,10
|
2019-01-02 19:19:02,10
|
||||||
2019-01-02 00:04:53,10
|
2019-01-02 19:19:07,10
|
||||||
2019-01-02 00:04:58,10
|
2019-01-02 19:19:12,10
|
||||||
2019-01-02 00:05:03,10
|
2019-01-02 19:19:17,10
|
||||||
2019-01-02 00:05:08,10
|
2019-01-02 19:19:22,10
|
||||||
2019-01-02 00:05:13,10
|
2019-01-02 19:19:27,10
|
||||||
2019-01-02 00:05:18,10
|
2019-01-02 19:19:32,10
|
||||||
2019-01-02 00:05:23,10
|
2019-01-02 19:19:37,10
|
||||||
2019-01-02 00:05:28,10
|
2019-01-02 19:19:42,10
|
||||||
2019-01-02 00:05:33,10
|
2019-01-02 19:19:47,10
|
||||||
2019-01-02 00:05:38,10
|
2019-01-02 19:19:52,10
|
||||||
2019-01-02 00:05:43,10
|
2019-01-02 19:19:57,10
|
||||||
2019-01-02 00:05:48,10
|
2019-01-02 19:20:02,10
|
||||||
2019-01-02 00:05:53,10
|
2019-01-02 19:20:07,10
|
||||||
2019-01-02 00:05:58,10
|
2019-01-02 19:20:12,10
|
||||||
2019-01-02 00:06:03,10
|
2019-01-02 19:20:17,10
|
||||||
2019-01-02 00:06:08,10
|
2019-01-02 19:20:22,10
|
||||||
2019-01-02 00:06:13,10
|
2019-01-02 19:20:27,10
|
||||||
2019-01-02 00:06:18,10
|
2019-01-02 19:20:32,10
|
||||||
2019-01-02 00:06:23,10
|
2019-01-02 19:20:37,10
|
||||||
2019-01-02 00:06:28,10
|
2019-01-02 19:20:42,10
|
||||||
2019-01-02 00:06:33,10
|
2019-01-02 19:20:47,10
|
||||||
2019-01-02 00:06:38,10
|
2019-01-02 19:20:52,10
|
||||||
2019-01-02 00:06:43,10
|
2019-01-02 19:20:57,10
|
||||||
2019-01-02 00:06:48,10
|
2019-01-02 19:21:02,10
|
||||||
2019-01-02 00:06:53,10
|
2019-01-02 19:21:07,10
|
||||||
2019-01-02 00:06:58,10
|
2019-01-02 19:21:12,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-01 23:50:48,10
|
2019-01-02 19:02:41,10
|
||||||
2019-01-01 23:50:53,10
|
2019-01-02 19:02:46,10
|
||||||
2019-01-01 23:51:03,10
|
2019-01-02 19:02:51,10
|
||||||
2019-01-01 23:51:08,10
|
2019-01-02 19:02:56,10
|
||||||
2019-01-01 23:51:13,10
|
2019-01-02 19:03:01,10
|
||||||
2019-01-01 23:51:18,10
|
2019-01-02 19:03:06,10
|
||||||
2019-01-01 23:51:23,10
|
2019-01-02 19:03:11,10
|
||||||
2019-01-01 23:51:28,10
|
2019-01-02 19:03:16,10
|
||||||
2019-01-01 23:51:33,10
|
2019-01-02 19:03:21,10
|
||||||
2019-01-01 23:51:38,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:51:49,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:51:54,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:51:59,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:04,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:09,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:14,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:19,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:24,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:29,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:34,10
|
2019-01-02 19:03:33,10
|
||||||
2019-01-01 23:52:39,10
|
2019-01-02 19:08:33,10
|
||||||
2019-01-01 23:52:44,10
|
2019-01-02 19:08:38,10
|
||||||
2019-01-01 23:52:49,10
|
2019-01-02 19:08:43,10
|
||||||
2019-01-01 23:52:54,10
|
2019-01-02 19:08:48,10
|
||||||
2019-01-01 23:52:59,10
|
2019-01-02 19:08:53,10
|
||||||
2019-01-01 23:53:04,10
|
2019-01-02 19:08:58,10
|
||||||
2019-01-01 23:53:09,10
|
2019-01-02 19:09:03,10
|
||||||
2019-01-01 23:53:14,10
|
2019-01-02 19:09:08,10
|
||||||
2019-01-01 23:53:19,10
|
2019-01-02 19:09:16,10
|
||||||
2019-01-01 23:53:24,10
|
2019-01-02 19:09:21,10
|
||||||
2019-01-01 23:53:29,10
|
2019-01-02 19:09:26,10
|
||||||
2019-01-01 23:53:34,10
|
2019-01-02 19:09:31,10
|
||||||
2019-01-01 23:53:39,10
|
2019-01-02 19:09:36,10
|
||||||
2019-01-01 23:53:44,10
|
2019-01-02 19:09:41,10
|
||||||
2019-01-01 23:53:49,10
|
2019-01-02 19:09:46,10
|
||||||
2019-01-01 23:53:54,10
|
2019-01-02 19:09:51,10
|
||||||
2019-01-01 23:53:59,10
|
2019-01-02 19:09:56,10
|
||||||
2019-01-01 23:54:04,10
|
2019-01-02 19:10:01,10
|
||||||
2019-01-01 23:54:09,10
|
2019-01-02 19:10:06,10
|
||||||
2019-01-01 23:54:14,10
|
2019-01-02 19:10:11,10
|
||||||
2019-01-01 23:54:19,10
|
2019-01-02 19:10:16,10
|
||||||
2019-01-01 23:54:24,10
|
2019-01-02 19:10:21,10
|
||||||
2019-01-01 23:54:34,10
|
2019-01-02 19:10:26,10
|
||||||
2019-01-01 23:54:39,10
|
2019-01-02 19:10:31,10
|
||||||
2019-01-01 23:54:44,10
|
2019-01-02 19:10:36,10
|
||||||
2019-01-01 23:54:49,10
|
2019-01-02 19:10:41,10
|
||||||
2019-01-01 23:54:54,10
|
2019-01-02 19:10:46,10
|
||||||
2019-01-01 23:54:59,10
|
2019-01-02 19:10:51,10
|
||||||
2019-01-01 23:56:32,10
|
2019-01-02 19:10:56,10
|
||||||
2019-01-01 23:56:37,10
|
2019-01-02 19:11:01,10
|
||||||
2019-01-01 23:56:42,10
|
2019-01-02 19:11:06,10
|
||||||
2019-01-01 23:56:47,10
|
2019-01-02 19:11:11,10
|
||||||
2019-01-01 23:56:52,10
|
2019-01-02 19:11:16,10
|
||||||
2019-01-01 23:56:57,10
|
2019-01-02 19:11:21,10
|
||||||
2019-01-01 23:57:02,10
|
2019-01-02 19:11:26,10
|
||||||
2019-01-01 23:57:07,10
|
2019-01-02 19:11:31,10
|
||||||
2019-01-01 23:57:12,10
|
2019-01-02 19:11:36,10
|
||||||
2019-01-01 23:57:17,10
|
2019-01-02 19:11:41,10
|
||||||
2019-01-01 23:57:22,10
|
2019-01-02 19:11:46,10
|
||||||
2019-01-01 23:57:27,10
|
2019-01-02 19:11:51,10
|
||||||
2019-01-01 23:57:32,10
|
2019-01-02 19:11:56,10
|
||||||
2019-01-01 23:57:37,10
|
2019-01-02 19:12:01,10
|
||||||
2019-01-01 23:57:42,10
|
2019-01-02 19:12:06,10
|
||||||
2019-01-01 23:57:47,10
|
2019-01-02 19:12:11,10
|
||||||
2019-01-01 23:57:53,10
|
2019-01-02 19:12:16,10
|
||||||
2019-01-01 23:57:58,10
|
2019-01-02 19:12:21,10
|
||||||
2019-01-01 23:58:03,10
|
2019-01-02 19:12:26,10
|
||||||
2019-01-01 23:58:12,10
|
2019-01-02 19:12:31,10
|
||||||
2019-01-01 23:58:17,10
|
2019-01-02 19:12:36,10
|
||||||
2019-01-01 23:58:22,10
|
2019-01-02 19:12:41,10
|
||||||
2019-01-01 23:58:27,10
|
2019-01-02 19:12:46,10
|
||||||
2019-01-01 23:58:32,10
|
2019-01-02 19:12:51,10
|
||||||
2019-01-01 23:58:37,10
|
2019-01-02 19:12:56,10
|
||||||
2019-01-01 23:58:42,10
|
2019-01-02 19:13:01,10
|
||||||
2019-01-01 23:58:47,10
|
2019-01-02 19:13:06,10
|
||||||
2019-01-01 23:58:52,10
|
2019-01-02 19:13:11,10
|
||||||
2019-01-01 23:58:57,10
|
2019-01-02 19:13:16,10
|
||||||
2019-01-01 23:59:02,10
|
2019-01-02 19:13:21,10
|
||||||
2019-01-01 23:59:07,10
|
2019-01-02 19:13:26,10
|
||||||
2019-01-01 23:59:12,10
|
2019-01-02 19:13:31,10
|
||||||
2019-01-01 23:59:17,10
|
2019-01-02 19:13:36,10
|
||||||
2019-01-01 23:59:22,10
|
2019-01-02 19:13:41,10
|
||||||
2019-01-01 23:59:27,10
|
2019-01-02 19:13:46,10
|
||||||
2019-01-01 23:59:32,10
|
2019-01-02 19:13:51,10
|
||||||
2019-01-01 23:59:37,10
|
2019-01-02 19:13:56,10
|
||||||
2019-01-01 23:59:42,10
|
2019-01-02 19:14:01,10
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
2019-01-01 23:43:05,10
|
2019-01-02 18:51:48,10
|
||||||
2019-01-01 23:43:10,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:43:15,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:43:20,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:43:25,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:43:30,10
|
2019-01-02 18:51:58,10
|
||||||
2019-01-01 23:43:35,10
|
2019-01-02 18:52:03,10
|
||||||
2019-01-01 23:43:40,10
|
2019-01-02 18:52:08,10
|
||||||
2019-01-01 23:43:45,10
|
2019-01-02 18:52:13,10
|
||||||
2019-01-01 23:43:50,10
|
2019-01-02 18:52:18,10
|
||||||
2019-01-01 23:43:55,10
|
2019-01-02 18:52:23,10
|
||||||
2019-01-01 23:44:02,10
|
2019-01-02 18:52:28,10
|
||||||
2019-01-01 23:44:07,10
|
2019-01-02 18:52:33,10
|
||||||
2019-01-01 23:44:12,10
|
2019-01-02 18:52:38,10
|
||||||
2019-01-01 23:44:17,10
|
2019-01-02 18:52:43,10
|
||||||
2019-01-01 23:44:22,10
|
2019-01-02 18:52:48,10
|
||||||
2019-01-01 23:44:27,10
|
2019-01-02 18:52:53,10
|
||||||
2019-01-01 23:44:32,10
|
2019-01-02 18:52:58,10
|
||||||
2019-01-01 23:44:37,10
|
2019-01-02 18:53:03,10
|
||||||
2019-01-01 23:44:42,10
|
2019-01-02 18:53:08,10
|
||||||
2019-01-01 23:44:47,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:44:52,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:44:57,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:02,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:11,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:16,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:21,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:26,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:31,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:36,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:41,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:46,10
|
2019-01-02 18:53:13,10
|
||||||
2019-01-01 23:45:51,10
|
2019-01-02 18:53:22,10
|
||||||
2019-01-01 23:45:56,10
|
2019-01-02 18:53:27,10
|
||||||
2019-01-01 23:46:01,10
|
2019-01-02 18:53:32,10
|
||||||
2019-01-01 23:46:06,10
|
2019-01-02 18:53:37,10
|
||||||
2019-01-01 23:46:11,10
|
2019-01-02 18:53:42,10
|
||||||
2019-01-01 23:46:16,10
|
2019-01-02 18:53:47,10
|
||||||
2019-01-01 23:46:21,10
|
2019-01-02 18:53:52,10
|
||||||
2019-01-01 23:46:26,10
|
2019-01-02 18:53:57,10
|
||||||
2019-01-01 23:46:31,10
|
2019-01-02 18:54:02,10
|
||||||
2019-01-01 23:46:36,10
|
2019-01-02 18:54:07,10
|
||||||
2019-01-01 23:46:41,10
|
2019-01-02 18:54:12,10
|
||||||
2019-01-01 23:46:46,10
|
2019-01-02 18:54:17,10
|
||||||
2019-01-01 23:46:51,10
|
2019-01-02 18:54:22,10
|
||||||
2019-01-01 23:46:56,10
|
2019-01-02 18:54:27,10
|
||||||
2019-01-01 23:47:01,10
|
2019-01-02 18:54:32,10
|
||||||
2019-01-01 23:47:06,10
|
2019-01-02 18:54:37,10
|
||||||
2019-01-01 23:47:11,10
|
2019-01-02 18:54:42,10
|
||||||
2019-01-01 23:47:16,10
|
2019-01-02 18:54:47,10
|
||||||
2019-01-01 23:47:21,10
|
2019-01-02 18:54:52,10
|
||||||
2019-01-01 23:47:26,10
|
2019-01-02 18:54:57,10
|
||||||
2019-01-01 23:47:31,10
|
2019-01-02 18:55:02,10
|
||||||
2019-01-01 23:47:36,10
|
2019-01-02 18:55:07,10
|
||||||
2019-01-01 23:47:41,10
|
2019-01-02 18:55:12,10
|
||||||
2019-01-01 23:47:46,10
|
2019-01-02 18:55:17,10
|
||||||
2019-01-01 23:47:51,10
|
2019-01-02 18:55:22,10
|
||||||
2019-01-01 23:47:56,10
|
2019-01-02 18:55:27,10
|
||||||
2019-01-01 23:48:01,10
|
2019-01-02 18:55:32,10
|
||||||
2019-01-01 23:48:06,10
|
2019-01-02 18:55:37,10
|
||||||
2019-01-01 23:48:11,10
|
2019-01-02 18:55:42,10
|
||||||
2019-01-01 23:48:16,10
|
2019-01-02 18:55:47,10
|
||||||
2019-01-01 23:48:21,10
|
2019-01-02 18:55:52,10
|
||||||
2019-01-01 23:48:26,10
|
2019-01-02 18:55:57,10
|
||||||
2019-01-01 23:48:31,10
|
2019-01-02 18:56:02,10
|
||||||
2019-01-01 23:48:36,10
|
2019-01-02 18:56:07,10
|
||||||
2019-01-01 23:48:41,10
|
2019-01-02 18:56:12,10
|
||||||
2019-01-01 23:48:46,10
|
2019-01-02 18:56:17,10
|
||||||
2019-01-01 23:48:51,10
|
2019-01-02 18:56:22,10
|
||||||
2019-01-01 23:48:56,10
|
2019-01-02 18:56:27,10
|
||||||
2019-01-01 23:49:01,10
|
2019-01-02 18:56:32,10
|
||||||
2019-01-01 23:49:21,10
|
2019-01-02 18:56:37,10
|
||||||
2019-01-01 23:49:26,10
|
2019-01-02 18:56:42,10
|
||||||
2019-01-01 23:49:31,10
|
2019-01-02 18:56:47,10
|
||||||
2019-01-01 23:49:36,10
|
2019-01-02 18:56:52,10
|
||||||
2019-01-01 23:49:41,10
|
2019-01-02 18:56:57,10
|
||||||
2019-01-01 23:49:46,10
|
2019-01-02 18:57:02,10
|
||||||
2019-01-01 23:49:51,10
|
2019-01-02 18:57:07,10
|
||||||
2019-01-01 23:49:56,10
|
2019-01-02 18:57:12,10
|
||||||
2019-01-01 23:50:01,10
|
2019-01-02 18:57:17,10
|
||||||
2019-01-01 23:50:06,10
|
2019-01-02 18:57:22,10
|
||||||
2019-01-01 23:50:11,10
|
2019-01-02 18:57:27,10
|
||||||
2019-01-01 23:50:16,10
|
2019-01-02 18:57:32,10
|
||||||
2019-01-01 23:50:21,10
|
2019-01-02 18:57:37,10
|
||||||
2019-01-01 23:50:26,10
|
2019-01-02 19:02:31,10
|
||||||
2019-01-01 23:50:43,10
|
2019-01-02 19:02:36,10
|
||||||
|
|
|
@ -1,86 +1,9 @@
|
||||||
2019-01-01 23:27:07,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 23:27:12,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:17,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:22,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:27,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:32,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:37,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:42,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:47,10
|
2019-01-02 18:51:53,10
|
||||||
2019-01-01 23:27:52,10
|
|
||||||
2019-01-01 23:27:57,10
|
|
||||||
2019-01-01 23:28:02,10
|
|
||||||
2019-01-01 23:28:07,10
|
|
||||||
2019-01-01 23:28:12,10
|
|
||||||
2019-01-01 23:28:17,10
|
|
||||||
2019-01-01 23:28:22,10
|
|
||||||
2019-01-01 23:28:27,10
|
|
||||||
2019-01-01 23:28:32,10
|
|
||||||
2019-01-01 23:28:37,10
|
|
||||||
2019-01-01 23:28:42,10
|
|
||||||
2019-01-01 23:28:47,10
|
|
||||||
2019-01-01 23:28:52,10
|
|
||||||
2019-01-01 23:28:57,10
|
|
||||||
2019-01-01 23:29:02,10
|
|
||||||
2019-01-01 23:29:07,10
|
|
||||||
2019-01-01 23:29:12,10
|
|
||||||
2019-01-01 23:29:17,10
|
|
||||||
2019-01-01 23:29:22,10
|
|
||||||
2019-01-01 23:29:27,10
|
|
||||||
2019-01-01 23:29:32,10
|
|
||||||
2019-01-01 23:29:37,10
|
|
||||||
2019-01-01 23:29:42,10
|
|
||||||
2019-01-01 23:29:47,10
|
|
||||||
2019-01-01 23:29:52,10
|
|
||||||
2019-01-01 23:29:57,10
|
|
||||||
2019-01-01 23:30:02,10
|
|
||||||
2019-01-01 23:35:55,10
|
|
||||||
2019-01-01 23:36:00,10
|
|
||||||
2019-01-01 23:36:05,10
|
|
||||||
2019-01-01 23:36:10,10
|
|
||||||
2019-01-01 23:36:15,10
|
|
||||||
2019-01-01 23:36:20,10
|
|
||||||
2019-01-01 23:36:25,10
|
|
||||||
2019-01-01 23:36:30,10
|
|
||||||
2019-01-01 23:36:35,10
|
|
||||||
2019-01-01 23:36:40,10
|
|
||||||
2019-01-01 23:36:45,10
|
|
||||||
2019-01-01 23:36:50,10
|
|
||||||
2019-01-01 23:36:55,10
|
|
||||||
2019-01-01 23:37:02,10
|
|
||||||
2019-01-01 23:37:07,10
|
|
||||||
2019-01-01 23:37:12,10
|
|
||||||
2019-01-01 23:37:17,10
|
|
||||||
2019-01-01 23:37:22,10
|
|
||||||
2019-01-01 23:39:27,10
|
|
||||||
2019-01-01 23:39:32,10
|
|
||||||
2019-01-01 23:39:37,10
|
|
||||||
2019-01-01 23:39:42,10
|
|
||||||
2019-01-01 23:39:47,10
|
|
||||||
2019-01-01 23:40:44,10
|
|
||||||
2019-01-01 23:40:49,10
|
|
||||||
2019-01-01 23:40:54,10
|
|
||||||
2019-01-01 23:40:59,10
|
|
||||||
2019-01-01 23:41:04,10
|
|
||||||
2019-01-01 23:41:09,10
|
|
||||||
2019-01-01 23:41:14,10
|
|
||||||
2019-01-01 23:41:19,10
|
|
||||||
2019-01-01 23:41:24,10
|
|
||||||
2019-01-01 23:41:29,10
|
|
||||||
2019-01-01 23:41:34,10
|
|
||||||
2019-01-01 23:41:39,10
|
|
||||||
2019-01-01 23:41:44,10
|
|
||||||
2019-01-01 23:41:49,10
|
|
||||||
2019-01-01 23:41:54,10
|
|
||||||
2019-01-01 23:41:59,10
|
|
||||||
2019-01-01 23:42:04,10
|
|
||||||
2019-01-01 23:42:09,10
|
|
||||||
2019-01-01 23:42:14,10
|
|
||||||
2019-01-01 23:42:19,10
|
|
||||||
2019-01-01 23:42:24,10
|
|
||||||
2019-01-01 23:42:29,10
|
|
||||||
2019-01-01 23:42:34,10
|
|
||||||
2019-01-01 23:42:39,10
|
|
||||||
2019-01-01 23:42:44,10
|
|
||||||
2019-01-01 23:42:49,10
|
|
||||||
2019-01-01 23:42:54,10
|
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
2019-01-01 16:29:39,10
|
2019-01-02 18:49:55,10
|
||||||
2019-01-01 16:29:40,10
|
2019-01-02 18:49:56,10
|
||||||
2019-01-01 16:29:41,10
|
2019-01-02 18:49:57,10
|
||||||
2019-01-01 16:29:42,10
|
2019-01-02 18:51:25,10
|
||||||
2019-01-01 16:31:21,10
|
2019-01-02 18:51:26,10
|
||||||
2019-01-01 16:31:22,10
|
2019-01-02 18:51:27,10
|
||||||
2019-01-01 16:31:23,10
|
2019-01-02 18:51:28,10
|
||||||
2019-01-01 16:31:24,10
|
2019-01-02 18:51:40,10
|
||||||
2019-01-01 16:49:40,10
|
2019-01-02 18:51:41,10
|
||||||
2019-01-01 16:49:41,10
|
2019-01-02 18:51:42,10
|
||||||
2019-01-01 16:49:42,10
|
2019-01-02 18:51:43,10
|
||||||
2019-01-01 16:49:43,10
|
2019-01-02 18:51:49,10
|
||||||
2019-01-01 16:51:23,10
|
2019-01-02 18:51:50,10
|
||||||
2019-01-01 16:51:24,10
|
2019-01-02 18:51:51,10
|
||||||
2019-01-01 16:51:25,10
|
2019-01-02 18:51:52,10
|
||||||
2019-01-01 16:51:26,10
|
2019-01-02 18:53:09,10
|
||||||
|
2019-01-02 18:53:10,10
|
||||||
|
2019-01-02 18:53:11,10
|
||||||
|
2019-01-02 18:53:12,10
|
||||||
|
2019-01-02 19:03:29,10
|
||||||
|
2019-01-02 19:03:30,10
|
||||||
|
2019-01-02 19:03:31,10
|
||||||
|
2019-01-02 19:03:32,10
|
||||||
|
|
86
logs/sensors/sensor_2.log.1
Normal file
86
logs/sensors/sensor_2.log.1
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
2019-01-02 17:05:13,10
|
||||||
|
2019-01-02 17:05:14,10
|
||||||
|
2019-01-02 17:05:15,10
|
||||||
|
2019-01-02 18:02:23,10
|
||||||
|
2019-01-02 18:02:24,10
|
||||||
|
2019-01-02 18:02:25,10
|
||||||
|
2019-01-02 18:02:26,10
|
||||||
|
2019-01-02 18:21:31,10
|
||||||
|
2019-01-02 18:21:32,10
|
||||||
|
2019-01-02 18:21:33,10
|
||||||
|
2019-01-02 18:21:34,10
|
||||||
|
2019-01-02 18:21:47,10
|
||||||
|
2019-01-02 18:21:48,10
|
||||||
|
2019-01-02 18:21:49,10
|
||||||
|
2019-01-02 18:21:50,10
|
||||||
|
2019-01-02 18:21:51,10
|
||||||
|
2019-01-02 18:29:16,10
|
||||||
|
2019-01-02 18:29:17,10
|
||||||
|
2019-01-02 18:29:18,10
|
||||||
|
2019-01-02 18:29:19,10
|
||||||
|
2019-01-02 18:31:37,10
|
||||||
|
2019-01-02 18:31:38,10
|
||||||
|
2019-01-02 18:31:39,10
|
||||||
|
2019-01-02 18:31:40,10
|
||||||
|
2019-01-02 18:32:06,10
|
||||||
|
2019-01-02 18:32:07,10
|
||||||
|
2019-01-02 18:32:08,10
|
||||||
|
2019-01-02 18:32:09,10
|
||||||
|
2019-01-02 18:32:59,10
|
||||||
|
2019-01-02 18:33:00,10
|
||||||
|
2019-01-02 18:33:01,10
|
||||||
|
2019-01-02 18:33:02,10
|
||||||
|
2019-01-02 18:33:33,10
|
||||||
|
2019-01-02 18:33:34,10
|
||||||
|
2019-01-02 18:33:35,10
|
||||||
|
2019-01-02 18:33:36,10
|
||||||
|
2019-01-02 18:33:37,10
|
||||||
|
2019-01-02 18:34:07,10
|
||||||
|
2019-01-02 18:34:08,10
|
||||||
|
2019-01-02 18:34:09,10
|
||||||
|
2019-01-02 18:34:10,10
|
||||||
|
2019-01-02 18:37:59,10
|
||||||
|
2019-01-02 18:38:00,10
|
||||||
|
2019-01-02 18:38:01,10
|
||||||
|
2019-01-02 18:38:02,10
|
||||||
|
2019-01-02 18:38:48,10
|
||||||
|
2019-01-02 18:38:49,10
|
||||||
|
2019-01-02 18:38:50,10
|
||||||
|
2019-01-02 18:38:51,10
|
||||||
|
2019-01-02 18:38:52,10
|
||||||
|
2019-01-02 18:40:45,10
|
||||||
|
2019-01-02 18:40:46,10
|
||||||
|
2019-01-02 18:40:47,10
|
||||||
|
2019-01-02 18:40:48,10
|
||||||
|
2019-01-02 18:40:56,10
|
||||||
|
2019-01-02 18:40:57,10
|
||||||
|
2019-01-02 18:40:58,10
|
||||||
|
2019-01-02 18:40:59,10
|
||||||
|
2019-01-02 18:41:00,10
|
||||||
|
2019-01-02 18:41:50,10
|
||||||
|
2019-01-02 18:41:51,10
|
||||||
|
2019-01-02 18:41:52,10
|
||||||
|
2019-01-02 18:41:53,10
|
||||||
|
2019-01-02 18:43:39,10
|
||||||
|
2019-01-02 18:43:40,10
|
||||||
|
2019-01-02 18:43:41,10
|
||||||
|
2019-01-02 18:43:42,10
|
||||||
|
2019-01-02 18:44:37,10
|
||||||
|
2019-01-02 18:44:38,10
|
||||||
|
2019-01-02 18:44:39,10
|
||||||
|
2019-01-02 18:44:40,10
|
||||||
|
2019-01-02 18:44:41,10
|
||||||
|
2019-01-02 18:45:17,10
|
||||||
|
2019-01-02 18:45:18,10
|
||||||
|
2019-01-02 18:45:19,10
|
||||||
|
2019-01-02 18:45:20,10
|
||||||
|
2019-01-02 18:47:19,10
|
||||||
|
2019-01-02 18:47:20,10
|
||||||
|
2019-01-02 18:47:21,10
|
||||||
|
2019-01-02 18:47:22,10
|
||||||
|
2019-01-02 18:47:23,10
|
||||||
|
2019-01-02 18:49:03,10
|
||||||
|
2019-01-02 18:49:05,10
|
||||||
|
2019-01-02 18:49:06,10
|
||||||
|
2019-01-02 18:49:07,10
|
||||||
|
2019-01-02 18:49:54,10
|
86
logs/sensors/sensor_2.log.2
Normal file
86
logs/sensors/sensor_2.log.2
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
2019-01-02 11:15:04,10
|
||||||
|
2019-01-02 11:16:21,10
|
||||||
|
2019-01-02 11:16:22,10
|
||||||
|
2019-01-02 11:16:23,10
|
||||||
|
2019-01-02 11:16:24,10
|
||||||
|
2019-01-02 11:16:25,10
|
||||||
|
2019-01-02 11:18:51,10
|
||||||
|
2019-01-02 11:18:52,10
|
||||||
|
2019-01-02 11:18:53,10
|
||||||
|
2019-01-02 11:18:54,10
|
||||||
|
2019-01-02 16:19:57,10
|
||||||
|
2019-01-02 16:19:58,10
|
||||||
|
2019-01-02 16:19:59,10
|
||||||
|
2019-01-02 16:20:00,10
|
||||||
|
2019-01-02 16:20:01,10
|
||||||
|
2019-01-02 16:21:08,10
|
||||||
|
2019-01-02 16:21:09,10
|
||||||
|
2019-01-02 16:21:10,10
|
||||||
|
2019-01-02 16:21:11,10
|
||||||
|
2019-01-02 16:21:25,10
|
||||||
|
2019-01-02 16:21:26,10
|
||||||
|
2019-01-02 16:21:27,10
|
||||||
|
2019-01-02 16:21:28,10
|
||||||
|
2019-01-02 16:22:24,10
|
||||||
|
2019-01-02 16:22:25,10
|
||||||
|
2019-01-02 16:22:26,10
|
||||||
|
2019-01-02 16:22:27,10
|
||||||
|
2019-01-02 16:23:42,10
|
||||||
|
2019-01-02 16:23:43,10
|
||||||
|
2019-01-02 16:23:44,10
|
||||||
|
2019-01-02 16:23:45,10
|
||||||
|
2019-01-02 16:23:46,10
|
||||||
|
2019-01-02 16:24:55,10
|
||||||
|
2019-01-02 16:24:56,10
|
||||||
|
2019-01-02 16:24:57,10
|
||||||
|
2019-01-02 16:24:58,10
|
||||||
|
2019-01-02 16:24:59,10
|
||||||
|
2019-01-02 16:25:20,10
|
||||||
|
2019-01-02 16:25:21,10
|
||||||
|
2019-01-02 16:25:22,10
|
||||||
|
2019-01-02 16:25:23,10
|
||||||
|
2019-01-02 16:25:24,10
|
||||||
|
2019-01-02 16:26:25,10
|
||||||
|
2019-01-02 16:26:26,10
|
||||||
|
2019-01-02 16:26:27,10
|
||||||
|
2019-01-02 16:26:28,10
|
||||||
|
2019-01-02 16:52:03,10
|
||||||
|
2019-01-02 16:52:04,10
|
||||||
|
2019-01-02 16:52:05,10
|
||||||
|
2019-01-02 16:52:06,10
|
||||||
|
2019-01-02 16:52:07,10
|
||||||
|
2019-01-02 16:52:47,10
|
||||||
|
2019-01-02 16:52:48,10
|
||||||
|
2019-01-02 16:52:49,10
|
||||||
|
2019-01-02 16:52:50,10
|
||||||
|
2019-01-02 16:53:19,10
|
||||||
|
2019-01-02 16:53:20,10
|
||||||
|
2019-01-02 16:53:22,10
|
||||||
|
2019-01-02 16:53:23,10
|
||||||
|
2019-01-02 16:53:46,10
|
||||||
|
2019-01-02 16:53:47,10
|
||||||
|
2019-01-02 16:53:48,10
|
||||||
|
2019-01-02 16:53:49,10
|
||||||
|
2019-01-02 17:00:57,10
|
||||||
|
2019-01-02 17:00:58,10
|
||||||
|
2019-01-02 17:00:59,10
|
||||||
|
2019-01-02 17:01:00,10
|
||||||
|
2019-01-02 17:01:06,10
|
||||||
|
2019-01-02 17:01:07,10
|
||||||
|
2019-01-02 17:01:08,10
|
||||||
|
2019-01-02 17:01:09,10
|
||||||
|
2019-01-02 17:02:14,10
|
||||||
|
2019-01-02 17:02:15,10
|
||||||
|
2019-01-02 17:02:16,10
|
||||||
|
2019-01-02 17:02:17,10
|
||||||
|
2019-01-02 17:02:18,10
|
||||||
|
2019-01-02 17:02:34,10
|
||||||
|
2019-01-02 17:02:35,10
|
||||||
|
2019-01-02 17:02:36,10
|
||||||
|
2019-01-02 17:02:37,10
|
||||||
|
2019-01-02 17:02:38,10
|
||||||
|
2019-01-02 17:02:48,10
|
||||||
|
2019-01-02 17:02:49,10
|
||||||
|
2019-01-02 17:02:50,10
|
||||||
|
2019-01-02 17:02:51,10
|
||||||
|
2019-01-02 17:05:12,10
|
86
logs/sensors/sensor_2.log.3
Normal file
86
logs/sensors/sensor_2.log.3
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
2019-01-01 16:29:39,10
|
||||||
|
2019-01-01 16:29:40,10
|
||||||
|
2019-01-01 16:29:41,10
|
||||||
|
2019-01-01 16:29:42,10
|
||||||
|
2019-01-01 16:31:21,10
|
||||||
|
2019-01-01 16:31:22,10
|
||||||
|
2019-01-01 16:31:23,10
|
||||||
|
2019-01-01 16:31:24,10
|
||||||
|
2019-01-01 16:49:40,10
|
||||||
|
2019-01-01 16:49:41,10
|
||||||
|
2019-01-01 16:49:42,10
|
||||||
|
2019-01-01 16:49:43,10
|
||||||
|
2019-01-01 16:51:23,10
|
||||||
|
2019-01-01 16:51:24,10
|
||||||
|
2019-01-01 16:51:25,10
|
||||||
|
2019-01-01 16:51:26,10
|
||||||
|
2019-01-02 10:46:44,10
|
||||||
|
2019-01-02 10:46:45,10
|
||||||
|
2019-01-02 10:46:46,10
|
||||||
|
2019-01-02 10:46:47,10
|
||||||
|
2019-01-02 10:46:48,10
|
||||||
|
2019-01-02 10:48:16,10
|
||||||
|
2019-01-02 10:48:17,10
|
||||||
|
2019-01-02 10:48:18,10
|
||||||
|
2019-01-02 10:48:19,10
|
||||||
|
2019-01-02 10:48:41,10
|
||||||
|
2019-01-02 10:48:42,10
|
||||||
|
2019-01-02 10:48:43,10
|
||||||
|
2019-01-02 10:48:44,10
|
||||||
|
2019-01-02 10:48:45,10
|
||||||
|
2019-01-02 10:49:30,10
|
||||||
|
2019-01-02 10:49:31,10
|
||||||
|
2019-01-02 10:49:32,10
|
||||||
|
2019-01-02 10:49:33,10
|
||||||
|
2019-01-02 10:49:51,10
|
||||||
|
2019-01-02 10:49:52,10
|
||||||
|
2019-01-02 10:49:53,10
|
||||||
|
2019-01-02 10:49:54,10
|
||||||
|
2019-01-02 10:56:09,10
|
||||||
|
2019-01-02 10:56:10,10
|
||||||
|
2019-01-02 10:56:11,10
|
||||||
|
2019-01-02 10:56:12,10
|
||||||
|
2019-01-02 10:56:35,10
|
||||||
|
2019-01-02 10:56:36,10
|
||||||
|
2019-01-02 10:56:37,10
|
||||||
|
2019-01-02 10:56:38,10
|
||||||
|
2019-01-02 11:01:55,10
|
||||||
|
2019-01-02 11:01:56,10
|
||||||
|
2019-01-02 11:01:57,10
|
||||||
|
2019-01-02 11:01:58,10
|
||||||
|
2019-01-02 11:03:23,10
|
||||||
|
2019-01-02 11:03:24,10
|
||||||
|
2019-01-02 11:03:25,10
|
||||||
|
2019-01-02 11:03:26,10
|
||||||
|
2019-01-02 11:04:47,10
|
||||||
|
2019-01-02 11:04:48,10
|
||||||
|
2019-01-02 11:04:49,10
|
||||||
|
2019-01-02 11:04:50,10
|
||||||
|
2019-01-02 11:05:22,10
|
||||||
|
2019-01-02 11:05:23,10
|
||||||
|
2019-01-02 11:05:24,10
|
||||||
|
2019-01-02 11:05:25,10
|
||||||
|
2019-01-02 11:06:54,10
|
||||||
|
2019-01-02 11:06:55,10
|
||||||
|
2019-01-02 11:06:56,10
|
||||||
|
2019-01-02 11:06:57,10
|
||||||
|
2019-01-02 11:08:16,10
|
||||||
|
2019-01-02 11:08:17,10
|
||||||
|
2019-01-02 11:08:18,10
|
||||||
|
2019-01-02 11:08:19,10
|
||||||
|
2019-01-02 11:09:04,10
|
||||||
|
2019-01-02 11:09:05,10
|
||||||
|
2019-01-02 11:09:06,10
|
||||||
|
2019-01-02 11:09:07,10
|
||||||
|
2019-01-02 11:10:59,10
|
||||||
|
2019-01-02 11:11:00,10
|
||||||
|
2019-01-02 11:11:01,10
|
||||||
|
2019-01-02 11:11:02,10
|
||||||
|
2019-01-02 11:11:03,10
|
||||||
|
2019-01-02 11:14:02,10
|
||||||
|
2019-01-02 11:14:03,10
|
||||||
|
2019-01-02 11:14:04,10
|
||||||
|
2019-01-02 11:14:05,10
|
||||||
|
2019-01-02 11:15:01,10
|
||||||
|
2019-01-02 11:15:02,10
|
||||||
|
2019-01-02 11:15:03,10
|
3
run.py
3
run.py
|
@ -1,7 +1,4 @@
|
||||||
from core.craftbeerpi import CraftBeerPi
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cbpi = CraftBeerPi()
|
cbpi = CraftBeerPi()
|
||||||
cbpi.start()
|
cbpi.start()
|
|
@ -21,23 +21,24 @@ class ActorTestCase(AioHTTPTestCase):
|
||||||
resp = await self.client.post(path="/login", data={"username": "cbpi", "password": "123"})
|
resp = await self.client.post(path="/login", data={"username": "cbpi", "password": "123"})
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
||||||
resp = await self.client.request("GET", "/actor/1/on")
|
resp = await self.client.request("POST", "/actor/1/on")
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
i = await self.cbpi.actor.get_one(1)
|
i = await self.cbpi.actor.get_one(1)
|
||||||
|
print(i)
|
||||||
assert i.instance.state is True
|
assert i.instance.state is True
|
||||||
|
|
||||||
resp = await self.client.request("GET", "/actor/1/off")
|
resp = await self.client.request("POST", "/actor/1/off")
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
i = await self.cbpi.actor.get_one(1)
|
i = await self.cbpi.actor.get_one(1)
|
||||||
assert i.instance.state is False
|
assert i.instance.state is False
|
||||||
|
|
||||||
resp = await self.client.request("GET", "/actor/1/toggle")
|
resp = await self.client.request("POST", "/actor/1/toggle")
|
||||||
|
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
i = await self.cbpi.actor.get_one(1)
|
i = await self.cbpi.actor.get_one(1)
|
||||||
assert i.instance.state is True
|
assert i.instance.state is True
|
||||||
|
|
||||||
resp = await self.client.request("GET", "/actor/1/toggle")
|
resp = await self.client.request("POST", "/actor/1/toggle")
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
i = await self.cbpi.actor.get_one(1)
|
i = await self.cbpi.actor.get_one(1)
|
||||||
assert i.instance.state is False
|
assert i.instance.state is False
|
||||||
|
@ -73,3 +74,21 @@ class ActorTestCase(AioHTTPTestCase):
|
||||||
# # Delete Sensor
|
# # Delete Sensor
|
||||||
resp = await self.client.delete(path="/actor/%s" % sensor_id)
|
resp = await self.client.delete(path="/actor/%s" % sensor_id)
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_crud_negative(self):
|
||||||
|
data = {
|
||||||
|
"name": "CustomActor",
|
||||||
|
"type": "CustomActor",
|
||||||
|
"config": {
|
||||||
|
"interval": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get actor which not exists
|
||||||
|
resp = await self.client.get(path="/actor/%s" % 9999)
|
||||||
|
assert resp.status == 500
|
||||||
|
|
||||||
|
# Update not existing actor
|
||||||
|
resp = await self.client.put(path="/actor/%s" % 9999, json=data)
|
||||||
|
assert resp.status == 500
|
||||||
|
|
|
@ -55,3 +55,7 @@ class ConfigTestCase(AioHTTPTestCase):
|
||||||
resp = await self.client.request("GET", "/config/")
|
resp = await self.client.request("GET", "/config/")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_get_default(self):
|
||||||
|
value = self.cbpi.config.get("HELLO_WORLD", None)
|
||||||
|
assert value == None
|
82
tests/test_dashboard.py
Normal file
82
tests/test_dashboard.py
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import aiohttp
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
|
||||||
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardTestCase(AioHTTPTestCase):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async def get_application(self):
|
||||||
|
self.cbpi = CraftBeerPi()
|
||||||
|
await self.cbpi.init_serivces()
|
||||||
|
return self.cbpi.app
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_crud(self):
|
||||||
|
data = {
|
||||||
|
"name": "MyDashboard",
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboard_content = {
|
||||||
|
"type": "Test",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"config": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = await self.client.get(path="/dashboard")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
# Add new dashboard
|
||||||
|
resp = await self.client.post(path="/dashboard/", json=data)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
m = await resp.json()
|
||||||
|
dashboard_id = m["id"]
|
||||||
|
|
||||||
|
# Get dashboard
|
||||||
|
resp = await self.client.get(path="/dashboard/%s" % dashboard_id)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
m2 = await resp.json()
|
||||||
|
dashboard_id = m2["id"]
|
||||||
|
|
||||||
|
# Update dashboard
|
||||||
|
resp = await self.client.put(path="/dashboard/%s" % dashboard_id, json=m)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
# Add dashboard content
|
||||||
|
dashboard_content["dbid"] = dashboard_id
|
||||||
|
resp = await self.client.post(path="/dashboard/%s/content" % dashboard_id, json=dashboard_content)
|
||||||
|
assert resp.status == 200
|
||||||
|
m_content = await resp.json()
|
||||||
|
print("CONTENT", m_content)
|
||||||
|
content_id = m_content["id"]
|
||||||
|
# Get dashboard
|
||||||
|
resp = await self.client.get(path="/dashboard/%s/content" % (dashboard_id))
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.put(path="/dashboard/%s/content/%s/move" % (dashboard_id, content_id), json=dict(x=1,y=1))
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.delete(path="/dashboard/%s/content/%s" % (dashboard_id, content_id))
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
# Delete dashboard
|
||||||
|
resp = await self.client.delete(path="/dashboard/%s" % dashboard_id)
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_dashboard_controller(self):
|
||||||
|
result = await self.cbpi.dashboard.get_all()
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
await self.cbpi.dashboard.add(**{"name":"Tewst"})
|
||||||
|
print(await self.cbpi.dashboard.get_one(1))
|
||||||
|
|
||||||
|
await self.cbpi.dashboard.add_content(dict(dbid=1,element_id=1,type="test",config={"name":"Manue"}))
|
||||||
|
await self.cbpi.dashboard.move_content(1,2,3)
|
36
tests/test_index.py
Normal file
36
tests/test_index.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
|
||||||
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
class IndexTestCase(AioHTTPTestCase):
|
||||||
|
|
||||||
|
async def get_application(self):
|
||||||
|
self.cbpi = CraftBeerPi()
|
||||||
|
await self.cbpi.init_serivces()
|
||||||
|
return self.cbpi.app
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_index(self):
|
||||||
|
|
||||||
|
|
||||||
|
# Test Index Page
|
||||||
|
resp = await self.client.get(path="/")
|
||||||
|
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"})
|
||||||
|
print("REPONSE STATUS", resp.status)
|
||||||
|
assert resp.status == 403
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_login(self):
|
||||||
|
|
||||||
|
resp = await self.client.post(path="/login", data={"username": "cbpi", "password": "123"})
|
||||||
|
print("REPONSE STATUS", resp.status)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.get(path="/logout")
|
||||||
|
print("REPONSE STATUS LGOUT", resp.status)
|
||||||
|
assert resp.status == 200
|
|
@ -18,6 +18,36 @@ class KettleTestCase(AioHTTPTestCase):
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
print(await resp.json())
|
print(await resp.json())
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_heater(self):
|
||||||
|
resp = await self.client.get("/kettle/1/heater/on")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
resp = await self.client.get("/kettle/1/heater/off")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_agitator(self):
|
||||||
|
resp = await self.client.get("/kettle/1/agitator/on")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
resp = await self.client.get("/kettle/1/agitator/off")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_temp(self):
|
||||||
|
resp = await self.client.get("/kettle/1/temp")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.get("/kettle/1/targettemp")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_automatic(self):
|
||||||
|
resp = await self.client.get("/kettle/1/automatic")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
|
||||||
@unittest_run_loop
|
@unittest_run_loop
|
||||||
async def test_crud(self):
|
async def test_crud(self):
|
||||||
data = {
|
data = {
|
||||||
|
@ -38,6 +68,7 @@ class KettleTestCase(AioHTTPTestCase):
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
||||||
m = await resp.json()
|
m = await resp.json()
|
||||||
|
print(m)
|
||||||
sensor_id = m["id"]
|
sensor_id = m["id"]
|
||||||
|
|
||||||
# Get sensor
|
# Get sensor
|
||||||
|
|
17
tests/test_notification_controller.py
Normal file
17
tests/test_notification_controller.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import aiohttp
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
|
||||||
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationTestCase(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_switch(self):
|
||||||
|
self.cbpi.notify("test", "test")
|
|
@ -21,7 +21,6 @@ class SensorTestCase(AioHTTPTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Add new sensor
|
# Add new sensor
|
||||||
resp = await self.client.post(path="/sensor/", json=data)
|
resp = await self.client.post(path="/sensor/", json=data)
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
@ -43,5 +42,3 @@ class SensorTestCase(AioHTTPTestCase):
|
||||||
# # Delete Sensor
|
# # Delete Sensor
|
||||||
resp = await self.client.delete(path="/sensor/%s" % sensor_id)
|
resp = await self.client.delete(path="/sensor/%s" % sensor_id)
|
||||||
assert resp.status == 204
|
assert resp.status == 204
|
||||||
|
|
||||||
await asyncio.sleep(5)
|
|
70
tests/test_step.py
Normal file
70
tests/test_step.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import asyncio
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
class StepTestCase(AioHTTPTestCase):
|
||||||
|
|
||||||
|
|
||||||
|
async def get_application(self):
|
||||||
|
self.cbpi = CraftBeerPi()
|
||||||
|
await self.cbpi.init_serivces()
|
||||||
|
return self.cbpi.app
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_get(self):
|
||||||
|
|
||||||
|
resp = await self.client.request("GET", "/step")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.request("GET", "/step/types")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_crud(self):
|
||||||
|
data = {
|
||||||
|
"name": "Test",
|
||||||
|
"type": "CustomStepCBPi",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add new sensor
|
||||||
|
resp = await self.client.post(path="/step/", json=data)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
m = await resp.json()
|
||||||
|
print(m)
|
||||||
|
sensor_id = m["id"]
|
||||||
|
|
||||||
|
# Get sensor
|
||||||
|
resp = await self.client.get(path="/step/%s" % sensor_id)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
m2 = await resp.json()
|
||||||
|
sensor_id = m2["id"]
|
||||||
|
|
||||||
|
# Update Sensor
|
||||||
|
resp = await self.client.put(path="/step/%s" % sensor_id, json=m)
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
# # Delete Sensor
|
||||||
|
resp = await self.client.delete(path="/step/%s" % sensor_id)
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_process(self):
|
||||||
|
resp = await self.client.request("GET", "/step/stop")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
resp = await self.client.request("GET", "/step/start")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
resp = await self.client.request("GET", "/step/next")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
resp = await self.client.request("GET", "/step/stop")
|
||||||
|
assert resp.status == 204
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
tests/test_system.py
Normal file
29
tests/test_system.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
|
||||||
|
from core.craftbeerpi import CraftBeerPi
|
||||||
|
|
||||||
|
|
||||||
|
class IndexTestCase(AioHTTPTestCase):
|
||||||
|
|
||||||
|
async def get_application(self):
|
||||||
|
self.cbpi = CraftBeerPi()
|
||||||
|
await self.cbpi.init_serivces()
|
||||||
|
return self.cbpi.app
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_endpoints(self):
|
||||||
|
|
||||||
|
|
||||||
|
# Test Index Page
|
||||||
|
resp = await self.client.post(path="/system/restart")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.post(path="/system/shutdown")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.get(path="/system/jobs")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await self.client.get(path="/system/events")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
15
tests/test_utils.py
Normal file
15
tests/test_utils.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
|
||||||
|
|
||||||
|
from core.craftbeerpi import CraftBeerPi, load_config
|
||||||
|
|
||||||
|
|
||||||
|
class UtilsTestCase(AioHTTPTestCase):
|
||||||
|
|
||||||
|
async def get_application(self):
|
||||||
|
self.cbpi = CraftBeerPi()
|
||||||
|
await self.cbpi.init_serivces()
|
||||||
|
return self.cbpi.app
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_load_file(self):
|
||||||
|
assert load_config("") is None
|
Loading…
Reference in a new issue