wip: separate clock and rest into separate apps.
This commit is contained in:
12
persistence/README.md
Normal file
12
persistence/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## What is happening here?
|
||||
|
||||
This "persistence"-module aims to standardize 2 things:
|
||||
* the creation of a common set of variables that survives a potential (let's face it, likely) crash
|
||||
* advanced logging and analytics
|
||||
|
||||
### Common variables
|
||||
These are saved as a json file and are handled internally as a dict. Each change in the dict triggers a write to the file.
|
||||
|
||||
|
||||
### Logging
|
||||
A chunky sqlite-db which periodically gets new entries. From all modules. Ideally this db is then visualized through grafana. WIP
|
29
persistence/models.py
Normal file
29
persistence/models.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from peewee import *
|
||||
|
||||
#db = SqliteDatabase('data.db')
|
||||
db = MySQLDatabase("AIO_sensors", host="192.168.1.101", port=3306, user="pi", passwd="supersecret")
|
||||
# whyyy?
|
||||
|
||||
class Metric(Model):
|
||||
time = DateTimeField()
|
||||
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
class SensorMetric(Metric):
|
||||
# this is a continuous metric
|
||||
temperature = IntegerField()
|
||||
humidity = IntegerField()
|
||||
luminosity = IntegerField()
|
||||
|
||||
|
||||
class ChatMetric(Metric):
|
||||
# this gets cumulated over one hour (or one day, or...)
|
||||
activity = CharField()
|
||||
|
||||
|
||||
class ErrorMetric(Metric):
|
||||
# same as above
|
||||
error = CharField()
|
||||
|
@@ -2,7 +2,6 @@ import json
|
||||
import os
|
||||
|
||||
|
||||
|
||||
class PersistentDict(dict):
|
||||
"""Extended dict that writes its content to a file every time a value is changed"""
|
||||
|
||||
@@ -32,6 +31,7 @@ class PersistentDict(dict):
|
||||
super().__setitem__(key, tmp[key])
|
||||
self.last_action = "r"
|
||||
|
||||
|
||||
## extended dictionary - logic
|
||||
def __setitem__(self, key, value):
|
||||
if self.last_action != "r":
|
||||
@@ -45,8 +45,8 @@ class PersistentDict(dict):
|
||||
self.read_dict()
|
||||
|
||||
ret_val = super().__getitem__(key)
|
||||
if type(ret_val) == dict:
|
||||
ret_val = HookedDict(key, self, ret_val)
|
||||
if type(ret_val) != int and type(ret_val) != str:
|
||||
ret_val = create_struct(type(ret_val), key, self, ret_val)
|
||||
|
||||
return ret_val
|
||||
|
||||
@@ -57,25 +57,31 @@ class PersistentDict(dict):
|
||||
|
||||
|
||||
|
||||
class HookedDict(dict):
|
||||
"""helper class to detect writes to a child-dictionary and triger a write in PersistentDict"""
|
||||
def create_struct(struct_type, own_name, parent_name, *args, **kwargs):
|
||||
class HookedStruct(struct_type):
|
||||
|
||||
def __init__(self, own_name, parent_dict, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.name = own_name
|
||||
self.parent = parent_dict
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super().__setitem__(key, value)
|
||||
self.parent.__setitem__(self.name, self)
|
||||
def __init__(self, own_name, parent_name, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.name = own_name
|
||||
self.parent = parent_name
|
||||
|
||||
def __setitem__(self, *args, **kwargs):
|
||||
super().__setitem__(*args, **kwargs)
|
||||
self.parent.__setitem__(self.name, self)
|
||||
|
||||
def __getitem__(self, key):
|
||||
ret_val = super().__getitem__(key)
|
||||
if type(ret_val) == dict:
|
||||
ret_val = HookedDict(key, self, ret_val)
|
||||
return ret_val
|
||||
|
||||
def pop(self, k, d=None):
|
||||
retvalue = super().pop(k, d)
|
||||
self.parent.__setitem__(self.name, self)
|
||||
return retvalue
|
||||
def __getitem__(self, *args, **kwargs):
|
||||
ret_val = super().__getitem__(*args, **kwargs)
|
||||
if type(ret_val) != int and type(ret_val) != str:
|
||||
ret_val = create_struct(type(ret_val), args[0], self, ret_val)
|
||||
return ret_val
|
||||
|
||||
def pop(self, *args):
|
||||
retvalue = super().pop(*args)
|
||||
self.parent.__setitem__(self.name, self)
|
||||
return retvalue
|
||||
|
||||
def append(self, *args):
|
||||
super().append(*args)
|
||||
self.parent.__setitem__(self.name, self)
|
||||
print(*args)
|
||||
return HookedStruct(own_name, parent_name, *args, **kwargs)
|
32
persistence/p_out.py
Normal file
32
persistence/p_out.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from models import db
|
||||
from models import *
|
||||
import datetime as dt
|
||||
from random import randint
|
||||
|
||||
|
||||
def create_tables():
|
||||
with db:
|
||||
db.create_tables([SensorMetric, ChatMetric, ErrorMetric])
|
||||
|
||||
|
||||
create_tables()
|
||||
# read from json, excel, txt ... whatever
|
||||
now = dt.datetime.timestamp(dt.datetime.now())
|
||||
|
||||
|
||||
for i in range(1000):
|
||||
with db:
|
||||
sensor_data = SensorMetric.create(
|
||||
time = now + i,
|
||||
temperature = 23,
|
||||
humidity = 30 + randint(0,20),
|
||||
luminosity = 1
|
||||
)
|
||||
chat = ChatMetric(
|
||||
time = now + i,
|
||||
activity = "Hello world"
|
||||
)
|
||||
errors = ErrorMetric(
|
||||
time = now + i,
|
||||
error = "Could not load module"
|
||||
)
|
Reference in New Issue
Block a user