refactoring job controller

This commit is contained in:
manuel83 2019-01-02 00:48:36 +01:00
parent e0bec43960
commit b800fed933
48 changed files with 2890 additions and 1201 deletions

View file

@ -8,5 +8,11 @@
<auth-required>false</auth-required> <auth-required>false</auth-required>
<introspection-schemas>*:main</introspection-schemas> <introspection-schemas>*:main</introspection-schemas>
</data-source> </data-source>
<data-source name="craftbeerpi" uuid="3f79e533-e857-4e39-8e2e-d7f62530cc84">
<database-info product="SQLite" version="3.16.1" jdbc-version="2.1" driver-name="SQLiteJDBC" driver-version="native" dbms="SQLITE" exact-version="3.16.1" />
<case-sensitivity plain-identifiers="mixed" quoted-identifiers="mixed" />
<auth-required>false</auth-required>
<introspection-schemas>*:@</introspection-schemas>
</data-source>
</component> </component>
</project> </project>

View file

@ -10,5 +10,22 @@
<property name="enable_load_extension" value="true" /> <property name="enable_load_extension" value="true" />
</driver-properties> </driver-properties>
</data-source> </data-source>
<data-source source="LOCAL" name="craftbeerpi" uuid="3f79e533-e857-4e39-8e2e-d7f62530cc84">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/tests/craftbeerpi.db</jdbc-url>
<driver-properties>
<property name="enable_load_extension" value="true" />
</driver-properties>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.16.1/xerial-sqlite-license.txt</url>
</library>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.16.1/sqlite-jdbc-3.16.1.jar</url>
</library>
</libraries>
</data-source>
</component> </component>
</project> </project>

View file

@ -0,0 +1,352 @@
<?xml version="1.0" encoding="UTF-8"?>
<dataSource name="craftbeerpi">
<database-model serializer="dbm" dbms="SQLITE" family-id="SQLITE" format-version="4.14">
<root id="1">
<ServerVersion>3.16.1</ServerVersion>
</root>
<schema id="2" parent="1" name="main">
<Current>1</Current>
<Visible>1</Visible>
</schema>
<collation id="3" parent="1" name="BINARY"/>
<collation id="4" parent="1" name="NOCASE"/>
<collation id="5" parent="1" name="RTRIM"/>
<table id="6" parent="2" name="actor"/>
<table id="7" parent="2" name="config"/>
<table id="8" parent="2" name="dashboard"/>
<table id="9" parent="2" name="dashboard_content"/>
<table id="10" parent="2" name="dummy"/>
<table id="11" parent="2" name="kettle"/>
<table id="12" parent="2" name="sensor"/>
<table id="13" parent="2" name="sqlite_master">
<System>1</System>
</table>
<table id="14" parent="2" name="step"/>
<table id="15" parent="2" name="tank"/>
<table id="16" parent="2" name="translation"/>
<column id="17" parent="6" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="18" parent="6" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="19" parent="6" name="type">
<Position>3</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="20" parent="6" name="config">
<Position>4</Position>
<DataType>VARCHAR(3000)|0s</DataType>
</column>
<key id="21" parent="6">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="22" parent="7" name="name">
<Position>1</Position>
<DataType>VARCHAR(50)|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="23" parent="7" name="value">
<Position>2</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<column id="24" parent="7" name="type">
<Position>3</Position>
<DataType>VARCHAR(50)|0s</DataType>
</column>
<column id="25" parent="7" name="description">
<Position>4</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<column id="26" parent="7" name="options">
<Position>5</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<index id="27" parent="7" name="sqlite_autoindex_config_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="28" parent="7">
<ColNames>name</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_config_1</UnderlyingIndexName>
</key>
<column id="29" parent="8" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="30" parent="8" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<key id="31" parent="8">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="32" parent="9" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="33" parent="9" name="dbid">
<Position>2</Position>
<DataType>INTEGER(80)|0s</DataType>
</column>
<column id="34" parent="9" name="element_id">
<Position>3</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="35" parent="9" name="type">
<Position>4</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="36" parent="9" name="x">
<Position>5</Position>
<DataType>INTEGER(5)|0s</DataType>
</column>
<column id="37" parent="9" name="y">
<Position>6</Position>
<DataType>INTEGER(5)|0s</DataType>
</column>
<column id="38" parent="9" name="config">
<Position>7</Position>
<DataType>VARCHAR(3000)|0s</DataType>
</column>
<key id="39" parent="9">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="40" parent="10" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="41" parent="10" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<key id="42" parent="10">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="43" parent="11" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="44" parent="11" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="45" parent="11" name="sensor">
<Position>3</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="46" parent="11" name="heater">
<Position>4</Position>
<DataType>VARCHAR(10)|0s</DataType>
</column>
<column id="47" parent="11" name="automatic">
<Position>5</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<column id="48" parent="11" name="logic">
<Position>6</Position>
<DataType>VARCHAR(50)|0s</DataType>
</column>
<column id="49" parent="11" name="config">
<Position>7</Position>
<DataType>VARCHAR(1000)|0s</DataType>
</column>
<column id="50" parent="11" name="agitator">
<Position>8</Position>
<DataType>VARCHAR(10)|0s</DataType>
</column>
<column id="51" parent="11" name="target_temp">
<Position>9</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="52" parent="11" name="height">
<Position>10</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="53" parent="11" name="diameter">
<Position>11</Position>
<DataType>INTEGER|0s</DataType>
</column>
<key id="54" parent="11">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="55" parent="12" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="56" parent="12" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="57" parent="12" name="type">
<Position>3</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="58" parent="12" name="config">
<Position>4</Position>
<DataType>VARCHAR(3000)|0s</DataType>
</column>
<key id="59" parent="12">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="60" parent="13" name="type">
<Position>1</Position>
<DataType>text|0s</DataType>
</column>
<column id="61" parent="13" name="name">
<Position>2</Position>
<DataType>text|0s</DataType>
</column>
<column id="62" parent="13" name="tbl_name">
<Position>3</Position>
<DataType>text|0s</DataType>
</column>
<column id="63" parent="13" name="rootpage">
<Position>4</Position>
<DataType>integer|0s</DataType>
</column>
<column id="64" parent="13" name="sql">
<Position>5</Position>
<DataType>text|0s</DataType>
</column>
<column id="65" parent="14" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="66" parent="14" name="order">
<Position>2</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="67" parent="14" name="name">
<Position>3</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="68" parent="14" name="type">
<Position>4</Position>
<DataType>VARCHAR(100)|0s</DataType>
</column>
<column id="69" parent="14" name="stepstate">
<Position>5</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<column id="70" parent="14" name="state">
<Position>6</Position>
<DataType>VARCHAR(1)|0s</DataType>
</column>
<column id="71" parent="14" name="start">
<Position>7</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="72" parent="14" name="end">
<Position>8</Position>
<DataType>INTEGER|0s</DataType>
</column>
<column id="73" parent="14" name="config">
<Position>9</Position>
<DataType>VARCHAR(255)|0s</DataType>
</column>
<column id="74" parent="14" name="kettleid">
<Position>10</Position>
<DataType>INTEGER|0s</DataType>
</column>
<key id="75" parent="14">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="76" parent="15" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="77" parent="15" name="name">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="78" parent="15" name="brewname">
<Position>3</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="79" parent="15" name="sensor">
<Position>4</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="80" parent="15" name="sensor2">
<Position>5</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="81" parent="15" name="sensor3">
<Position>6</Position>
<DataType>VARCHAR(80)|0s</DataType>
</column>
<column id="82" parent="15" name="heater">
<Position>7</Position>
<DataType>VARCHAR(10)|0s</DataType>
</column>
<column id="83" parent="15" name="logic">
<Position>8</Position>
<DataType>VARCHAR(50)|0s</DataType>
</column>
<column id="84" parent="15" name="config">
<Position>9</Position>
<DataType>VARCHAR(1000)|0s</DataType>
</column>
<column id="85" parent="15" name="cooler">
<Position>10</Position>
<DataType>VARCHAR(10)|0s</DataType>
</column>
<column id="86" parent="15" name="target_temp">
<Position>11</Position>
<DataType>INTEGER|0s</DataType>
</column>
<key id="87" parent="15">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<column id="88" parent="16" name="language_code">
<Position>1</Position>
<DataType>VARCHAR(3)|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="89" parent="16" name="key">
<Position>2</Position>
<DataType>VARCHAR(80)|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="90" parent="16" name="text">
<Position>3</Position>
<DataType>VARCHAR(100)|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="91" parent="16" name="sqlite_autoindex_translation_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>language_code
key</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="92" parent="16">
<ColNames>language_code
key</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_translation_1</UnderlyingIndexName>
</key>
</database-model>
</dataSource>

View file

@ -0,0 +1,2 @@
#n:main
!<md> [0, 0, null, null, -2147483648, -2147483648]

File diff suppressed because it is too large Load diff

View file

@ -2,12 +2,10 @@
name: CraftBeerPi name: CraftBeerPi
version: 4.1 version: 4.1
#index_url: /myext
port: 8080 port: 8080
username: cbpi username: cbpi
password: 123 password: 123
test:
name: Manuel
name2: Manuel

View file

@ -9,40 +9,223 @@ from core.database.model import ActorModel
from core.http_endpoints.http_api import HttpAPI from core.http_endpoints.http_api import HttpAPI
from utils.encoder import ComplexEncoder from utils.encoder import ComplexEncoder
auth = True auth = False
class ActorHttp(HttpAPI): class ActorHttp(HttpAPI):
@request_mapping(path="/{id:\d+}/on", auth_required=auth) @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: async def http_on(self, request) -> web.Response:
""" """
:param request:
:return: ---
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']) id = int(request.match_info['id'])
result = await self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99) result = await self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
for key, value in result.results.items(): for key, value in result.results.items():
pass pass
return web.Response(status=204) return web.Response(status=204)
@request_mapping(path="/{id:\d+}/off", auth_required=auth) @request_mapping(path="/{id:\d+}/off", method="POST", auth_required=auth)
async def http_off(self, request) -> web.Response: async def http_off(self, request) -> web.Response:
""" """
:param request:
:return: ---
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']) id = int(request.match_info['id'])
await self.cbpi.bus.fire(topic="actor/%s/off" % id, id=id) await self.cbpi.bus.fire(topic="actor/%s/off" % id, id=id)
return web.Response(status=204) return web.Response(status=204)
@request_mapping(path="/{id:\d+}/toggle", auth_required=auth) @request_mapping(path="/{id:\d+}/toggle", method="POST", auth_required=auth)
async def http_toggle(self, request) -> web.Response: async def http_toggle(self, request) -> web.Response:
""" """
:param request:
:return: ---
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']) id = int(request.match_info['id'])
@ -79,13 +262,12 @@ class ActorController(ActorHttp, CRUDController):
await super(ActorController, self).init() await super(ActorController, self).init()
for id, value in self.cache.items(): for id, value in self.cache.items():
await self._init_actor(value) await self._init_actor(value)
async def _init_actor(self, actor): async def _init_actor(self, actor):
print("INIT ACXTOR")
if actor.type in self.types: if actor.type in self.types:
print("INIT ONE ACTOT")
cfg = actor.config.copy() cfg = actor.config.copy()
cfg.update(dict(cbpi=self.cbpi, id=id, name=actor.name)) cfg.update(dict(cbpi=self.cbpi, id=id, name=actor.name))
clazz = self.types[actor.type]["class"]; clazz = self.types[actor.type]["class"];

View file

@ -3,6 +3,7 @@ import os
from aiohttp import web from aiohttp import web
from cbpi_api import request_mapping from cbpi_api import request_mapping
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 ConfigModel from core.database.model import ConfigModel
@ -13,8 +14,19 @@ class ConfigHTTPController():
@request_mapping(path="/{name}/", method="POST", auth_required=False) @request_mapping(path="/{name}/", method="POST", auth_required=False)
async def http_post(self, request) -> web.Response: async def http_post(self, request) -> web.Response:
""" """
:param request: ---
:return: 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'] name = request.match_info['name']
data = await request.json() data = await request.json()
@ -25,11 +37,39 @@ class ConfigHTTPController():
@request_mapping(path="/", auth_required=False) @request_mapping(path="/", auth_required=False)
async def http_get_all(self, request) -> web.Response: async def http_get_all(self, request) -> web.Response:
""" """
:param request: ---
:return: description: Get all config parameters
tags:
- Config
responses:
"200":
description: successful operation
""" """
return web.json_response(self.cache, dumps=json_dumps) 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(ConfigHTTPController):
''' '''

View file

@ -138,12 +138,10 @@ class CRUDController(metaclass=ABCMeta):
await self._post_delete_callback(id) await self._post_delete_callback(id)
try: try:
if self.caching is True: if self.caching is True:
del self.cache[int(id)] del self.cache[int(id)]
except Exception as e: except Exception as e:
pass pass
pprint.pprint(self.cache)
await self.cbpi.bus.fire(topic="actor/%s/deleted" % id, id=id) await self.cbpi.bus.fire(topic="actor/%s/deleted" % id, id=id)
async def delete_all(self): async def delete_all(self):

View file

@ -1,6 +1,9 @@
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__)

View file

@ -1,39 +1,54 @@
import re import re
from aiohttp import web from aiohttp import web
from cbpi_api import * from cbpi_api import *
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.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 import json_dumps
class KettleHttp(HttpAPI): class KettleHttp(HttpAPI):
@request_mapping(path="/types", auth_required=False)
async def get_types(self, request):
web.json_response(data=self.cbpi.kettle.types, dumps=json_dumps)
@request_mapping(path="/{id:\d+}/automatic", auth_required=False) @request_mapping(path="/{id:\d+}/automatic", auth_required=False)
async def start2(self, request): async def http_automatic(self, request):
id = int(request.match_info['id']) await self.cbpi.kettle.toggle_automtic(int(request.match_info['id']))
result = await self.cbpi.kettle.toggle_automtic(id) return web.Response(status=204)
if result[0] is True:
return web.Response(text="OK") @request_mapping(path="/{id:\d+}/heater/on", auth_required=False)
else: async def http_heater_on(self, request):
return web.Response(status=404, text=result[1]) 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))
@request_mapping(path="/{id:\d+}/heater", auth_required=False)
async def start(self, request):
id = int(request.match_info['id'])
result = await self.cbpi.kettle.heater_on(id)
if result[0] is True:
return web.Response(text="OK")
else:
return web.Response(status=404, text=result[1])
class KettleController(CRUDController, KettleHttp): class KettleController(CRUDController, KettleHttp):
''' '''
@ -47,9 +62,6 @@ class KettleController(CRUDController, KettleHttp):
self.types = {} self.types = {}
self.cbpi.register(self, "/kettle") self.cbpi.register(self, "/kettle")
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
@ -68,12 +80,11 @@ class KettleController(CRUDController, KettleHttp):
''' '''
kettle = await self.get_one(id) kettle = await self.get_one(id)
if kettle is None: if kettle is None:
return (False, "Kettle Not Found") raise KettleException("Kettle not found")
if kettle.logic is None: if kettle.logic is None:
return (False, "No Logic defined") raise CBPiExtension("Logic not found for kettle id: %s" % id)
id = kettle.heater
await self.cbpi.bus.fire(topic="kettle/%s/automatic" % id, id=id) await self.cbpi.bus.fire(topic="kettle/%s/automatic" % id, id=id)
return (True, "Logic switched on switched")
@on_event(topic="job/done") @on_event(topic="job/done")
async def job_stop(self, key, **kwargs) -> None: async def job_stop(self, key, **kwargs) -> None:
@ -84,8 +95,6 @@ class KettleController(CRUDController, KettleHttp):
kettle = self.cache[int(kid)] kettle = self.cache[int(kid)]
kettle.instance = None kettle.instance = None
@on_event(topic="kettle/+/automatic") @on_event(topic="kettle/+/automatic")
async def handle_automtic_event(self, id, **kwargs): async def handle_automtic_event(self, id, **kwargs):
@ -112,16 +121,14 @@ class KettleController(CRUDController, KettleHttp):
cfg.update(dict(cbpi=self.cbpi)) cfg.update(dict(cbpi=self.cbpi))
kettle.instance = clazz(**cfg) kettle.instance = clazz(**cfg)
await self.cbpi.job.start_job(kettle.instance.run(), "Kettle_logic_%s" % kettle.id, "kettle_logic%s"%id) await self.cbpi.job.start_job(kettle.instance.run(), "Kettle_logic_%s" % kettle.id, "kettle_logic%s" % id)
else: else:
kettle.instance.running = False kettle.instance.running = False
kettle.instance = None kettle.instance = None
def _is_logic_running(self, kettle_id): def _is_logic_running(self, kettle_id):
scheduler = get_scheduler_from_app(self.cbpi.app) scheduler = get_scheduler_from_app(self.cbpi.app)
async def heater_on(self, id): async def heater_on(self, id):
''' '''
Convenience Method to switch the heater of a kettle on Convenience Method to switch the heater of a kettle on
@ -132,12 +139,11 @@ class KettleController(CRUDController, KettleHttp):
''' '''
kettle = await self.get_one(id) kettle = await self.get_one(id)
if kettle is None: if kettle is None:
return (False, "Kettle Not Found") raise KettleException("Kettle not found")
if kettle.heater is None: if kettle.sensor is None:
return (False, "No Heater defined") raise ActorException("Actor not defined for kettle id %s" % id)
id = kettle.heater id = kettle.heater
await self.cbpi.bus.fire(topic="actor/%s/on" % id, id=id, power=99) await self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
return (True,"Heater switched on")
async def heater_off(self, id): async def heater_off(self, id):
''' '''
@ -149,23 +155,44 @@ class KettleController(CRUDController, KettleHttp):
''' '''
kettle = await self.get_one(id) kettle = await self.get_one(id)
if kettle is None: if kettle is None:
return (False, "Kettle Not Found") raise KettleException("Kettle not found")
if kettle.heater is None: if kettle.sensor is None:
return (False, "No Heater defined") raise ActorException("Actor not defined for kettle id %s" % id)
id = kettle.heater id = kettle.heater
await self.cbpi.bus.fire(topic="actor/%s/off" % id, id=id, power=99) await self.cbpi.bus.fire(topic="actor/%s/switch/off" % id, id=id, power=99)
return (True, "Heater switched off")
async def agitator_on(self, id): async def agitator_on(self, id):
pass kettle = await self.get_one(id)
if kettle is None:
raise KettleException("Kettle not found")
if kettle.sensor is None:
raise ActorException("Actor not defined for kettle id %s" % id)
agitator_id = kettle.agitator
await self.cbpi.bus.fire(topic="actor/%s/switch/on" % agitator_id, id=agitator_id, power=99)
async def agitator_off(self, id): async def agitator_off(self, id):
pass kettle = await self.get_one(id)
if kettle is None:
raise KettleException("Kettle not found")
if kettle.sensor is None:
raise ActorException("Actor not defined for kettle id %s" % id)
agitator_id = kettle.agitator
await self.cbpi.bus.fire(topic="actor/%s/switch/off" % agitator_id, 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)
if kettle is None:
raise KettleException("Kettle Not Found")
return kettle.target_temp return kettle.target_temp
async def get_temp(self, id): async def get_temp(self, id):
pass kettle = await self.get_one(id)
if kettle is None:
raise KettleException("Kettle Not Found")
if kettle.sensor is None:
raise SensorException("Sensor not defined for kettle id %s" % id)
sensor_id = kettle.sensor
return await self.cbpi.sensor.get_value(sensor_id)

View file

@ -1,6 +1,8 @@
import json import json
import logging import logging
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.http_endpoints.http_api import HttpAPI
@ -21,9 +23,137 @@ class SensorController(CRUDController, HttpAPI):
self.sensors = {} self.sensors = {}
def info(self): def info(self):
return json.dumps(dict(name="SensorController", types=self.types), cls=ComplexEncoder) 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
@ -31,19 +161,51 @@ class SensorController(CRUDController, HttpAPI):
: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():
if value.type in self.types: await self.init_sensor(value)
cfg = value.config.copy()
cfg.update(dict(cbpi=self.cbpi, id=id, name=value.name))
clazz = self.types[value.type]["class"];
self.cache[id].instance = clazz(**cfg)
scheduler = get_scheduler_from_app(self.cbpi.app)
self.cache[id].instance.job = await scheduler.spawn(self.cache[id].instance.run(self.cbpi), value.name, "sensor")
else:
self.logger.error("Sensor type '%s' not found (Available Sensor Types: %s)" % (value.type, ', '.join(self.types.keys())))
async def get_value(self, id): async def init_sensor(self, sensor):
return self.cache[id].instance.value if sensor.type in self.types:
cfg = sensor.config.copy()
cfg.update(dict(cbpi=self.cbpi, id=sensor.id, name=sensor.name))
clazz = self.types[sensor.type]["class"];
self.cache[sensor.id].instance = clazz(**cfg)
self.cache[sensor.id].instance.init()
scheduler = get_scheduler_from_app(self.cbpi.app)
self.cache[sensor.id].instance.job = await scheduler.spawn(self.cache[sensor.id].instance.run(self.cbpi), sensor.name, "sensor")
else:
self.logger.error("Sensor type '%s' not found (Available Sensor Types: %s)" % (sensor.type, ', '.join(self.types.keys())))
async def stop_sensor(self, sensor):
print("STOP", sensor.id)
sensor.instance.stop()
await self.cbpi.bus.fire(topic="sensor/%s/stopped" % sensor.id, id=sensor.id)
async def get_value(self, sensor_id):
sensor_id = int(sensor_id)
return self.cache[sensor_id].instance.value
async def _post_add_callback(self, m):
'''
:param m:
:return:
'''
await self.init_sensor(m)
pass
async def _pre_delete_callback(self, sensor_id):
if int(sensor_id) not in self.cache:
return
if self.cache[int(sensor_id)].instance is not None:
await self.stop_sensor(self.cache[int(sensor_id)])
async def _pre_update_callback(self, sensor):
if sensor.instance is not None:
await self.stop_sensor(sensor)
async def _post_update_callback(self, sensor):
self.init_sensor(sensor)

View file

@ -1,21 +1,238 @@
import asyncio import asyncio
import time import time
from aiohttp import web 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 from core.http_endpoints.http_api import HttpAPI
from core.job.aiohttp import get_scheduler_from_app
class StepController(HttpAPI, CRUDController): class StepHttpAPI(HttpAPI):
@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.
''' '''
model = StepModel model = StepModel
def __init__(self, cbpi): def __init__(self, cbpi):
@ -24,12 +241,11 @@ class StepController(HttpAPI, CRUDController):
self.cbpi = cbpi self.cbpi = cbpi
self.current_task = None self.current_task = None
self.types = {} self.types = {}
self.current_step = None self.current_step = None
self.current_job = None
self.cbpi.register(self, "/step") self.cbpi.register(self, "/step")
async def init(self): async def init(self):
''' '''
Initializer of the the Step Controller. Initializer of the the Step Controller.
@ -37,22 +253,15 @@ class StepController(HttpAPI, CRUDController):
''' '''
await super(StepController, self).init() await super(StepController, self).init()
await self.init_after_startup()
async def init_after_startup(self):
step = await self.model.get_by_state('A') step = await self.model.get_by_state('A')
# We have an active step # We have an active step
if step is not None: if step is not None:
# get the type # get the type
step_type = self.types.get(step.type) step_type = self.types.get(step.type)
if step_type is None: if step_type is None:
# step type not found. cant restart step # step type not found. cant restart step
return return
if step.stepstate is not None: if step.stepstate is not None:
@ -64,54 +273,7 @@ class StepController(HttpAPI, CRUDController):
self.current_step = step_type["class"](**cfg) self.current_step = step_type["class"](**cfg)
self.current_job = await self.cbpi.job.start_job(self.current_step.run(), step.name, "step") self.current_job = await self.cbpi.job.start_job(self.current_step.run(), step.name, "step")
@request_mapping(path="/action", auth_required=False)
async def http_action(self, request):
'''
HTTP Endpoint to call an action on the current step.
:param request: web requset
:return: web.Response(text="OK"
'''
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):
'''
HTTP Endpoint to start the brewing process.
:param request:
:return:
'''
await self.cbpi.bus.fire("step/start")
return web.Response(text="OK")
@request_mapping(path="/reset", auth_required=False)
async def http_reset(self, request):
'''
HTTP Endpoint to call reset on the current step.
:param request:
:return:
'''
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):
'''
HTTP Endpoint to start the next step. The current step will be stopped
:param request:
:return:
'''
await self.cbpi.bus.fire("step/next")
return web.Response(text="OK")
@on_event("step/action") @on_event("step/action")
async def handle_action(self, action, **kwargs): async def handle_action(self, action, **kwargs):
@ -139,54 +301,23 @@ class StepController(HttpAPI, CRUDController):
:return: None :return: None
''' '''
if self.current_step is not None: if self.current_step is not None:
self.current_step.next() self.current_step.next()
pass pass
@on_event("step/start")
async def handle_start(self, **kwargs):
'''
Event Handler for "step/start".
It starts the brewing process
:param kwargs:
:return: None
'''
await self.start()
@on_event("step/reset") @on_event("step/reset")
async def handle_reset(self, **kwargs): async def handle_reset(self, **kwargs):
''' '''
Event Handler for "step/reset". Event Handler for "step/reset".
Resets the current step Resets the current step
:param kwargs:
:return: None
'''
await self.model.reset_all_steps()
@on_event("step/stop")
async def handle_stop(self, **kwargs):
'''
Event Handler for "step/stop".
Stops the current step
:param kwargs: :param kwargs:
:return: None :return: None
''' '''
if self.current_step is not None: if self.current_step is not None:
self.current_step.stop() await self.stop()
self.is_stopping = True
for key, step in self.cache.items():
step.state = None
self.current_step = None
await self.model.reset_all_steps()
@on_event("job/step/done") @on_event("job/step/done")
@ -201,7 +332,6 @@ class StepController(HttpAPI, CRUDController):
:return: :return:
''' '''
if self.cbpi.shutdown: if self.cbpi.shutdown:
return return
@ -209,9 +339,10 @@ class StepController(HttpAPI, CRUDController):
step_id = self.current_step.id step_id = self.current_step.id
self.current_step = None self.current_step = None
await self.start() if self.is_stopping is not True:
await self.start()
self.is_stopping = False
def _get_manged_fields_as_array(self, type_cfg): def _get_manged_fields_as_array(self, type_cfg):
@ -221,7 +352,14 @@ class StepController(HttpAPI, CRUDController):
return result return result
async def start(self): def is_running(self):
if self.current_step is not None:
return True
else:
return False
@on_event("step/start")
async def start(self, future, **kwargs):
''' '''
Start the first step Start the first step
@ -236,8 +374,6 @@ class StepController(HttpAPI, CRUDController):
inactive = await self.model.get_by_state("I") inactive = await self.model.get_by_state("I")
active = await self.model.get_by_state("A") active = await self.model.get_by_state("A")
if active is not None: if active is not None:
active.state = 'D' active.state = 'D'
active.end = int(time.time()) active.end = int(time.time())
@ -259,5 +395,11 @@ class StepController(HttpAPI, CRUDController):
else: else:
await self.cbpi.bus.fire("step/berwing/finished") await self.cbpi.bus.fire("step/berwing/finished")
async def stop(self): future.set_result(True)
pass
@on_event("step/stop")
async def stop(self, **kwargs):
if self.current_job is not None:
self.is_stopping = True
await self.current_job.close()
await self.model.reset_all_steps()

View file

@ -7,9 +7,10 @@ from aiohttp_auth import auth
from aiohttp_session import session_middleware 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 controller.job_controller import JobController from controller.job_controller import JobController
from core.cbpiwebsocket import CBPiWebSocket 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
@ -26,19 +27,36 @@ from core.utils import *
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@web.middleware
async def error_middleware(request, handler):
try:
response = await handler(request)
if response.status != 404:
return response
message = response.message
except web.HTTPException as ex:
if ex.status != 404:
raise
message = ex.reason
except CBPiException as ex:
message = str(ex)
return web.json_response(status=500, data={'error': message})
return web.json_response({'error': message})
class CraftBeerPi(): class CraftBeerPi():
def __init__(self): def __init__(self):
self.static_config = load_config(os.path.join(os.path.dirname(__file__), '../config/config.yaml')) self.static_config = load_config(os.path.join(os.path.dirname(__file__), '../config/config.yaml'))
self.database_file = "./craftbeerpi.db"
logger.info("Init CraftBeerPI") logger.info("Init CraftBeerPI")
policy = auth.SessionTktAuthentication(urandom(32), 60, include_ip=True) policy = auth.SessionTktAuthentication(urandom(32), 60, include_ip=True)
middlewares = [web.normalize_path_middleware(), session_middleware(EncryptedCookieStorage(urandom(32))), auth.auth_middleware(policy)] middlewares = [web.normalize_path_middleware(), session_middleware(EncryptedCookieStorage(urandom(32))), auth.auth_middleware(policy), error_middleware]
self.app = web.Application(middlewares=middlewares) self.app = web.Application(middlewares=middlewares)
self._setup_shutdownhook() self._setup_shutdownhook()
self.initializer = [] self.initializer = []
self.bus = CBPiEventBus(self.app.loop, self) self.bus = CBPiEventBus(self.app.loop, self)
@ -97,7 +115,7 @@ class CraftBeerPi():
routes.append(web.post(method.__getattribute__("path"), method)) routes.append(web.post(method.__getattribute__("path"), method))
def add_get(): def add_get():
routes.append(web.get(method.__getattribute__("path"), method)) routes.append(web.get(method.__getattribute__("path"), method, allow_head=False))
def add_delete(): def add_delete():
routes.append(web.delete(path, method)) routes.append(web.delete(path, method))
@ -161,6 +179,17 @@ class CraftBeerPi():
f = Figlet(font='big') f = Figlet(font='big')
logger.info("\n%s" % f.renderText("%s %s" % (self.static_config.get("name"), self.static_config.get("version")))) logger.info("\n%s" % f.renderText("%s %s" % (self.static_config.get("name"), self.static_config.get("version"))))
def _setup_http_index(self):
async def http_index(request):
url = self.config.static.get("index_url")
if url is not None:
raise web.HTTPFound(url)
else:
return web.Response(text="Hello, world")
self.app.add_routes([web.get('/', http_index)])
async def init_serivces(self): async def init_serivces(self):
self._print_logo() self._print_logo()
@ -168,6 +197,8 @@ class CraftBeerPi():
await self.job.init() await self.job.init()
await DBModel.setup() await DBModel.setup()
await self.config.init() await self.config.init()
self._setup_http_index()
self.plugin.load_plugins() self.plugin.load_plugins()
self.plugin.load_plugins_from_evn() self.plugin.load_plugins_from_evn()
await self.sensor.init() await self.sensor.init()

View file

@ -34,7 +34,7 @@ class DBModel(object):
async with aiosqlite.connect(DATABASE_FILE) as db: async with aiosqlite.connect(DATABASE_FILE) as db:
assert isinstance(db, aiosqlite.Connection) assert isinstance(db, aiosqlite.Connection)
this_directory = os.path.dirname(__file__) this_directory = os.path.dirname(__file__)
qry = open(os.path.join(this_directory, '../sql/create_table_user.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 @classmethod

View file

@ -2,6 +2,8 @@ import asyncio
import inspect import inspect
import logging import logging
from cbpi_api.exceptions import CBPiException
class CBPiEventBus(object): class CBPiEventBus(object):
class Node(object): class Node(object):
@ -37,12 +39,15 @@ class CBPiEventBus(object):
else: else:
self.results[key] = CBPiEventBus.Result(None, False) self.results[key] = CBPiEventBus.Result(None, False)
def get(self, key):
r = self.results.get(key)
if r is None:
raise CBPiException("Event Key %s not found." % key)
return (r.result, r.timeout)
def register(self, topic, method, once=False): def register(self, topic, method, once=False):
if method in self.registry: if method in self.registry:
raise RuntimeError("Method %s already registerd. Please unregister first!" % method.__name__) raise RuntimeError("Method %s already registerd. Please unregister first!" % method.__name__)
self.logger.info("Topic %s", topic) self.logger.info("Topic %s", topic)
@ -151,7 +156,8 @@ class CBPiEventBus(object):
result = [] result = []
if node._content is not None: if node._content is not None:
for c in node._content: for c in node._content:
result.append(dict(topic=c.topic, method=c.method.__name__, path=c.method.__module__, once=c.once))
result.append(dict(topic=c.topic, supports_future=c.supports_future, method=c.method.__name__, path=c.method.__module__, once=c.once))
if node._children is not None: if node._children is not None:
for c in node._children: for c in node._children:

View file

@ -24,14 +24,14 @@ class CustomActor(CBPiActor):
def off(self): def off(self):
print("OFF")
# Code to swtich the actor off goes here # Code to swtich the actor off goes here
self.state = False self.state = False
def on(self, power=100): def on(self, power=100):
print("ON")
# Code to swtich the actor on goes here # Code to swtich the actor on goes here
self.state = True self.state = True

View file

@ -23,6 +23,10 @@ class CustomSensor(CBPiSensor):
''' '''
pass pass
def init(self):
super().init()
def state(self): def state(self):
super().state() super().state()
@ -33,7 +37,7 @@ class CustomSensor(CBPiSensor):
self.value = 0 self.value = 0
while True: while True:
await asyncio.sleep(self.interval) await asyncio.sleep(self.interval)
self.log_data(10)
self.value = self.value + 1 self.value = self.value + 1
await cbpi.bus.fire("sensor/%s" % self.id, value=self.value) await cbpi.bus.fire("sensor/%s" % self.id, value=self.value)

View file

@ -1,5 +1,6 @@
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
@ -8,103 +9,30 @@ class HttpAPI():
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
self.cbpi = cbpi self.cbpi = cbpi
@request_mapping(path="/types", auth_required=False)
async def get_types(self, request):
if self.types is not None:
return web.json_response(data=self.types, dumps=json_dumps)
else:
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):
"""
---
description: This end-point allow to test that service is up.
tags:
- REST API
produces:
- application/json
parameters:
- name: "id"
in: "path"
description: "ID of object to return"
required: true
type: "integer"
format: "int64"
responses:
"200":
description: successful operation. Return "pong" text
"405":
description: invalid HTTP Met
"""
return web.json_response(await self.get_all(force_db_update=True), dumps=json_dumps) return web.json_response(await self.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):
"""
---
description: This end-point allow to test that service is up.
tags:
- REST API
produces:
- application/json
parameters:
- name: "id"
in: "path"
description: "ID of object to return"
required: true
type: "integer"
format: "int64"
responses:
"200":
description: successful operation. Return "pong" text
"405":
description: invalid HTTP Method
"""
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.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):
"""
---
description: This end-point allow to test that service is up.
tags:
- REST API
produces:
- application/json
responses:
"200":
description: successful operation. Return "pong" text
"405":
description: invalid HTTP Method
"""
data = await request.json() data = await request.json()
obj = await self.add(**data) obj = await self.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):
"""
---
description: This end-point allow to test that service is up.
tags:
- REST API
produces:
- application/json
parameters:
- in: body
name: body
description: Created user object
required: false
schema:
type: object
properties:
id:
type: integer
format: int64
responses:
"200":
description: successful operation. Return "pong" text
"405":
description: invalid HTTP Method
"""
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.update(id, data)
@ -112,19 +40,6 @@ class HttpAPI():
@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):
"""
---
description: This end-point allow to test that service is up.
tags:
- REST API
produces:
- text/plain
responses:
"200":
description: successful operation. Return "pong" text
"405":
description: invalid HTTP Method
"""
id = request.match_info['id'] id = request.match_info['id']
await self.delete(id) await self.delete(int(id))
return web.Response(status=204) return web.Response(status=204)

View file

@ -10,7 +10,6 @@ class Login():
self.cbpi = cbpi self.cbpi = cbpi
self.cbpi.register(self) self.cbpi.register(self)
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")}
@request_mapping(path="/logout", name="Logout", method="GET", auth_required=True) @request_mapping(path="/logout", name="Logout", method="GET", auth_required=True)
@ -21,10 +20,8 @@ class Login():
@request_mapping(path="/login",name="Login", method="POST", auth_required=False) @request_mapping(path="/login",name="Login", method="POST", auth_required=False)
async def login_view(self, request): async def login_view(self, request):
print("TRY LOGIN")
params = await request.post() params = await request.post()
user = params.get('username', None) user = params.get('username', None)
password = params.get('password', None) password = params.get('password', None)
print("UUSEr", user, password, str(self.db[user])) print("UUSEr", user, password, str(self.db[user]))

View file

@ -0,0 +1,39 @@
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

Binary file not shown.

View file

@ -1,42 +0,0 @@
2018-11-04 12:52:49,171,1,WOOHO
2018-11-04 12:53:45,824,1,WOOHO
2018-11-04 12:53:46,827,1,WOOHO
2018-11-04 12:53:47,831,1,WOOHO
2018-11-04 12:54:14,070,1,WOOHO
2018-11-04 12:54:15,075,1,WOOHO
2018-11-04 12:54:16,079,1,WOOHO
2018-11-04 12:54:17,084,1,WOOHO
2018-11-04 12:54:18,087,1,WOOHO
2018-11-04 12:54:19,091,1,WOOHO
2018-11-04 12:54:20,094,1,WOOHO
2018-11-04 12:54:21,100,1,WOOHO
2018-11-04 12:54:22,105,1,WOOHO
2018-11-04 12:54:23,109,1,WOOHO
2018-11-04 12:54:24,111,1,WOOHO
2018-11-04 12:54:25,113,1,WOOHO
2018-11-04 12:54:26,117,1,WOOHO
2018-11-04 12:54:27,119,1,WOOHO
2018-11-04 12:54:28,124,1,WOOHO
2018-11-04 12:54:29,125,1,WOOHO
2018-11-04 12:54:30,131,1,WOOHO
2018-11-04 12:54:31,136,1,WOOHO
2018-11-04 12:54:32,140,1,WOOHO
2018-11-04 12:54:33,142,1,WOOHO
2018-11-04 12:54:34,144,1,WOOHO
2018-11-04 12:54:35,149,1,WOOHO
2018-11-04 12:54:36,153,1,WOOHO
2018-11-04 12:54:37,159,1,WOOHO
2018-11-04 12:54:38,164,1,WOOHO
2018-11-04 12:54:39,168,1,WOOHO
2018-11-04 12:54:40,172,1,WOOHO
2018-11-04 12:54:41,177,1,WOOHO
2018-11-04 12:54:42,182,1,WOOHO
2018-11-04 12:54:43,188,1,WOOHO
2018-11-04 12:54:44,194,1,WOOHO
2018-11-04 12:54:45,198,1,WOOHO
2018-11-04 12:55:12,657,1,WOOHO
2018-11-04 12:55:13,659,1,WOOHO
2018-11-04 12:55:14,662,1,WOOHO
2018-11-04 12:55:15,668,1,WOOHO
2018-11-04 12:55:16,672,1,WOOHO
2018-11-04 12:55:17,678,1,WOOHO

View file

@ -1,90 +0,0 @@
2018-11-04 01:01:28,031,1,WOOHO
2018-11-04 01:01:29,034,1,WOOHO
2018-11-04 01:01:30,038,1,WOOHO
2018-11-04 01:01:31,043,1,WOOHO
2018-11-04 01:01:32,050,1,WOOHO
2018-11-04 01:01:33,054,1,WOOHO
2018-11-04 01:01:34,057,1,WOOHO
2018-11-04 01:01:35,062,1,WOOHO
2018-11-04 01:01:36,065,1,WOOHO
2018-11-04 01:01:37,068,1,WOOHO
2018-11-04 01:01:38,071,1,WOOHO
2018-11-04 01:01:39,075,1,WOOHO
2018-11-04 01:01:40,080,1,WOOHO
2018-11-04 01:01:41,082,1,WOOHO
2018-11-04 01:01:42,086,1,WOOHO
2018-11-04 01:01:43,091,1,WOOHO
2018-11-04 01:01:44,095,1,WOOHO
2018-11-04 01:01:45,097,1,WOOHO
2018-11-04 01:01:46,101,1,WOOHO
2018-11-04 01:01:47,106,1,WOOHO
2018-11-04 01:01:48,112,1,WOOHO
2018-11-04 01:01:49,114,1,WOOHO
2018-11-04 01:01:50,119,1,WOOHO
2018-11-04 01:01:51,124,1,WOOHO
2018-11-04 01:01:52,132,1,WOOHO
2018-11-04 01:01:53,136,1,WOOHO
2018-11-04 01:01:54,139,1,WOOHO
2018-11-04 01:01:55,143,1,WOOHO
2018-11-04 01:01:56,146,1,WOOHO
2018-11-04 01:01:57,152,1,WOOHO
2018-11-04 01:01:58,156,1,WOOHO
2018-11-04 01:01:59,161,1,WOOHO
2018-11-04 01:02:00,165,1,WOOHO
2018-11-04 01:02:01,171,1,WOOHO
2018-11-04 01:02:02,172,1,WOOHO
2018-11-04 01:02:03,176,1,WOOHO
2018-11-04 01:02:04,182,1,WOOHO
2018-11-04 01:02:05,188,1,WOOHO
2018-11-04 01:02:06,189,1,WOOHO
2018-11-04 01:02:07,190,1,WOOHO
2018-11-04 01:02:08,196,1,WOOHO
2018-11-04 01:02:09,204,1,WOOHO
2018-11-04 01:02:10,207,1,WOOHO
2018-11-04 01:02:11,211,1,WOOHO
2018-11-04 01:02:12,214,1,WOOHO
2018-11-04 01:02:13,220,1,WOOHO
2018-11-04 01:02:14,225,1,WOOHO
2018-11-04 01:02:15,232,1,WOOHO
2018-11-04 01:02:16,236,1,WOOHO
2018-11-04 01:02:17,242,1,WOOHO
2018-11-04 01:02:18,246,1,WOOHO
2018-11-04 01:02:19,250,1,WOOHO
2018-11-04 01:02:20,256,1,WOOHO
2018-11-04 01:02:21,260,1,WOOHO
2018-11-04 01:02:24,816,1,WOOHO
2018-11-04 01:02:25,821,1,WOOHO
2018-11-04 01:02:26,827,1,WOOHO
2018-11-04 01:02:27,830,1,WOOHO
2018-11-04 01:02:28,833,1,WOOHO
2018-11-04 01:02:29,838,1,WOOHO
2018-11-04 01:02:30,842,1,WOOHO
2018-11-04 01:02:31,845,1,WOOHO
2018-11-04 01:02:32,851,1,WOOHO
2018-11-04 01:02:33,855,1,WOOHO
2018-11-04 01:02:34,859,1,WOOHO
2018-11-04 01:02:35,862,1,WOOHO
2018-11-04 01:02:36,865,1,WOOHO
2018-11-04 01:02:37,871,1,WOOHO
2018-11-04 01:02:38,878,1,WOOHO
2018-11-04 01:02:39,878,1,WOOHO
2018-11-04 01:02:40,881,1,WOOHO
2018-11-04 01:02:41,883,1,WOOHO
2018-11-04 01:02:42,888,1,WOOHO
2018-11-04 01:02:43,892,1,WOOHO
2018-11-04 01:02:44,896,1,WOOHO
2018-11-04 01:02:45,900,1,WOOHO
2018-11-04 01:02:46,906,1,WOOHO
2018-11-04 01:02:47,912,1,WOOHO
2018-11-04 01:02:48,915,1,WOOHO
2018-11-04 01:02:49,920,1,WOOHO
2018-11-04 01:02:50,924,1,WOOHO
2018-11-04 01:02:51,931,1,WOOHO
2018-11-04 01:02:52,936,1,WOOHO
2018-11-04 01:02:53,941,1,WOOHO
2018-11-04 01:02:54,946,1,WOOHO
2018-11-04 01:02:55,950,1,WOOHO
2018-11-04 01:02:56,956,1,WOOHO
2018-11-04 01:02:57,960,1,WOOHO
2018-11-04 01:02:58,964,1,WOOHO
2018-11-04 01:02:59,966,1,WOOHO

View file

@ -1,18 +0,0 @@
2018-11-04 01:08:19,659,1,WOOHO
2018-11-04 01:08:20,668,1,WOOHO
2018-11-04 01:08:21,673,1,WOOHO
2018-11-04 01:08:22,681,1,WOOHO
2018-11-04 01:08:23,684,1,WOOHO
2018-11-04 01:08:24,689,1,WOOHO
2018-11-04 01:08:25,693,1,WOOHO
2018-11-04 01:08:26,694,1,WOOHO
2018-11-04 01:08:27,699,1,WOOHO
2018-11-04 01:08:28,704,1,WOOHO
2018-11-04 01:08:29,708,1,WOOHO
2018-11-04 01:08:30,712,1,WOOHO
2018-11-04 01:08:31,718,1,WOOHO
2018-11-04 01:08:32,723,1,WOOHO
2018-11-04 01:08:36,712,1,WOOHO
2018-11-04 01:08:37,716,1,WOOHO
2018-11-04 01:08:38,721,1,WOOHO
2018-11-04 01:08:39,726,1,WOOHO

View file

@ -1,13 +0,0 @@
2018-11-04 01:10:29,274,1,WOOHO
2018-11-04 01:10:30,280,1,WOOHO
2018-11-04 01:10:31,282,1,WOOHO
2018-11-04 01:10:32,286,1,WOOHO
2018-11-04 01:10:33,288,1,WOOHO
2018-11-04 01:10:34,294,1,WOOHO
2018-11-04 01:10:35,299,1,WOOHO
2018-11-04 01:10:36,301,1,WOOHO
2018-11-04 01:10:37,306,1,WOOHO
2018-11-04 01:10:38,311,1,WOOHO
2018-11-04 01:10:39,316,1,WOOHO
2018-11-04 01:10:40,317,1,WOOHO
2018-11-04 01:10:41,319,1,WOOHO

View file

@ -1,32 +0,0 @@
2018-11-04 12:42:23,466,1,WOOHO
2018-11-04 12:42:24,473,1,WOOHO
2018-11-04 12:42:25,478,1,WOOHO
2018-11-04 12:42:58,803,1,WOOHO
2018-11-04 12:42:59,807,1,WOOHO
2018-11-04 12:43:00,811,1,WOOHO
2018-11-04 12:43:34,009,1,WOOHO
2018-11-04 12:43:35,013,1,WOOHO
2018-11-04 12:43:36,015,1,WOOHO
2018-11-04 12:43:37,018,1,WOOHO
2018-11-04 12:43:38,023,1,WOOHO
2018-11-04 12:43:39,024,1,WOOHO
2018-11-04 12:43:40,029,1,WOOHO
2018-11-04 12:43:41,035,1,WOOHO
2018-11-04 12:43:42,041,1,WOOHO
2018-11-04 12:43:43,046,1,WOOHO
2018-11-04 12:43:44,052,1,WOOHO
2018-11-04 12:43:45,058,1,WOOHO
2018-11-04 12:43:46,062,1,WOOHO
2018-11-04 12:43:47,065,1,WOOHO
2018-11-04 12:43:48,067,1,WOOHO
2018-11-04 12:43:49,073,1,WOOHO
2018-11-04 12:43:50,077,1,WOOHO
2018-11-04 12:43:51,080,1,WOOHO
2018-11-04 12:43:52,089,1,WOOHO
2018-11-04 12:43:53,093,1,WOOHO
2018-11-04 12:43:54,099,1,WOOHO
2018-11-04 12:43:55,103,1,WOOHO
2018-11-04 12:43:56,108,1,WOOHO
2018-11-04 12:43:57,113,1,WOOHO
2018-11-04 12:43:58,116,1,WOOHO
2018-11-04 12:43:59,120,1,WOOHO

View file

@ -1,16 +0,0 @@
2018-11-04 12:44:00,127,1,WOOHO
2018-11-04 12:44:01,137,1,WOOHO
2018-11-04 12:44:02,142,1,WOOHO
2018-11-04 12:44:03,144,1,WOOHO
2018-11-04 12:44:04,145,1,WOOHO
2018-11-04 12:44:05,151,1,WOOHO
2018-11-04 12:44:06,156,1,WOOHO
2018-11-04 12:44:07,161,1,WOOHO
2018-11-04 12:44:08,165,1,WOOHO
2018-11-04 12:44:12,379,1,WOOHO
2018-11-04 12:44:13,384,1,WOOHO
2018-11-04 12:44:14,390,1,WOOHO
2018-11-04 12:44:15,395,1,WOOHO
2018-11-04 12:44:43,461,1,WOOHO
2018-11-04 12:44:44,465,1,WOOHO
2018-11-04 12:44:45,467,1,WOOHO

49
logs/sensors/sensor_1.log Normal file
View file

@ -0,0 +1,49 @@
2019-01-02 00:44:06,10
2019-01-02 00:44:11,10
2019-01-02 00:44:16,10
2019-01-02 00:44:21,10
2019-01-02 00:44:26,10
2019-01-02 00:44:31,10
2019-01-02 00:44:36,10
2019-01-02 00:44:41,10
2019-01-02 00:44:46,10
2019-01-02 00:44:51,10
2019-01-02 00:44:56,10
2019-01-02 00:45:01,10
2019-01-02 00:45:06,10
2019-01-02 00:45:11,10
2019-01-02 00:45:16,10
2019-01-02 00:45:21,10
2019-01-02 00:45:26,10
2019-01-02 00:45:31,10
2019-01-02 00:45:36,10
2019-01-02 00:45:41,10
2019-01-02 00:45:46,10
2019-01-02 00:45:51,10
2019-01-02 00:45:56,10
2019-01-02 00:46:01,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

View file

@ -0,0 +1,86 @@
2019-01-02 00:36:56,10
2019-01-02 00:37:01,10
2019-01-02 00:37:06,10
2019-01-02 00:37:11,10
2019-01-02 00:37:16,10
2019-01-02 00:37:21,10
2019-01-02 00:37:26,10
2019-01-02 00:37:31,10
2019-01-02 00:37:36,10
2019-01-02 00:37:41,10
2019-01-02 00:37:46,10
2019-01-02 00:37:51,10
2019-01-02 00:37:56,10
2019-01-02 00:38:01,10
2019-01-02 00:38:06,10
2019-01-02 00:38:11,10
2019-01-02 00:38:16,10
2019-01-02 00:38:21,10
2019-01-02 00:38:26,10
2019-01-02 00:38:31,10
2019-01-02 00:38:36,10
2019-01-02 00:38:41,10
2019-01-02 00:38:46,10
2019-01-02 00:38:51,10
2019-01-02 00:38:56,10
2019-01-02 00:39:01,10
2019-01-02 00:39:06,10
2019-01-02 00:39:11,10
2019-01-02 00:39:16,10
2019-01-02 00:39:21,10
2019-01-02 00:39:26,10
2019-01-02 00:39:31,10
2019-01-02 00:39:36,10
2019-01-02 00:39:41,10
2019-01-02 00:39:46,10
2019-01-02 00:39:51,10
2019-01-02 00:39:56,10
2019-01-02 00:40:01,10
2019-01-02 00:40:06,10
2019-01-02 00:40:11,10
2019-01-02 00:40:16,10
2019-01-02 00:40:21,10
2019-01-02 00:40:26,10
2019-01-02 00:40:31,10
2019-01-02 00:40:36,10
2019-01-02 00:40:41,10
2019-01-02 00:40:46,10
2019-01-02 00:40:51,10
2019-01-02 00:40:56,10
2019-01-02 00:41:01,10
2019-01-02 00:41:06,10
2019-01-02 00:41:11,10
2019-01-02 00:41:16,10
2019-01-02 00:41:21,10
2019-01-02 00:41:26,10
2019-01-02 00:41:31,10
2019-01-02 00:41:36,10
2019-01-02 00:41:41,10
2019-01-02 00:41:46,10
2019-01-02 00:41:51,10
2019-01-02 00:41:56,10
2019-01-02 00:42:01,10
2019-01-02 00:42:06,10
2019-01-02 00:42:11,10
2019-01-02 00:42:16,10
2019-01-02 00:42:21,10
2019-01-02 00:42:26,10
2019-01-02 00:42:31,10
2019-01-02 00:42:36,10
2019-01-02 00:42:41,10
2019-01-02 00:42:46,10
2019-01-02 00:42:51,10
2019-01-02 00:42:56,10
2019-01-02 00:43:01,10
2019-01-02 00:43:06,10
2019-01-02 00:43:11,10
2019-01-02 00:43:16,10
2019-01-02 00:43:21,10
2019-01-02 00:43:26,10
2019-01-02 00:43:31,10
2019-01-02 00:43:36,10
2019-01-02 00:43:41,10
2019-01-02 00:43:46,10
2019-01-02 00:43:51,10
2019-01-02 00:43:56,10
2019-01-02 00:44:01,10

View file

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

View file

@ -0,0 +1,86 @@
2019-01-02 00:29:45,10
2019-01-02 00:29:50,10
2019-01-02 00:29:55,10
2019-01-02 00:30:00,10
2019-01-02 00:30:05,10
2019-01-02 00:30:10,10
2019-01-02 00:30:15,10
2019-01-02 00:30:20,10
2019-01-02 00:30:25,10
2019-01-02 00:30:30,10
2019-01-02 00:30:35,10
2019-01-02 00:30:40,10
2019-01-02 00:30:45,10
2019-01-02 00:30:50,10
2019-01-02 00:30:55,10
2019-01-02 00:31:00,10
2019-01-02 00:31:05,10
2019-01-02 00:31:10,10
2019-01-02 00:31:15,10
2019-01-02 00:31:20,10
2019-01-02 00:31:25,10
2019-01-02 00:31:30,10
2019-01-02 00:31:35,10
2019-01-02 00:31:40,10
2019-01-02 00:31:45,10
2019-01-02 00:31:50,10
2019-01-02 00:31:55,10
2019-01-02 00:32:00,10
2019-01-02 00:32:05,10
2019-01-02 00:32:10,10
2019-01-02 00:32:15,10
2019-01-02 00:32:20,10
2019-01-02 00:32:25,10
2019-01-02 00:32:30,10
2019-01-02 00:32:35,10
2019-01-02 00:32:40,10
2019-01-02 00:32:45,10
2019-01-02 00:32:51,10
2019-01-02 00:32:56,10
2019-01-02 00:33:01,10
2019-01-02 00:33:06,10
2019-01-02 00:33:11,10
2019-01-02 00:33:16,10
2019-01-02 00:33:21,10
2019-01-02 00:33:26,10
2019-01-02 00:33:31,10
2019-01-02 00:33:36,10
2019-01-02 00:33:41,10
2019-01-02 00:33:46,10
2019-01-02 00:33:51,10
2019-01-02 00:33:56,10
2019-01-02 00:34:01,10
2019-01-02 00:34:06,10
2019-01-02 00:34:11,10
2019-01-02 00:34:16,10
2019-01-02 00:34:21,10
2019-01-02 00:34:26,10
2019-01-02 00:34:31,10
2019-01-02 00:34:36,10
2019-01-02 00:34:41,10
2019-01-02 00:34:46,10
2019-01-02 00:34:51,10
2019-01-02 00:34:56,10
2019-01-02 00:35:01,10
2019-01-02 00:35:06,10
2019-01-02 00:35:11,10
2019-01-02 00:35:16,10
2019-01-02 00:35:21,10
2019-01-02 00:35:26,10
2019-01-02 00:35:31,10
2019-01-02 00:35:36,10
2019-01-02 00:35:41,10
2019-01-02 00:35:46,10
2019-01-02 00:35:51,10
2019-01-02 00:35:56,10
2019-01-02 00:36:01,10
2019-01-02 00:36:06,10
2019-01-02 00:36:11,10
2019-01-02 00:36:16,10
2019-01-02 00:36:21,10
2019-01-02 00:36:26,10
2019-01-02 00:36:31,10
2019-01-02 00:36:36,10
2019-01-02 00:36:41,10
2019-01-02 00:36:46,10
2019-01-02 00:36:51,10

View file

@ -0,0 +1,86 @@
2019-01-02 00:22:01,10
2019-01-02 00:22:06,10
2019-01-02 00:22:11,10
2019-01-02 00:22:16,10
2019-01-02 00:22:21,10
2019-01-02 00:22:26,10
2019-01-02 00:22:31,10
2019-01-02 00:22:36,10
2019-01-02 00:22:41,10
2019-01-02 00:22:46,10
2019-01-02 00:22:51,10
2019-01-02 00:23:30,10
2019-01-02 00:23:35,10
2019-01-02 00:23:40,10
2019-01-02 00:23:45,10
2019-01-02 00:23:50,10
2019-01-02 00:23:55,10
2019-01-02 00:24:00,10
2019-01-02 00:24:05,10
2019-01-02 00:24:10,10
2019-01-02 00:24:15,10
2019-01-02 00:24:20,10
2019-01-02 00:24:25,10
2019-01-02 00:24:30,10
2019-01-02 00:24:35,10
2019-01-02 00:24:40,10
2019-01-02 00:24:45,10
2019-01-02 00:24:50,10
2019-01-02 00:24:55,10
2019-01-02 00:25:00,10
2019-01-02 00:25:05,10
2019-01-02 00:25:10,10
2019-01-02 00:25:15,10
2019-01-02 00:25:20,10
2019-01-02 00:25:25,10
2019-01-02 00:25:30,10
2019-01-02 00:25:35,10
2019-01-02 00:25:40,10
2019-01-02 00:25:45,10
2019-01-02 00:25:50,10
2019-01-02 00:25:55,10
2019-01-02 00:26:00,10
2019-01-02 00:26:05,10
2019-01-02 00:26:10,10
2019-01-02 00:26:15,10
2019-01-02 00:26:20,10
2019-01-02 00:26:25,10
2019-01-02 00:26:30,10
2019-01-02 00:26:35,10
2019-01-02 00:26:40,10
2019-01-02 00:26:45,10
2019-01-02 00:26:50,10
2019-01-02 00:26:55,10
2019-01-02 00:27:00,10
2019-01-02 00:27:05,10
2019-01-02 00:27:10,10
2019-01-02 00:27:15,10
2019-01-02 00:27:20,10
2019-01-02 00:27:25,10
2019-01-02 00:27:30,10
2019-01-02 00:27:35,10
2019-01-02 00:27:40,10
2019-01-02 00:27:45,10
2019-01-02 00:27:50,10
2019-01-02 00:27:55,10
2019-01-02 00:28:00,10
2019-01-02 00:28:05,10
2019-01-02 00:28:10,10
2019-01-02 00:28:15,10
2019-01-02 00:28:20,10
2019-01-02 00:28:25,10
2019-01-02 00:28:30,10
2019-01-02 00:28:35,10
2019-01-02 00:28:40,10
2019-01-02 00:28:45,10
2019-01-02 00:28:50,10
2019-01-02 00:28:55,10
2019-01-02 00:29:00,10
2019-01-02 00:29:05,10
2019-01-02 00:29:10,10
2019-01-02 00:29:15,10
2019-01-02 00:29:20,10
2019-01-02 00:29:25,10
2019-01-02 00:29:30,10
2019-01-02 00:29:35,10
2019-01-02 00:29:40,10

View file

@ -0,0 +1,86 @@
2019-01-02 00:14:36,10
2019-01-02 00:14:41,10
2019-01-02 00:14:46,10
2019-01-02 00:14:51,10
2019-01-02 00:14:56,10
2019-01-02 00:15:01,10
2019-01-02 00:15:06,10
2019-01-02 00:15:11,10
2019-01-02 00:15:16,10
2019-01-02 00:15:21,10
2019-01-02 00:15:26,10
2019-01-02 00:15:31,10
2019-01-02 00:15:36,10
2019-01-02 00:15:41,10
2019-01-02 00:15:46,10
2019-01-02 00:15:51,10
2019-01-02 00:15:56,10
2019-01-02 00:16:01,10
2019-01-02 00:16:06,10
2019-01-02 00:16:11,10
2019-01-02 00:16:16,10
2019-01-02 00:16:21,10
2019-01-02 00:16:26,10
2019-01-02 00:16:31,10
2019-01-02 00:16:36,10
2019-01-02 00:16:41,10
2019-01-02 00:16:46,10
2019-01-02 00:16:51,10
2019-01-02 00:16:56,10
2019-01-02 00:17:04,10
2019-01-02 00:17:09,10
2019-01-02 00:17:14,10
2019-01-02 00:17:19,10
2019-01-02 00:17:24,10
2019-01-02 00:17:29,10
2019-01-02 00:17:34,10
2019-01-02 00:17:45,10
2019-01-02 00:17:50,10
2019-01-02 00:17:55,10
2019-01-02 00:18:00,10
2019-01-02 00:18:05,10
2019-01-02 00:18:10,10
2019-01-02 00:18:15,10
2019-01-02 00:18:20,10
2019-01-02 00:18:25,10
2019-01-02 00:18:30,10
2019-01-02 00:18:35,10
2019-01-02 00:18:40,10
2019-01-02 00:18:45,10
2019-01-02 00:18:50,10
2019-01-02 00:18:55,10
2019-01-02 00:19:00,10
2019-01-02 00:19:05,10
2019-01-02 00:19:10,10
2019-01-02 00:19:15,10
2019-01-02 00:19:20,10
2019-01-02 00:19:25,10
2019-01-02 00:19:30,10
2019-01-02 00:19:35,10
2019-01-02 00:19:40,10
2019-01-02 00:19:51,10
2019-01-02 00:19:56,10
2019-01-02 00:20:01,10
2019-01-02 00:20:06,10
2019-01-02 00:20:11,10
2019-01-02 00:20:16,10
2019-01-02 00:20:21,10
2019-01-02 00:20:26,10
2019-01-02 00:20:31,10
2019-01-02 00:20:36,10
2019-01-02 00:20:41,10
2019-01-02 00:20:46,10
2019-01-02 00:20:51,10
2019-01-02 00:20:56,10
2019-01-02 00:21:01,10
2019-01-02 00:21:06,10
2019-01-02 00:21:11,10
2019-01-02 00:21:16,10
2019-01-02 00:21:21,10
2019-01-02 00:21:26,10
2019-01-02 00:21:31,10
2019-01-02 00:21:36,10
2019-01-02 00:21:41,10
2019-01-02 00:21:46,10
2019-01-02 00:21:51,10
2019-01-02 00:21:56,10

View file

@ -0,0 +1,86 @@
2019-01-02 00:07:03,10
2019-01-02 00:07:08,10
2019-01-02 00:07:13,10
2019-01-02 00:07:18,10
2019-01-02 00:07:23,10
2019-01-02 00:07:28,10
2019-01-02 00:07:33,10
2019-01-02 00:07:38,10
2019-01-02 00:07:43,10
2019-01-02 00:07:48,10
2019-01-02 00:07:53,10
2019-01-02 00:07:58,10
2019-01-02 00:08:03,10
2019-01-02 00:08:08,10
2019-01-02 00:08:13,10
2019-01-02 00:08:18,10
2019-01-02 00:08:23,10
2019-01-02 00:08:28,10
2019-01-02 00:08:33,10
2019-01-02 00:08:38,10
2019-01-02 00:08:43,10
2019-01-02 00:08:48,10
2019-01-02 00:08:53,10
2019-01-02 00:08:58,10
2019-01-02 00:09:03,10
2019-01-02 00:09:08,10
2019-01-02 00:09:13,10
2019-01-02 00:09:18,10
2019-01-02 00:09:23,10
2019-01-02 00:09:28,10
2019-01-02 00:09:33,10
2019-01-02 00:09:38,10
2019-01-02 00:09:43,10
2019-01-02 00:09:48,10
2019-01-02 00:09:53,10
2019-01-02 00:09:58,10
2019-01-02 00:10:03,10
2019-01-02 00:10:08,10
2019-01-02 00:10:13,10
2019-01-02 00:10:18,10
2019-01-02 00:10:23,10
2019-01-02 00:10:28,10
2019-01-02 00:10:33,10
2019-01-02 00:10:38,10
2019-01-02 00:10:43,10
2019-01-02 00:10:48,10
2019-01-02 00:10:53,10
2019-01-02 00:10:58,10
2019-01-02 00:11:03,10
2019-01-02 00:11:08,10
2019-01-02 00:11:13,10
2019-01-02 00:11:18,10
2019-01-02 00:11:23,10
2019-01-02 00:11:28,10
2019-01-02 00:11:33,10
2019-01-02 00:11:38,10
2019-01-02 00:11:43,10
2019-01-02 00:11:48,10
2019-01-02 00:11:53,10
2019-01-02 00:11:58,10
2019-01-02 00:12:03,10
2019-01-02 00:12:08,10
2019-01-02 00:12:13,10
2019-01-02 00:12:18,10
2019-01-02 00:12:23,10
2019-01-02 00:12:28,10
2019-01-02 00:12:33,10
2019-01-02 00:12:38,10
2019-01-02 00:12:43,10
2019-01-02 00:12:48,10
2019-01-02 00:12:53,10
2019-01-02 00:12:58,10
2019-01-02 00:13:03,10
2019-01-02 00:13:08,10
2019-01-02 00:13:13,10
2019-01-02 00:13:18,10
2019-01-02 00:13:23,10
2019-01-02 00:13:28,10
2019-01-02 00:13:33,10
2019-01-02 00:13:38,10
2019-01-02 00:13:43,10
2019-01-02 00:13:48,10
2019-01-02 00:13:53,10
2019-01-02 00:14:19,10
2019-01-02 00:14:24,10
2019-01-02 00:14:31,10

View file

@ -0,0 +1,86 @@
2019-01-01 23:59:47,10
2019-01-01 23:59:52,10
2019-01-01 23:59:57,10
2019-01-02 00:00:02,10
2019-01-02 00:00:07,10
2019-01-02 00:00:12,10
2019-01-02 00:00:17,10
2019-01-02 00:00:22,10
2019-01-02 00:00:27,10
2019-01-02 00:00:32,10
2019-01-02 00:00:37,10
2019-01-02 00:00:42,10
2019-01-02 00:00:47,10
2019-01-02 00:00:52,10
2019-01-02 00:00:57,10
2019-01-02 00:01:02,10
2019-01-02 00:01:07,10
2019-01-02 00:01:12,10
2019-01-02 00:01:17,10
2019-01-02 00:01:28,10
2019-01-02 00:01:33,10
2019-01-02 00:01:38,10
2019-01-02 00:01:43,10
2019-01-02 00:01:48,10
2019-01-02 00:01:53,10
2019-01-02 00:01:58,10
2019-01-02 00:02:03,10
2019-01-02 00:02:08,10
2019-01-02 00:02:13,10
2019-01-02 00:02:18,10
2019-01-02 00:02:23,10
2019-01-02 00:02:28,10
2019-01-02 00:02:33,10
2019-01-02 00:02:38,10
2019-01-02 00:02:43,10
2019-01-02 00:02:48,10
2019-01-02 00:02:53,10
2019-01-02 00:02:58,10
2019-01-02 00:03:03,10
2019-01-02 00:03:08,10
2019-01-02 00:03:13,10
2019-01-02 00:03:18,10
2019-01-02 00:03:23,10
2019-01-02 00:03:28,10
2019-01-02 00:03:33,10
2019-01-02 00:03:38,10
2019-01-02 00:03:43,10
2019-01-02 00:03:48,10
2019-01-02 00:03:53,10
2019-01-02 00:03:58,10
2019-01-02 00:04:03,10
2019-01-02 00:04:08,10
2019-01-02 00:04:13,10
2019-01-02 00:04:18,10
2019-01-02 00:04:23,10
2019-01-02 00:04:28,10
2019-01-02 00:04:33,10
2019-01-02 00:04:38,10
2019-01-02 00:04:43,10
2019-01-02 00:04:48,10
2019-01-02 00:04:53,10
2019-01-02 00:04:58,10
2019-01-02 00:05:03,10
2019-01-02 00:05:08,10
2019-01-02 00:05:13,10
2019-01-02 00:05:18,10
2019-01-02 00:05:23,10
2019-01-02 00:05:28,10
2019-01-02 00:05:33,10
2019-01-02 00:05:38,10
2019-01-02 00:05:43,10
2019-01-02 00:05:48,10
2019-01-02 00:05:53,10
2019-01-02 00:05:58,10
2019-01-02 00:06:03,10
2019-01-02 00:06:08,10
2019-01-02 00:06:13,10
2019-01-02 00:06:18,10
2019-01-02 00:06:23,10
2019-01-02 00:06:28,10
2019-01-02 00:06:33,10
2019-01-02 00:06:38,10
2019-01-02 00:06:43,10
2019-01-02 00:06:48,10
2019-01-02 00:06:53,10
2019-01-02 00:06:58,10

View file

@ -0,0 +1,86 @@
2019-01-01 23:50:48,10
2019-01-01 23:50:53,10
2019-01-01 23:51:03,10
2019-01-01 23:51:08,10
2019-01-01 23:51:13,10
2019-01-01 23:51:18,10
2019-01-01 23:51:23,10
2019-01-01 23:51:28,10
2019-01-01 23:51:33,10
2019-01-01 23:51:38,10
2019-01-01 23:51:49,10
2019-01-01 23:51:54,10
2019-01-01 23:51:59,10
2019-01-01 23:52:04,10
2019-01-01 23:52:09,10
2019-01-01 23:52:14,10
2019-01-01 23:52:19,10
2019-01-01 23:52:24,10
2019-01-01 23:52:29,10
2019-01-01 23:52:34,10
2019-01-01 23:52:39,10
2019-01-01 23:52:44,10
2019-01-01 23:52:49,10
2019-01-01 23:52:54,10
2019-01-01 23:52:59,10
2019-01-01 23:53:04,10
2019-01-01 23:53:09,10
2019-01-01 23:53:14,10
2019-01-01 23:53:19,10
2019-01-01 23:53:24,10
2019-01-01 23:53:29,10
2019-01-01 23:53:34,10
2019-01-01 23:53:39,10
2019-01-01 23:53:44,10
2019-01-01 23:53:49,10
2019-01-01 23:53:54,10
2019-01-01 23:53:59,10
2019-01-01 23:54:04,10
2019-01-01 23:54:09,10
2019-01-01 23:54:14,10
2019-01-01 23:54:19,10
2019-01-01 23:54:24,10
2019-01-01 23:54:34,10
2019-01-01 23:54:39,10
2019-01-01 23:54:44,10
2019-01-01 23:54:49,10
2019-01-01 23:54:54,10
2019-01-01 23:54:59,10
2019-01-01 23:56:32,10
2019-01-01 23:56:37,10
2019-01-01 23:56:42,10
2019-01-01 23:56:47,10
2019-01-01 23:56:52,10
2019-01-01 23:56:57,10
2019-01-01 23:57:02,10
2019-01-01 23:57:07,10
2019-01-01 23:57:12,10
2019-01-01 23:57:17,10
2019-01-01 23:57:22,10
2019-01-01 23:57:27,10
2019-01-01 23:57:32,10
2019-01-01 23:57:37,10
2019-01-01 23:57:42,10
2019-01-01 23:57:47,10
2019-01-01 23:57:53,10
2019-01-01 23:57:58,10
2019-01-01 23:58:03,10
2019-01-01 23:58:12,10
2019-01-01 23:58:17,10
2019-01-01 23:58:22,10
2019-01-01 23:58:27,10
2019-01-01 23:58:32,10
2019-01-01 23:58:37,10
2019-01-01 23:58:42,10
2019-01-01 23:58:47,10
2019-01-01 23:58:52,10
2019-01-01 23:58:57,10
2019-01-01 23:59:02,10
2019-01-01 23:59:07,10
2019-01-01 23:59:12,10
2019-01-01 23:59:17,10
2019-01-01 23:59:22,10
2019-01-01 23:59:27,10
2019-01-01 23:59:32,10
2019-01-01 23:59:37,10
2019-01-01 23:59:42,10

View file

@ -0,0 +1,86 @@
2019-01-01 23:43:05,10
2019-01-01 23:43:10,10
2019-01-01 23:43:15,10
2019-01-01 23:43:20,10
2019-01-01 23:43:25,10
2019-01-01 23:43:30,10
2019-01-01 23:43:35,10
2019-01-01 23:43:40,10
2019-01-01 23:43:45,10
2019-01-01 23:43:50,10
2019-01-01 23:43:55,10
2019-01-01 23:44:02,10
2019-01-01 23:44:07,10
2019-01-01 23:44:12,10
2019-01-01 23:44:17,10
2019-01-01 23:44:22,10
2019-01-01 23:44:27,10
2019-01-01 23:44:32,10
2019-01-01 23:44:37,10
2019-01-01 23:44:42,10
2019-01-01 23:44:47,10
2019-01-01 23:44:52,10
2019-01-01 23:44:57,10
2019-01-01 23:45:02,10
2019-01-01 23:45:11,10
2019-01-01 23:45:16,10
2019-01-01 23:45:21,10
2019-01-01 23:45:26,10
2019-01-01 23:45:31,10
2019-01-01 23:45:36,10
2019-01-01 23:45:41,10
2019-01-01 23:45:46,10
2019-01-01 23:45:51,10
2019-01-01 23:45:56,10
2019-01-01 23:46:01,10
2019-01-01 23:46:06,10
2019-01-01 23:46:11,10
2019-01-01 23:46:16,10
2019-01-01 23:46:21,10
2019-01-01 23:46:26,10
2019-01-01 23:46:31,10
2019-01-01 23:46:36,10
2019-01-01 23:46:41,10
2019-01-01 23:46:46,10
2019-01-01 23:46:51,10
2019-01-01 23:46:56,10
2019-01-01 23:47:01,10
2019-01-01 23:47:06,10
2019-01-01 23:47:11,10
2019-01-01 23:47:16,10
2019-01-01 23:47:21,10
2019-01-01 23:47:26,10
2019-01-01 23:47:31,10
2019-01-01 23:47:36,10
2019-01-01 23:47:41,10
2019-01-01 23:47:46,10
2019-01-01 23:47:51,10
2019-01-01 23:47:56,10
2019-01-01 23:48:01,10
2019-01-01 23:48:06,10
2019-01-01 23:48:11,10
2019-01-01 23:48:16,10
2019-01-01 23:48:21,10
2019-01-01 23:48:26,10
2019-01-01 23:48:31,10
2019-01-01 23:48:36,10
2019-01-01 23:48:41,10
2019-01-01 23:48:46,10
2019-01-01 23:48:51,10
2019-01-01 23:48:56,10
2019-01-01 23:49:01,10
2019-01-01 23:49:21,10
2019-01-01 23:49:26,10
2019-01-01 23:49:31,10
2019-01-01 23:49:36,10
2019-01-01 23:49:41,10
2019-01-01 23:49:46,10
2019-01-01 23:49:51,10
2019-01-01 23:49:56,10
2019-01-01 23:50:01,10
2019-01-01 23:50:06,10
2019-01-01 23:50:11,10
2019-01-01 23:50:16,10
2019-01-01 23:50:21,10
2019-01-01 23:50:26,10
2019-01-01 23:50:43,10

View file

@ -0,0 +1,86 @@
2019-01-01 23:27:07,10
2019-01-01 23:27:12,10
2019-01-01 23:27:17,10
2019-01-01 23:27:22,10
2019-01-01 23:27:27,10
2019-01-01 23:27:32,10
2019-01-01 23:27:37,10
2019-01-01 23:27:42,10
2019-01-01 23:27:47,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

16
logs/sensors/sensor_2.log Normal file
View file

@ -0,0 +1,16 @@
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

191
main.py
View file

@ -1,191 +0,0 @@
import aiosqlite
from aiohttp import web
from aiohttp_swagger import *
from aiojobs.aiohttp import setup, spawn, get_scheduler_from_app
from core.matcher import MQTTMatcher
from hbmqtt.broker import Broker
from hbmqtt.client import MQTTClient
from hbmqtt.mqtt.constants import QOS_1
from core.cbpiwebsocket import websocket_handler
TEST_DB = "test.db"
c = MQTTClient()
import asyncio
matcher = MQTTMatcher()
config = {
'listeners': {
'default': {
'type': 'tcp',
'bind': '0.0.0.0:1885',
},
'my-ws-1': {
'bind': '0.0.0.0:8888',
'type': 'ws'
}
},
'sys_interval': 10,
'auth': {
'allow-anonymous': True,
}
}
broker = Broker(config, plugin_namespace="hbmqtt.test.plugins")
async def test2(name):
while True:
print(name)
await asyncio.sleep(1)
async def handle(request):
name = request.match_info.get('name', "Anonymous")
text = "Hello, " + name
return web.Response(text=text)
async def test_connection():
async with aiosqlite.connect(TEST_DB) as db:
assert isinstance(db, aiosqlite.Connection)
app = web.Application()
async def listen_to_redis(app):
while True:
await asyncio.sleep(1)
#for w in _ws:
# pass
# await w.send_str("HALLO")
# print(w)
async def myjob(app):
while True:
await asyncio.sleep(1)
def ok_msg(msg):
pass
def ok_msg1(msg):
pass
def ok_msg2(msg):
pass
mqtt_methods = {"test": ok_msg, "test/+/ab": ok_msg1, "test/+": ok_msg2}
async def on_message():
while True:
message = await c.deliver_message()
matched = False
packet = message.publish_packet
print(message.topic)
print(message.topic.split('/'))
data = packet.payload.data.decode("utf-8")
for callback in matcher.iter_match(message.topic):
callback(data)
matched = True
if matched == False:
print("NO HANDLER", data)
#for w in _ws:
# await w.send_str(data)
async def start_background_tasks(app):
app['redis_listener'] = app.loop.create_task(listen_to_redis(app))
async def start_broker(app):
await broker.start()
await c.connect('mqtt://localhost:1885')
for k, v in mqtt_methods.items():
print(k, v)
await c.subscribe([(k, QOS_1)])
matcher[k] = v
# await c.subscribe([('/test', QOS_1),('/hallo', QOS_1)])
await get_scheduler_from_app(app).spawn(on_message())
job = None
async def start_task(request):
global job
job = await spawn(request, myjob(app))
await test_connection()
return web.Response(text="OK")
async def stop_task(request):
await job.close()
return web.Response(text="OK")
async def stats(request):
s = get_scheduler_from_app(app)
return web.Response(text="%s" % s.active_count)
setup(app)
def start_bg(app, name, method):
print("HALLO111")
async def start(app):
app[name] = app.loop.create_task(method(name))
app.on_startup.append(start)
# start_bg(app, "test", test2)
# start_bg(app, "test2", test2)
#app.on_startup.append(start_background_tasks)
app.on_startup.append(start_broker)
app.add_routes([web.get('/', handle),
web.get('/stop', stop_task),
web.get('/start', start_task),
web.get('/stats', stats),
web.get('/ws', websocket_handler),
web.get('/{name}', handle)
])
setup_swagger(app)
web.run_app(app)

View file

@ -1,7 +0,0 @@
with open('./config/plugin_list.txt') as f:
required = f.read().splitlines()
print(required)

View file

@ -4,7 +4,7 @@ from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
from core.craftbeerpi import CraftBeerPi from core.craftbeerpi import CraftBeerPi
class MyAppTestCase(AioHTTPTestCase): class ActorTestCase(AioHTTPTestCase):
@ -16,7 +16,7 @@ class MyAppTestCase(AioHTTPTestCase):
@unittest_run_loop @unittest_run_loop
async def test_example(self): async def test_actor_switch(self):
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
@ -42,5 +42,34 @@ class MyAppTestCase(AioHTTPTestCase):
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
@unittest_run_loop
async def test_crud(self):
data = {
"name": "CustomActor",
"type": "CustomActor",
"config": {
"interval": 5
}
}
# Add new sensor
resp = await self.client.post(path="/actor/", json=data)
assert resp.status == 200
m = await resp.json()
sensor_id = m["id"]
# Get sensor
resp = await self.client.get(path="/actor/%s" % sensor_id)
assert resp.status == 200
m2 = await resp.json()
sensor_id = m2["id"]
# Update Sensor
resp = await self.client.put(path="/actor/%s" % sensor_id, json=m)
assert resp.status == 200
# # Delete Sensor
resp = await self.client.delete(path="/actor/%s" % sensor_id)
assert resp.status == 204

View file

@ -54,4 +54,4 @@ class ConfigTestCase(AioHTTPTestCase):
async def test_http_get(self): async def test_http_get(self):
resp = await self.client.request("GET", "/config/") resp = await self.client.request("GET", "/config/")
assert resp.status == 200 assert resp.status == 200
#print(await eresp.json())

View file

@ -19,7 +19,7 @@ class KettleTestCase(AioHTTPTestCase):
print(await resp.json()) print(await resp.json())
@unittest_run_loop @unittest_run_loop
async def test_add(self): async def test_crud(self):
data = { data = {
"name": "Test", "name": "Test",
"sensor": None, "sensor": None,
@ -33,22 +33,26 @@ class KettleTestCase(AioHTTPTestCase):
"target_temp": None "target_temp": None
} }
# Add new sensor
resp = await self.client.post(path="/kettle/", json=data) resp = await self.client.post(path="/kettle/", json=data)
assert resp.status == 200 assert resp.status == 200
''' m = await resp.json()
result = await self.cbpi.kettle.toggle_automtic(1) sensor_id = m["id"]
print("#### RESULT", result)
assert result[0] is True # Get sensor
print("FIRE") resp = await self.client.get(path="/kettle/%s" % sensor_id)
assert resp.status == 200
m2 = await resp.json()
sensor_id = m2["id"]
# Update Sensor
resp = await self.client.put(path="/kettle/%s" % sensor_id, json=m)
assert resp.status == 200
# # Delete Sensor
resp = await self.client.delete(path="/kettle/%s" % sensor_id)
assert resp.status == 204
await asyncio.sleep(1)
self.cbpi.bus.fire("actor/1/on", id=1)
await asyncio.sleep(5)
#assert await self.cbpi.kettle.toggle_automtic(1) is True
#assert await self.cbpi.kettle.toggle_automtic(99) is False
'''

47
tests/test_sensor.py Normal file
View file

@ -0,0 +1,47 @@
import asyncio
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop
from core.craftbeerpi import CraftBeerPi
class SensorTestCase(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": "CustomSensor",
"type": "CustomSensor",
"config": {
"interval": 1
}
}
# Add new sensor
resp = await self.client.post(path="/sensor/", json=data)
assert resp.status == 200
m = await resp.json()
sensor_id = m["id"]
# Get sensor
resp = await self.client.get(path="/sensor/%s"% sensor_id)
assert resp.status == 200
m2 = await resp.json()
sensor_id = m2["id"]
# Update Sensor
resp = await self.client.put(path="/sensor/%s" % sensor_id, json=m)
assert resp.status == 200
# # Delete Sensor
resp = await self.client.delete(path="/sensor/%s" % sensor_id)
assert resp.status == 204
await asyncio.sleep(5)