Merged in POCONSOLE-62-Flask (pull request #1)

POCONSOLE-62 flask
This commit is contained in:
Patrick McDonagh
2016-11-04 22:43:36 +00:00
862 changed files with 57295 additions and 136541 deletions

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
'''
MySQL Tag Server
Sample Tag generator
Created on April 7, 2016
@author: Patrick McDonagh
@description: Continuously loops through a list of tags to store values from a PLC into a MySQL database
@@ -15,7 +15,7 @@ import requests
import json
# DEFAULTS
db_address = "10.10.10.10:3000"
db_address = "10.10.10.10:5000"
db_url = "https://{}".format(db_address)
scan_rate = 30 # seconds
save_all = "test" # use True, False, or any string
@@ -61,9 +61,8 @@ def main():
global db_address, scan_rate, save_all
try:
# Get tags stored in database
get_tag_request_data = {'where': '{"tag_class": 5}'}
get_tag_request = requests.get('{}/tag'.format(db_url), params=get_tag_request_data, verify=False)
tags = json.loads(get_tag_request.text)
get_tag_request = requests.get('{}/api/tags'.format(db_url), verify=False)
tags = json.loads(get_tag_request.text)['objects']
except Exception as e:
print("Error getting tags: {}".format(e))
time.sleep(10)
@@ -91,10 +90,9 @@ def main():
except Exception as e:
print("Error getting save-all: {}".format(e))
print("I'll just use {} as the save-all parameter...".format(save_all))
for t in tags:
# name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'):
tag_store[t['name']] = Sample(t['name'], t['tag'], t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'], db_address=db_address)
tag_store[t['name']] = Sample(t['name'], t['tag'], t['id'], t['data_type_id'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['device']['address'], db_address=db_address)
while True:
for tag in tag_store:

26
docker-compose.yml Normal file
View File

@@ -0,0 +1,26 @@
version : '2'
services:
web_db:
image: henrypump/logger/web_db
ports:
- "443:5000"
networks:
poconsole:
ipv4_address: 10.10.10.10
daq_sample:
image: henrypump/logger/daq_sample
networks:
- poconsole
depends_on:
- web_db
networks:
poconsole:
driver: bridge
driver_opts:
com.docker.network.enable_ipv4: "true"
ipam:
driver: default
config:
- subnet: 10.10.10.0/24

View File

@@ -1,23 +1,23 @@
FROM hypriot/rpi-node:latest
FROM patrickjmcd/rpi-python3:latest
RUN apt-get -y update && apt-get install -y apt-utils dialog vim git
RUN apt-get -y update
COPY mysql-install.sh /tmp/mysql-install.sh
COPY taglogger_db_structure.sql /tmp/taglogger_db_structure.sql
RUN chmod +x /tmp/mysql-install.sh && /tmp/mysql-install.sh
RUN mkdir /root/tag-logger
COPY www /root/tag-logger/www
COPY flask /root/tag-logger/flask
COPY mysql-connector-python-2.1.4 /tmp/mysql
RUN cd /tmp/mysql && python setup.py install && cd ~
COPY startup.sh /root/startup.sh
RUN chmod +x /root/startup.sh
RUN npm install -g bower pm2 sails --silent
RUN cd /root/tag-logger/www && npm install && bower install --allow-root && cd /
RUN pip install flask flask-restless flask-sqlalchemy pyopenssl
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN service mysql restart && python /root/tag-logger/flask/setupdb.py
CMD '/root/startup.sh'

View File

@@ -1,23 +1,23 @@
FROM node:latest
FROM python:latest
RUN apt-get -y update && apt-get install -y apt-utils dialog vim git
RUN apt-get -y update
COPY mysql-install.sh /tmp/mysql-install.sh
COPY taglogger_db_structure.sql /tmp/taglogger_db_structure.sql
RUN chmod +x /tmp/mysql-install.sh && /tmp/mysql-install.sh
RUN mkdir /root/tag-logger
COPY www /root/tag-logger/www
COPY flask /root/tag-logger/flask
COPY mysql-connector-python-2.1.4 /tmp/mysql
RUN cd /tmp/mysql && python setup.py install && cd ~
COPY startup.sh /root/startup.sh
RUN chmod +x /root/startup.sh
RUN npm install -g bower pm2 sails --silent
RUN cd /root/tag-logger/www && npm install && bower install --allow-root && cd /
RUN pip install flask flask-restless flask-sqlalchemy pyopenssl
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN service mysql restart && python /root/tag-logger/flask/setupdb.py
CMD '/root/startup.sh'

View File

@@ -0,0 +1,123 @@
# project/__init__.py
import os
from flask import Flask, render_template, request, session, send_from_directory, jsonify, url_for, flash, redirect, Response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.utils import secure_filename
from sqlalchemy import and_
import mysql.connector
UPLOAD_FOLDER = '/root/tag-server/flask/app/docs'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app = Flask('app', static_url_path='')
app.config.update(
DEBUG=True,
SQLALCHEMY_DATABASE_URI='mysql+mysqlconnector://website:henrypump@127.0.0.1/poconsole'
# SQLALCHEMY_DATABASE_URI='sqlite:///../database.db',
)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.secret_key = 'henry_pump'
db = SQLAlchemy(app)
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
return app.send_static_file('index.html')
from .datalogger import datalogger
from .datalogger.models import *
@app.route('/api/latest')
def get_latest_tag_vals():
res = db.engine.execute('SELECT v1.id as id, v1.created_on as dtime, t.id as t_id, t.name as name, t.tag as tag, v1.value as value, t.units as units, t.description as description, t.min_expected as min_expected, t.max_expected as max_expected FROM tag_vals v1 INNER JOIN tags t ON t.id = v1.tag_id WHERE v1.id = (SELECT v2.id FROM tag_vals v2 WHERE v2.tag_id = v1.tag_id ORDER BY v2.id DESC LIMIT 1) ORDER BY t.id')
lat = res.fetchall()
latest_tags = list(map(latest_to_obj, lat))
return jsonify(latest_tags)
@app.route('/api/valuesbetween/<string:ids>/<string:start>/<string:end>')
def get_tag_vals_between(ids, start, end):
ids = ids.split(',')
res = Tag_val.query.filter(and_(Tag_val.tag_id.in_(ids), Tag_val.created_on > start, Tag_val.created_on <= end)).all()
return jsonify([i.serialize for i in res])
@app.route('/api/multipletags/<string:ids>')
def get_multiple_tags(ids):
ids = ids.split(',')
res = Tag.query.filter(Tag.id.in_(ids)).all()
return jsonify([i.serialize for i in res])
@app.route('/doc/upload', methods=['POST'])
def upload_file():
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect("/#/docs")
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect("/#/docs")
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
d = Doc(name=filename)
db.session.add(d)
db.session.commit()
return redirect(url_for('uploaded_file',
filename=filename))
return redirect("/#/docs")
@app.route('/docs/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
@app.route('/csv/all')
def get_csv_all():
csv_string = "datetime,"
all_tags = [i.serialize for i in Tag.query.all()]
all_tag_names = [x['name'] for x in all_tags]
for x in all_tag_names:
csv_string += "{},".format(x)
csv_string += "\n"
all_vals = [i.serialize for i in Tag_val.query.all()]
val_objs = [{'value': x['value'], 'tag_name': x['tag']['name'], 'datetime': x['created_on']} for x in all_vals]
for v in val_objs:
tag_ind = all_tag_names.index(v['tag_name'])
csv_string += "{},".format(v['datetime']) + "," * tag_ind + "{},".format(v['value']) + "," * (len(all_tag_names) - tag_ind) + "\n"
return Response(
csv_string,
mimetype="text/csv",
headers={"Content-disposition":
"attachment; filename=datadump.csv"})
@app.route('/csv/<string:ids>')
def get_csv_selected(ids):
csv_string = "datetime,"
all_tags = [i.serialize for i in Tag.query.filter(Tag.id.in_(ids)).all()]
all_tag_names = [x['name'] for x in all_tags]
for x in all_tag_names:
csv_string += "{},".format(x)
csv_string += "\n"
all_vals = [i.serialize for i in Tag_val.query.filter(Tag_val.tag_id.in_(ids)).all()]
val_objs = [{'value': x['value'], 'tag_name': x['tag']['name'], 'datetime': x['created_on']} for x in all_vals]
for v in val_objs:
tag_ind = all_tag_names.index(v['tag_name'])
csv_string += "{},".format(v['datetime']) + "," * tag_ind + "{},".format(v['value']) + "," * (len(all_tag_names) - tag_ind) + "\n"
return Response(
csv_string,
mimetype="text/csv",
headers={"Content-disposition":
"attachment; filename=datadump{}.csv".format(ids.replace(",","-"))})

View File

@@ -0,0 +1 @@
pass

View File

@@ -0,0 +1,15 @@
from flask_restless import APIManager
from .models import *
from .. import app
manager = APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Config, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Data_type, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Device_type, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Device, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Doc, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Tag_class, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Tag, methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(Tag_val, methods=['GET', 'POST', 'DELETE'], allow_delete_many=True)

View File

@@ -0,0 +1,203 @@
from datetime import datetime
import json
from .. import db
class Config(db.Model):
__tablename__ = "configs"
id = db.Column(db.Integer, primary_key=True)
parameter = db.Column(db.String(100), unique=True)
val = db.Column(db.String(100), unique=True)
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"parameter": self.parameter,
"val": self.val,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Data_type(db.Model):
__tablename__ = "data_types"
id = db.Column(db.Integer, primary_key=True)
data_type = db.Column(db.String(32), unique=True)
plc_type = db.Column(db.String(32))
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"data_type": self.data_type,
"plc_type": self.plc_type,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Device_type(db.Model):
__tablename__ = "device_types"
id = db.Column(db.Integer, primary_key=True)
device_type = db.Column(db.String(64))
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"device_type": self.device_type,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Device(db.Model):
__tablename__ = "devices"
id = db.Column(db.Integer, primary_key=True)
device_type_id = db.Column(db.Integer, db.ForeignKey('device_types.id'))
device_type = db.relationship(Device_type, primaryjoin=device_type_id==Device_type.id)
address = db.Column(db.String(256))
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"device_type_id": self.device_type_id,
"device_type": self.device_type.serialize,
"address": self.address,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Doc(db.Model):
__tablename__ = "docs"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256))
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"name": self.name,
"location": self.location,
"description": self.description,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Tag_class(db.Model):
__tablename__ = "tag_classes"
id = db.Column(db.Integer, primary_key=True)
class_type = db.Column(db.String(64), unique=True)
description = db.Column(db.String(128))
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
def toJSON(self):
return json.dumps({'id': self.id, 'class_type': self.class_type, 'description': self.description, 'created_on': self.created_on, 'updated_on': self.updated_on})
@property
def serialize(self):
return {
"id": self.id,
"class_type": self.class_type,
"description": self.description,
"created_on": self.created_on,
"updated_on": self.updated_on,
}
class Tag(db.Model):
__tablename__ = "tags"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
tag_class_id = db.Column(db.Integer, db.ForeignKey('tag_classes.id'))
tag_class = db.relationship(Tag_class)
tag = db.Column(db.String(128))
device_id = db.Column(db.Integer, db.ForeignKey('devices.id'))
device = db.relationship(Device)
description = db.Column(db.String(64))
data_type_id = db.Column(db.Integer, db.ForeignKey('data_types.id'))
data_type = db.relationship(Data_type)
change_threshold = db.Column(db.Float)
guarantee_sec = db.Column(db.Integer)
map_function = db.Column(db.String(64))
units = db.Column(db.String(10))
min_expected = db.Column(db.Float)
max_expected = db.Column(db.Float)
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"name": self.name,
"tag_class_id": self.tag_class_id,
"tag_class": self.tag_class.serialize,
"tag": self.tag,
"device_id": self.device_id,
"device": self.device.serialize,
"description": self.description,
"data_type_id": self.data_type_id,
"data_type": self.data_type.serialize,
"change_threshold": self.change_threshold,
"guarantee_sec": self.guarantee_sec,
"map_function": self.map_function,
"units": self.units,
"min_expected": self.min_expected,
"max_expected": self.max_expected,
"created_on": self.created_on,
"updated_on": self.updated_on
}
def latest_to_obj(tup):
ob = {}
ob['id'] = tup[0]
ob['datetime'] = str(tup[1])
ob['tag_id'] = str(tup[2])
ob['tag_name'] = str(tup[3])
ob['tag'] = str(tup[4])
ob['value'] = tup[5]
ob['units'] = tup[6]
ob['tag_description'] = str(tup[7])
ob['min_expected'] = tup[8]
ob['max_expected'] = tup[9]
return ob
class Tag_val(db.Model):
__tablename__ = "tag_vals"
id = db.Column(db.Integer, primary_key=True)
tag_id = db.Column(db.Integer, db.ForeignKey('tags.id'))
tag = db.relationship(Tag)
value = db.Column(db.Float)
created_on = db.Column(db.DateTime(), default=datetime.utcnow)
updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
@property
def serialize(self):
return {
"id": self.id,
"tag_id": self.tag_id,
"tag": self.tag.serialize,
"value": self.value,
"created_on": self.created_on,
"updated_on": self.updated_on
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@@ -0,0 +1 @@
.chart-legend{margin-left:20px}.chart-legend .item{cursor:pointer;font-family:sans-serif;height:16px;font-size:.8em;font-weight:100;display:inline-block;margin-right:10px}.chart-legend .item>*{vertical-align:middle;display:inline-block}.chart-legend .item>.legend-label{height:16px;line-height:17px}.chart-legend .item>.icon{width:16px;border-radius:50%;height:16px;margin-right:5px;background-repeat:no-repeat;background-position:50% 25%}.chart-legend .item.legend-hidden{opacity:.4}.chart-legend .item.column>.icon{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' style='fill: white;' width='10' height='10'><rect y='2' width='2' height='8'/><rect x='4' y='5' width='2' height='5'/><rect x='8' y='3' width='2' height='7'/></svg>")}.chart-legend .item.dot>.icon{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' style='fill: white;' width='10' height='10'><circle cx='5' cy='6' r='2'/></svg>")}.chart-legend .item.dashed-line>.icon{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' style='fill: white;' width='10' height='10'>\a <g style=\"stroke: white; fill: none; stroke-dasharray: 4px,2px;\">\a <path d='M0,6 L10,6'/>\a </g>\a </svg>")}.chart-legend .item.line>.icon{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' style='fill: white;' width='10' height='10'>\a <g style=\"stroke: white;\">\a <path d='M0,6 L10,6'/>\a </g>\a </svg>")}.chart-legend .item.area>.icon{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' style='fill: white;' width='10' height='10'><polygon points='0,10 2.428,3 5,6 7.625,5 10,10 10,10 0,10'/></svg>")}.tooltip-line{stroke:grey;stroke-width:1;shape-rendering:crispEdges}.tooltip-dot{stroke-width:2px;fill:white}.chart-tooltip{position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:white;z-index:100;box-shadow:1px 1px 2px rgba(61,61,61,0.5);padding:5px 10px;border-radius:1px;font-family:sans-serif;font-weight:100}.chart-tooltip>.abscissas{margin-bottom:5px;font-size:.7em;white-space:nowrap}.chart-tooltip .tooltip-item{font-size:.8em;white-space:nowrap}.chart-tooltip .tooltip-item:not(:last-child){margin-bottom:.2em}.chart-tooltip .tooltip-item>*{display:inline-block}.chart-tooltip .tooltip-item>*:not(:last-child){margin-right:.4em}.chart-tooltip .tooltip-item .color-dot{width:10px;height:10px;border-radius:50%}.chart-tooltip .tooltip-item .y-value{font-weight:500}.chart{position:relative;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chart .axis{font:10px Roboto;shape-rendering:crispEdges}.chart .axis.x2-axis{display:none}.chart .axis>path{fill:none;stroke:black}.chart .axis>.tick>text{fill:black}.chart .axis>.tick>line{stroke:black}.chart .grid .tick>text{display:none}.chart .grid .tick>line{stroke:#eee;stroke-width:1;shape-rendering:crispEdges}.chart .dot-series circle{fill:white;stroke-width:2px}.chart .line-series path{stroke-width:1px}.chart .column-series{fill-opacity:.3}.chart .area-series{opacity:.3}.chart .chart-brush{fill:rgba(166,166,166,0.5)}.chart .hline{shape-rendering:crispEdges;stroke-width:1px}

View File

Before

Width:  |  Height:  |  Size: 357 KiB

After

Width:  |  Height:  |  Size: 357 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html ng-app="tagserver" ng-controller="mainCtrl">
<head>
<title>TagServer: {{ Page.title() }}</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/LineChart.min.css">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
<link rel="stylesheet" href="css/ng-quick-date.css">
<link rel="stylesheet" href="css/ng-quick-date-default-theme.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" rel="home" href="/#/" title="Henry Pump">
<img style="max-width:100px; " src="/images/logo.png">
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li ng-class="{active: Page.page() == 'dashboard'}"><a href="/#/"><i class="fa fa-home"></i> Dashboard</a></li>
<li ng-class="{active: Page.page() == 'tags'}"><a href="/#/tags"><i class="fa fa-tags"></i> Tags</a></li>
<li ng-class="{active: Page.page() == 'docs'}"><a href="/#/docs"><i class="fa fa-folder-open-o"></i> Docs</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-class="{active: Page.page() == 'configuration'}"><a href="/#/config"><i class="fa fa-cog"></i> Configuration</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
<div ng-view style="margin-top:40px;"></div>
<!-- libraries -->
<script src="js/lib/d3.min.js"></script>
<script src="js/lib/sugar.min.js"></script>
<script src="js/lib/angular.min.js"></script>
<script src="js/lib/angular-route.min.js"></script>
<script src="js/lib/jquery-2.2.4.min.js"></script>
<script src="js/lib/raphael-min.js"></script>
<script src="js/lib/bootstrap.min.js"></script>
<script src="js/lib/ng-quick-date.min.js"></script>
<script src="js/lib/justgage.js"></script>
<script src="js/lib/ng-justgage.js"></script>
<script src="js/lib/LineChart.min.js"></script>
<!-- application -->
<script src="js/router.js"></script>
<script src="js/main.controller.js"></script>
<script src="js/dateConversion.factory.js"></script>
<script src="js/config.factory.js"></script>
<script src="js/devices.factory.js"></script>
<script src="js/docs.factory.js"></script>
<script src="js/page.factory.js"></script>
<script src="js/tags.factory.js"></script>
<script src="js/config.controller.js"></script>
<script src="js/dashboard.controller.js"></script>
<script src="js/docs.controller.js"></script>
<script src="js/tagVals.controller.js"></script>
<script src="js/tags.controller.js"></script>
</body>
</html>

View File

@@ -52,7 +52,7 @@ poconsole.controller('configCtrl', function($scope, Page, $log, config, devices,
$scope.loggerRunning = data.status;
});
};
$scope.checkLogger();
// $scope.checkLogger();
$scope.restartLogger = function(){
var restartLogger = config.restartLogger();
@@ -74,7 +74,7 @@ poconsole.controller('configCtrl', function($scope, Page, $log, config, devices,
var addDevice = devices.addDevice(dev);
addDevice.then(function(d){
$scope.getDevices();
$scope.newDevice.address = "";
dev.address = "";
});
};

View File

@@ -2,9 +2,9 @@ poconsole.factory('config',function($q, $http, $log){
var getConfig = function(){
var deferred = $q.defer();
$http.get('/config').success(function(data) {
$http.get('/api/configs').success(function(data) {
deferred.resolve({
config:data
config:data.objects
});
});
return deferred.promise;
@@ -12,7 +12,7 @@ poconsole.factory('config',function($q, $http, $log){
var submitParameter = function(entry){
var deferred = $q.defer();
$http.post('/config', {
$http.post('/api/configs', {
parameter: entry.parameter,
val: entry.val
}).success(function(data){
@@ -25,7 +25,7 @@ poconsole.factory('config',function($q, $http, $log){
var updateParameter = function(entry){
var deferred = $q.defer();
$http.post('/config/update/' + entry.id, {
$http.put('/api/configs/' + entry.id, {
parameter: entry.parameter,
val: entry.val
}).success(function(data){
@@ -38,7 +38,7 @@ poconsole.factory('config',function($q, $http, $log){
var deleteParameter = function(id){
var deferred = $q.defer();
$http.delete('/config/' + id).success(function(data){
$http.delete('/api/configs/' + id).success(function(data){
deferred.resolve({
data:data
});

View File

@@ -0,0 +1,37 @@
poconsole.controller('dashboardCtrl', function($scope, $route, $http, Page, $log, tags) {
$log.info("Opened Dashboard");
Page.setTitle('Dashboard');
Page.setPage('dashboard');
$scope.loadDashboard = function(){
$scope.loading = true;
var getCurrentValues = tags.getCurrentValues();
getCurrentValues.then(function(data) {
$scope.loading = false;
$scope.vals = data.vals;
$log.info($scope.vals);
});
};
$scope.loadDashboard();
// $sails.get("/tag_val").success(function(data, status, headers, jwr){
// $log.info(data);
// });
// var valHandler = $sails.on('tag_val', function(message){
// if (message.verb === "created"){
// $log.info(message.data);
// for(var i = 0; i < $scope.vals.length; i++){
// if(message.data.tagID == $scope.vals[i].t_id){
// $scope.vals[i].val = message.data.val;
// $scope.vals[i].dtime = message.data.createdAt;
// }
// }
// }
// });
// $scope.$on('$destroy', function() {
// $sails.off('tag_val', valHandler);
// });
});

View File

@@ -24,8 +24,19 @@ poconsole.factory('dateConversion', function(){
var sec = d.getSeconds().pad(2);
return "".concat(year, "-", month, "-", day, " ", hour, ":", min, ":", sec);
};
var pythonDate = function(d){
var year = d.getUTCFullYear().pad(4);
var month = (d.getUTCMonth() + 1).pad(2);
var day = d.getUTCDate().pad(2);
var hour = d.getUTCHours().pad(2);
var min = d.getUTCMinutes().pad(2);
var sec = d.getUTCSeconds().pad(2);
return "".concat(year, "-", month, "-", day, " ", hour, ":", min, ":", sec, ".000");
};
return {
mysqlDate: mysqlDate,
sqliteDate: sqliteDate
sqliteDate: sqliteDate,
pythonDate: pythonDate
};
});

View File

@@ -1,9 +1,10 @@
poconsole.factory('devices', function($q, $http, $log){
var getAllDevices = function(){
var deferred = $q.defer();
$http.get('/device').success(function(data) {
$http.get('/api/devices').success(function(data) {
console.log({device:data.objects});
deferred.resolve({
devices:data
devices:data.objects
});
});
return deferred.promise;
@@ -11,7 +12,7 @@ poconsole.factory('devices', function($q, $http, $log){
var getDevice = function(id){
var deferred = $q.defer();
$http.get('/device/'+ id).success(function(data) {
$http.get('/api/devices/'+ id).success(function(data) {
deferred.resolve({
devices:data
});
@@ -22,9 +23,9 @@ poconsole.factory('devices', function($q, $http, $log){
var addDevice = function(d){
$log.info(d);
var deferred = $q.defer();
$http.post('/device/create', {
$http.post('/api/devices', {
address: d.address,
device_type: d.device_type.id
device_type_id: d.device_type.id
}).success(function(data){
deferred.resolve({
data:data
@@ -35,7 +36,7 @@ poconsole.factory('devices', function($q, $http, $log){
var updateDevice = function(d){
var deferred = $q.defer();
$http.post('/device/update/' + d.id, {
$http.put('/api/devices/' + d.id, {
address: d.address,
device_type: d.device_type.id
}).success(function(data){
@@ -48,7 +49,7 @@ poconsole.factory('devices', function($q, $http, $log){
var deleteDevice = function(id){
var deferred = $q.defer();
var url = '/device/' + id;
var url = '/api/devices/' + id;
$http.delete(url).success(function(data) {
deferred.resolve({
data:data
@@ -59,9 +60,9 @@ poconsole.factory('devices', function($q, $http, $log){
var getDeviceTypes = function(){
var deferred = $q.defer();
$http.get('/device_type').success(function(data) {
$http.get('/api/device_types').success(function(data) {
deferred.resolve({
device_types:data
device_types:data.objects
});
});
return deferred.promise;

View File

@@ -10,7 +10,7 @@ poconsole.controller('docsCtrl', function($scope, $route, Page, $log, docs) {
var imageBase = "/images/icons/";
var imageExtension = ".png";
$scope.docs = d.docs.map(function(doc){
var spl = doc.location.split(".");
var spl = doc.name.split(".");
var split_name = doc.name.split(".");
var trunc_filebase = split_name[0];

View File

@@ -12,9 +12,9 @@ poconsole.factory('docs',function($q, $http, $log, formDataObject){
var getAllDocs = function(){
var deferred = $q.defer();
$http.get('/doc').success(function(data) {
$http.get('/api/docs').success(function(data) {
deferred.resolve({
docs:data
docs:data.objects
});
});
return deferred.promise;
@@ -22,7 +22,7 @@ poconsole.factory('docs',function($q, $http, $log, formDataObject){
var getDoc = function(id){
var deferred = $q.defer();
$http.get('/doc/' + id).success(function(data) {
$http.get('/api/docs/' + id).success(function(data) {
deferred.resolve({
docs:data
});
@@ -32,7 +32,7 @@ poconsole.factory('docs',function($q, $http, $log, formDataObject){
var deleteDoc = function(id){
var deferred = $q.defer();
$http.delete('/doc/' + id).success(function(data) {
$http.delete('/api/docs/' + id).success(function(data) {
deferred.resolve({
deleted:data
});

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More