1 Commits

Author SHA1 Message Date
Patrick McDonagh
53ddf5fab4 Initial framework for Pyramid 2016-12-07 15:02:18 -06:00
8 changed files with 518 additions and 0 deletions

4
.gitignore vendored
View File

@@ -5,3 +5,7 @@ sails/.tmp
.remote-sync.json
database.db
venv/
.vscode/
pyr_test/env/lib/python2.7/site-packages/pyramid/tests/test_scaffolds/fixture_scaffold/development.ini_tmpl
pyr_test/env/
pyr_test/hp_webserver/poconsole.egg-info/

View File

@@ -0,0 +1,49 @@
[app:main]
use = egg:poconsole
pyramid.reload_templates = true
pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
sqlalchemy.url = sqlite:///%(here)s/poconsole.sqlite
[server:main]
use = egg:pyramid#wsgiref
host = 0.0.0.0
port = 6543
# Begin logging configuration
[loggers]
keys = root, poconsole, sqlalchemy.engine.base.Engine
[logger_poconsole]
level = DEBUG
handlers =
qualname = poconsole
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_sqlalchemy.engine.base.Engine]
level = INFO
handlers =
qualname = sqlalchemy.engine.base.Engine
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
# End logging configuration

View File

@@ -0,0 +1,35 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from .models import DBSession, Base
def main(global_config, **settings):
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.bind = engine
config = Configurator(settings=settings,
root_factory='poconsole.models.Root')
config.include('pyramid_chameleon')
# Configs
config.add_route('configs', '/api/configs')
config.add_route('config', '/api/configs/{_id}')
# Configs
config.add_route('configs', '/api/configs')
config.add_route('config', '/api/configs/{_id}')
# Device Types
config.add_route('device_types', '/api/device_types')
config.add_route('device_type', '/api/device_types/{_id}')
config.add_route('wiki_view', '/')
config.add_route('wikipage_add', '/add')
config.add_route('wikipage_view', '/{uid}')
config.add_route('wikipage_edit', '/{uid}/edit')
config.add_static_view('deform_static', 'deform:static/')
config.scan('.views')
return config.make_wsgi_app()

View File

@@ -0,0 +1,61 @@
import os
import sys
import transaction
from sqlalchemy import engine_from_config
from pyramid.paster import (
get_appsettings,
setup_logging,
)
from .models import (
DBSession,
Config,
Device_type,
Device,
Doc,
Tag,
Tag_val,
Card,
GaugeOffVal,
WellTest,
Note,
EventConfig,
Event,
RunStatus,
FluidShot,
BackupRestore,
Base,
)
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
'(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
config_uri = argv[1]
setup_logging(config_uri)
settings = get_appsettings(config_uri)
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
# Device Type Seeds
device_type_CLX = Device_type(device_type='CLX')
device_type_u800 = Device_type(device_type='Micro800')
device_type_E300 = Device_type(device_type='E300')
DBSession.add(device_type_CLX)
DBSession.add(device_type_u800)
DBSession.add(device_type_E300)
# Device Seeds
main_plc = Device(device_type_id=1, address="192.168.1.10")
DBSession.add(main_plc)

View File

@@ -0,0 +1,221 @@
from pyramid.security import Allow, Everyone
from datetime import datetime
from sqlalchemy import (
Column,
Integer,
Text,
String,
Float,
DateTime,
ForeignKey,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
scoped_session,
sessionmaker,
relationship
)
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(
sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
# class Page(Base):
# __tablename__ = 'wikipages'
# uid = Column(Integer, primary_key=True)
# title = Column(Text, unique=True)
# body = Column(Text)
class Config(Base):
__tablename__ = "configs"
_id = Column(Integer, primary_key=True)
parameter = Column(String(100), unique=True)
val = Column(String(100), unique=True)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Device_type(Base):
__tablename__ = "device_types"
_id = Column(Integer, primary_key=True)
device_type = Column(String(64))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Device(Base):
__tablename__ = "devices"
_id = Column(Integer, primary_key=True)
device_type_id = Column(Integer, ForeignKey('device_types._id'))
device_type = relationship(Device_type, primaryjoin=device_type_id == Device_type._id)
address = Column(String(256))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Doc(Base):
__tablename__ = "docs"
_id = Column(Integer, primary_key=True)
name = Column(String(256))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Tag(Base):
__tablename__ = "tags"
_id = Column(Integer, primary_key=True)
name = Column(String(64))
tag = Column(String(128))
tag_category = Column(String(128))
device_id = Column(Integer, ForeignKey('devices._id'))
device = relationship(Device)
description = Column(String(64))
data_type = Column(String(64))
change_threshold = Column(Float)
guarantee_sec = Column(Integer)
map_function = Column(String(64))
units = Column(String(10))
min_expected = Column(Float)
max_expected = Column(Float)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Tag_val(Base):
__tablename__ = "tag_vals"
_id = Column(Integer, primary_key=True)
tag_id = Column(Integer, ForeignKey('tags._id'))
tag = relationship(Tag)
value = Column(Float)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Card(Base):
__tablename__ = "cards"
_id = Column(Integer, primary_key=True)
stroke_type = Column(String(32))
stroke_number = Column(Integer)
surf_pos = Column(Text)
surf_lod = Column(Text)
down_pos = Column(Text)
down_lod = Column(Text)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class GaugeOffVal(Base):
__tablename__ = "gauge_off"
_id = Column(Integer, primary_key=True)
spm_average = Column(Float)
downhole_gross_stroke_average = Column(Float)
downhole_net_stroke_average = Column(Float)
electricity_cost_total = Column(Float)
fluid_level_average = Column(Float)
full_card_production_total = Column(Float)
inflow_rate_average = Column(Float)
kWh_used_total = Column(Float)
kWh_regen_total = Column(Float)
lifting_cost_average = Column(Float)
peak_pr_load = Column(Float)
min_pr_load = Column(Float)
percent_run = Column(Float)
polished_rod_hp_average = Column(Float)
pump_hp_average = Column(Float)
production_total = Column(Float)
pump_intake_pressure_average = Column(Float)
surface_stroke_length_average = Column(Float)
tubing_movement_average = Column(Float)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class WellTest(Base):
__tablename__ = "well_tests"
_id = Column(Integer, primary_key=True)
duration_hours = Column(Float)
volume_h2o_actual = Column(Float)
volume_oil_actual = Column(Float)
volume_gas_actual = Column(Float)
volume_h2o_projected = Column(Float)
volume_oil_projected = Column(Float)
volume_gas_projected = Column(Float)
api_gravity_oil = Column(Float)
spc_gravity_h2o = Column(Float)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Note(Base):
__tablename__ = "notes"
_id = Column(Integer, primary_key=True)
note_text = Column(String(256))
author = Column(String(128))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class EventConfig(Base):
__tablename__ = "event_configs"
_id = Column(Integer, primary_key=True)
name = Column(String(64))
event_type = Column(String(64))
tag = Column(String(128))
condition = Column(String(64))
device_id = Column(Integer, ForeignKey('devices._id'))
device = relationship(Device)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Event(Base):
__tablename__ = "events"
_id = Column(Integer, primary_key=True)
event_id = Column(Integer, ForeignKey('event_configs._id'))
event = relationship(EventConfig)
event_type = Column(String(64))
event_condition = Column(String(64))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class RunStatus(Base):
__tablename__ = "run_status_log"
_id = Column(Integer, primary_key=True)
run_status = Column(String(64))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class FluidShot(Base):
__tablename__ = "fluid_shots"
_id = Column(Integer, primary_key=True)
pump_intake_pressure = Column(Float)
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class BackupRestore(Base):
__tablename__ = "backup_restore"
_id = Column(Integer, primary_key=True)
tag = Column(String(128))
tag_type = Column(String(128))
device_id = Column(Integer, ForeignKey('devices._id'))
device = relationship(Device)
value = Column(String(128))
created_on = Column(DateTime(), default=datetime.utcnow)
updated_on = Column(DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)
class Root(object):
__acl__ = [(Allow, Everyone, 'view'),
(Allow, 'group:editors', 'edit')]
def __init__(self, request):
pass

View File

View File

@@ -0,0 +1,128 @@
import colander
import deform.widget
from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from .models import (
DBSession,
Config,
Device_type,
Device,
Doc,
Tag,
Tag_val,
Card,
GaugeOffVal,
WellTest,
Note,
EventConfig,
Event,
RunStatus,
FluidShot,
BackupRestore
)
class WikiPage(colander.MappingSchema):
title = colander.SchemaNode(colander.String())
body = colander.SchemaNode(
colander.String(),
widget=deform.widget.RichTextWidget()
)
class ConfigCol(colander.MappingSchema):
parameter = colander.SchemaNode(colander.string())
val = colander.SchemaNode(colander.string())
class ConfigViews(object):
def __init__(self, request):
self.request = request
@view_config(route_name='config', renderer='json')
def get_config(self):
id = int(self.request.matchdict['id'])
config = DBSession.query(Config).filter_by(_id=id).one()
return dict(config=config)
class WikiViews(object):
def __init__(self, request):
self.request = request
@property
def wiki_form(self):
schema = WikiPage()
return deform.Form(schema, buttons=('submit',))
@property
def reqts(self):
return self.wiki_form.get_widget_resources()
@view_config(route_name='wiki_view', renderer='wiki_view.pt')
def wiki_view(self):
pages = DBSession.query(Page).order_by(Page.title)
return dict(title='Wiki View', pages=pages)
@view_config(route_name='wikipage_add',
renderer='wikipage_addedit.pt')
def wikipage_add(self):
form = self.wiki_form.render()
if 'submit' in self.request.params:
controls = self.request.POST.items()
try:
appstruct = self.wiki_form.validate(controls)
except deform.ValidationFailure as e:
# Form is NOT valid
return dict(form=e.render())
# Add a new page to the database
new_title = appstruct['title']
new_body = appstruct['body']
DBSession.add(Page(title=new_title, body=new_body))
# Get the new ID and redirect
page = DBSession.query(Page).filter_by(title=new_title).one()
new_uid = page.uid
url = self.request.route_url('wikipage_view', uid=new_uid)
return HTTPFound(url)
return dict(form=form)
@view_config(route_name='wikipage_view', renderer='wikipage_view.pt')
def wikipage_view(self):
uid = int(self.request.matchdict['uid'])
page = DBSession.query(Page).filter_by(uid=uid).one()
return dict(page=page)
@view_config(route_name='wikipage_edit',
renderer='wikipage_addedit.pt')
def wikipage_edit(self):
uid = int(self.request.matchdict['uid'])
page = DBSession.query(Page).filter_by(uid=uid).one()
wiki_form = self.wiki_form
if 'submit' in self.request.params:
controls = self.request.POST.items()
try:
appstruct = wiki_form.validate(controls)
except deform.ValidationFailure as e:
return dict(page=page, form=e.render())
# Change the content and redirect to the view
page.title = appstruct['title']
page.body = appstruct['body']
url = self.request.route_url('wikipage_view', uid=uid)
return HTTPFound(url)
form = self.wiki_form.render(dict(
uid=page.uid, title=page.title, body=page.body)
)
return dict(page=page, form=form)

View File

@@ -0,0 +1,20 @@
from setuptools import setup
requires = [
'pyramid',
'pyramid_chameleon',
'deform',
'sqlalchemy',
'pyramid_tm',
'zope.sqlalchemy'
]
setup(name='poconsole',
install_requires=requires,
entry_points="""\
[paste.app_factory]
main = poconsole:main
[console_scripts]
initialize_poconsole_db = poconsole.initialize_db:main
""",
)