Commit 1254e606 authored by Kristian Tan's avatar Kristian Tan

Merge branch 'master' of github.com:KristianTan/IoTSmartMeter

parents a217470b 824b3aad
from .daily_usage import DailyUsage
\ No newline at end of file
from flask import Flask, render_template from flask import Flask, render_template
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from .daily_usage import DailyUsage
import os
from datetime import datetime, date, timedelta
# from daily_usage import DailyUsage
app = Flask(__name__) app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///energyUsage' os.environ['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///energyUsage'
db = SQLAlchemy(app) app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['SQLALCHEMY_DATABASE_URI']
SQLAlchemy.create_all() # To suppress warnings
db.create_all() app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
GPIO.setmode(GPIO.BCM) GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False) GPIO.setwarnings(False)
test = DailyUsage("12/11/2019", 5) db = SQLAlchemy(app)
db.session.add(test)
db.session.commit()
# TODO: Move this into daily_usage class file
class DailyUsage(db.Model):
__tablename__ = 'daily_usage'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
date = db.Column(db.DateTime, unique=True, nullable=False)
kwhUsed = db.Column(db.Float, unique=False)
def __init__(self, date, kwhUsed):
self.date = date
self.kwhUsed = kwhUsed
def __repr__(self):
return '<DailyUsage %r, %r, %r>' % (self.id, self.date, self.kwhUsed)
db.create_all()
# TODO: be able to query db by date
daily_total = 0
latest_entry = db.session.query(DailyUsage).order_by(DailyUsage.id.desc()).first()
if latest_entry:
latest_entry_date = date(latest_entry.date.year, latest_entry.date.month, latest_entry.date.day)
if latest_entry_date == datetime.today().date():
daily_total = format(latest_entry.kwhUsed, '.7f')
todays_cost = format(float(daily_total) * 0.1622, '0.5f')
# Create dictionary to store pin info # Create dictionary to store pin info
pins = { pins = {
25: {'name': 'Light', 'state': GPIO.LOW} 25: {'name': 'Light', 'state': GPIO.LOW, 'on_time': None, 'on_date': None, 'Wattage': 15}
} }
...@@ -35,40 +66,75 @@ def main(): ...@@ -35,40 +66,75 @@ def main():
# Set the template data for the HTML template # Set the template data for the HTML template
template_data = { template_data = {
'pins': pins 'pins': pins,
'daily_total': daily_total,
'todays_cost': todays_cost
} }
return render_template('main.html', **template_data) return render_template('main.html', **template_data)
@app.route("/<change_pin>") @app.route("/toggle/<change_pin>")
def toggle_pin(change_pin): def toggle_pin(change_pin):
# TODO: change_pin is somethimes favicon.co for some reason? Fix
if change_pin == 'favicon.ico':
pass
change_pin = int(change_pin) change_pin = int(change_pin)
device_name = pins[change_pin]['name'] device_name = pins[change_pin]['name']
# Toggle the selected pin # Toggle the selected pin
GPIO.output(change_pin, not GPIO.input(change_pin)) GPIO.output(change_pin, not GPIO.input(change_pin))
message = "Turned " + device_name
if GPIO.input(change_pin) == 0: if GPIO.input(change_pin) == 0:
message += " off." if pins[change_pin]['on_time'] is not None:
create_entry(change_pin)
else: else:
message += " on." pins[change_pin]['on_time'] = datetime.now()
pins[change_pin]['on_date'] = date.today()
for pin in pins: for pin in pins:
pins[pin]['state'] = GPIO.input(pin) pins[pin]['state'] = GPIO.input(pin)
latest_entry = db.session.query(DailyUsage).order_by(DailyUsage.id.desc()).first()
if latest_entry:
latest_entry_date = date(latest_entry.date.year, latest_entry.date.month, latest_entry.date.day)
if latest_entry_date == datetime.today().date():
daily_total = format(latest_entry.kwhUsed, '.7f')
else:
daily_total = 0
todays_cost = format(float(daily_total) * 0.1622, '0.5f')
template_data = { template_data = {
'message': message, 'pins': pins,
'pins': pins 'daily_total': daily_total,
'todays_cost': todays_cost
} }
return render_template('main.html', **template_data) return render_template('main.html', **template_data)
def create_entry(change_pin):
latest_entry = db.session.query(DailyUsage).order_by(DailyUsage.id.desc()).first()
start_time = pins[change_pin]['on_time']
# Get the elapsed time and strip away milliseconds
elapsed = int((datetime.now() - start_time).total_seconds())
start_date = pins[change_pin]['on_date']
# Formula to calculate kWh based on time and wattage
kwh = pins[change_pin]['Wattage'] * (elapsed / 3600) / 1000
# If there is already an entry for today, update on time
# if latest_entry:
if latest_entry:
latest_entry_date = date(latest_entry.date.year, latest_entry.date.month, latest_entry.date.day)
if latest_entry_date == start_date:
latest_entry.kwhUsed += kwh
else:
# If no entry for today, make one
entry = DailyUsage(date=start_date, kwhUsed=kwh)
db.session.add(entry)
db.session.commit()
pins[change_pin]['on_time'] = None
pins[change_pin]['on_date'] = None
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', port=8090) app.run(host='0.0.0.0', port=8090)
from .app import db from app import db
class DailyUsage(db.Model): class DailyUsage(db.Model):
...@@ -7,4 +7,4 @@ class DailyUsage(db.Model): ...@@ -7,4 +7,4 @@ class DailyUsage(db.Model):
hours = db.Column(db.Integer(120), unique=False) hours = db.Column(db.Integer(120), unique=False)
def __repr__(self): def __repr__(self):
return '<User %r>' % self.username return '<DailyUsage %r>' % self.id
\ No newline at end of file
...@@ -16,17 +16,14 @@ ...@@ -16,17 +16,14 @@
{% for pin in pins %} {% for pin in pins %}
<p>{{ pins[pin].name }} : <p>{{ pins[pin].name }} :
{% if pins[pin].state == true %} {% if pins[pin].state == true %}
(<a href="/{{pin}}">turn off</a>) (<a href="/toggle/{{pin}}">turn off</a>)
{% else %} {% else %}
(<a href="/{{pin}}">turn on</a>) (<a href="/toggle/{{pin}}">turn on</a>)
{% endif %} {% endif %}
</p> </p>
{% endfor %} {% endfor %}
{# {% if message %}#}
{# <h2>{{ message }}</h2>#}
{# {% endif %}#}
</div> </div>
<div class="smart_meter"> <div class="smart_meter">
...@@ -39,9 +36,9 @@ ...@@ -39,9 +36,9 @@
{% endfor %} {% endfor %}
</p> </p>
{# Implement some way to display "No devices" message if none are in use#} {# Implement some way to display "No devices" message if none are in use#}
<p> Used today:
</p> <p> Total energy used today: {{ daily_total }} kWh.</p>
<p> Total cost of today's energy usage: £{{ todays_cost }}</p>
</div> </div>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment