1
0
Fork 0
Browse Source

2021.11.05 snapshot.

commit 5ecf3f1173
Author: Craig Oates <craig@craigoates.net>
Date:   Fri Nov 5 18:35:56 2021 +0000

    update README.

commit f2aa373418
Author: Craig Oates <craig@craigoates.net>
Date:   Mon Jan 13 00:58:01 2020 +0000

    make git ignore readings.db.

commit 9c1a023ab4
Author: Craig Oates <craig@craigoates.net>
Date:   Mon Jan 13 00:33:23 2020 +0000

    make home page refresh every 60 seconds.

commit b3efcc73c8
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 16:18:16 2020 +0000

    add comment to device_check_token.

commit 747f6b847c
Merge: bf21990 ba85b56
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 16:00:02 2020 +0000

    merge of unstable into stable

commit ba85b560ea
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:44:41 2020 +0000

    add tim e of request info. to home.

commit 427d263812
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:21:36 2020 +0000

    fix typo in YAML file.

commit e7e4923330
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:18:40 2020 +0000

    add get latest (all) device status to YAML (A.P.I.) file.

commit b4d9ca04fa
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:09:06 2020 +0000

    reset database.

commit 3e80738d32
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:08:33 2020 +0000

    add 400-error responses to GET requests in YAML file.

commit 13e2f5d3ba
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 15:03:27 2020 +0000

    add 400-error info. to PUT request in YAML file.

commit b01178a711
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 14:57:21 2020 +0000

    add try-blocks to post requests.

commit d377ef4eca
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 14:44:07 2020 +0000

    add secirity token checks to status change A.P.I. call.

commit 95cb475428
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 14:35:26 2020 +0000

    add security token checks when adding new reading.

commit bf2199012e
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 00:17:39 2020 +0000

    reset database.

commit c24981a0e3
Author: Craig Oates <craig@craigoates.net>
Date:   Thu Jan 9 00:04:50 2020 +0000

    reset database.

commit 0bb4ed4be8
Merge: bd20f7b f32e4ae
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 23:56:26 2020 +0000

    Merge branch 'unstable' of return-to-ritherdon/midpoint into stable

commit f32e4aec4a
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 23:52:50 2020 +0000

    update A.P.I. version to 1.0.0 - Alpha.

commit 1008d3e2e4
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 23:51:16 2020 +0000

    implement home page status report feature.

commit 6394009f40
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 22:39:15 2020 +0000

    implement get all status changes (all devices) A.P.I. call.

commit fc3fe18b0e
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 22:30:25 2020 +0000

    implement get all status changes (per device) A.P.I. call.

commit 65464fae54
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 21:59:35 2020 +0000

    implement get device status latest A.P.I. call.

commit 641fe8f604
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 21:08:07 2020 +0000

    add device status-update logging.

commit 312bcd70a6
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 19:04:38 2020 +0000

    remove in-mem readings and refactor related items.

commit c4590b906c
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 03:30:47 2020 +0000

    add website info. section to home.

commit 1ded49cfcf
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 03:20:48 2020 +0000

    add artwork status bar to home page.

commit 628ea5a9a2
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 02:28:56 2020 +0000

    add styling and content to home page.

commit 400c0f0310
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 00:25:16 2020 +0000

    add route for robots.txt.

commit bb05c5e151
Author: Craig Oates <craig@craigoates.net>
Date:   Wed Jan 8 00:10:12 2020 +0000

    create robot.txt file.

commit 5bdd448b7e
Author: Craig Oates <craig@craigoates.net>
Date:   Tue Jan 7 23:58:55 2020 +0000

    add favicons.

commit bd20f7be7d
Merge: 1975e6e 2d6ba68
Author: Craig Oates <craig@craigoates.net>
Date:   Tue Jan 7 23:46:14 2020 +0000

    Merge branch 'unstable' of return-to-ritherdon/midpoint into stable

commit 2d6ba68682
Author: Craig Oates <craig@craigoates.net>
Date:   Tue Jan 7 23:43:37 2020 +0000

    update requirements in proj-env.

commit 1975e6ecbf
Author: Craig Oates <craig@craigoates.net>
Date:   Tue Jan 7 23:24:52 2020 +0000

    create v-env. for server and update requirements.

commit 373b6686ad
Author: Craig Oates <craig@craigoates.net>
Date:   Mon Jan 6 01:18:35 2020 +0000

    create html templates.

commit 9f0c71ada2
Author: Craig Oates <craig@craigoates.net>
Date:   Sun Jan 5 23:51:37 2020 +0000

    port code over from test proj.

commit c1f174f828
Author: Craig Oates <craig@craigoates.net>
Date:   Sun Jan 5 22:52:51 2020 +0000

    create virtual environment.
master 2021.11.05
Craig Oates 3 years ago
parent
commit
9c1e681c31
  1. 1
      .gitignore
  2. 15
      README.md
  3. 37
      app/api.py
  4. 25
      app/app.py
  5. 69
      app/build_database.py
  6. 24
      app/config.py
  7. 82
      app/models/devices.py
  8. 50
      app/models/meters.py
  9. 214
      app/services/get_services.py
  10. 134
      app/services/post_services.py
  11. BIN
      app/static/favicons/android-icon-144x144.png
  12. BIN
      app/static/favicons/android-icon-192x192.png
  13. BIN
      app/static/favicons/android-icon-36x36.png
  14. BIN
      app/static/favicons/android-icon-48x48.png
  15. BIN
      app/static/favicons/android-icon-72x72.png
  16. BIN
      app/static/favicons/android-icon-96x96.png
  17. BIN
      app/static/favicons/apple-icon-114x114.png
  18. BIN
      app/static/favicons/apple-icon-120x120.png
  19. BIN
      app/static/favicons/apple-icon-144x144.png
  20. BIN
      app/static/favicons/apple-icon-152x152.png
  21. BIN
      app/static/favicons/apple-icon-180x180.png
  22. BIN
      app/static/favicons/apple-icon-57x57.png
  23. BIN
      app/static/favicons/apple-icon-60x60.png
  24. BIN
      app/static/favicons/apple-icon-72x72.png
  25. BIN
      app/static/favicons/apple-icon-76x76.png
  26. BIN
      app/static/favicons/apple-icon-precomposed.png
  27. BIN
      app/static/favicons/apple-icon.png
  28. 2
      app/static/favicons/browserconfig.xml
  29. BIN
      app/static/favicons/favicon-16x16.png
  30. BIN
      app/static/favicons/favicon-32x32.png
  31. BIN
      app/static/favicons/favicon-96x96.png
  32. BIN
      app/static/favicons/favicon.ico
  33. 41
      app/static/favicons/manifest.json
  34. BIN
      app/static/favicons/ms-icon-144x144.png
  35. BIN
      app/static/favicons/ms-icon-150x150.png
  36. BIN
      app/static/favicons/ms-icon-310x310.png
  37. BIN
      app/static/favicons/ms-icon-70x70.png
  38. BIN
      app/static/images/error.png
  39. BIN
      app/static/images/logo.png
  40. BIN
      app/static/images/off.png
  41. BIN
      app/static/images/on.png
  42. 71
      app/static/styles/main.css
  43. 440
      app/swagger.yml
  44. 17
      app/templates/favicons.html
  45. 82
      app/templates/home.html
  46. 26
      app/templates/layout.html
  47. 5
      app/templates/robots.txt
  48. 76
      proj-env/bin/activate
  49. 37
      proj-env/bin/activate.csh
  50. 75
      proj-env/bin/activate.fish
  51. 10
      proj-env/bin/chardetect
  52. 10
      proj-env/bin/connexion
  53. 10
      proj-env/bin/easy_install
  54. 10
      proj-env/bin/easy_install-3.7
  55. 10
      proj-env/bin/flask
  56. 10
      proj-env/bin/gunicorn
  57. 10
      proj-env/bin/jsonschema
  58. 10
      proj-env/bin/openapi-spec-validator
  59. 10
      proj-env/bin/pip
  60. 10
      proj-env/bin/pip3
  61. 10
      proj-env/bin/pip3.7
  62. 1
      proj-env/bin/python
  63. 1
      proj-env/bin/python3
  64. 10
      proj-env/bin/virtualenv
  65. 1
      proj-env/lib64
  66. 3
      proj-env/pyvenv.cfg
  67. BIN
      proj-env/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl
  68. BIN
      proj-env/share/python-wheels/appdirs-1.4.3-py2.py3-none-any.whl
  69. BIN
      proj-env/share/python-wheels/certifi-2018.8.24-py2.py3-none-any.whl
  70. BIN
      proj-env/share/python-wheels/chardet-3.0.4-py2.py3-none-any.whl
  71. BIN
      proj-env/share/python-wheels/colorama-0.3.7-py2.py3-none-any.whl
  72. BIN
      proj-env/share/python-wheels/distlib-0.2.8-py2.py3-none-any.whl
  73. BIN
      proj-env/share/python-wheels/distro-1.3.0-py2.py3-none-any.whl
  74. BIN
      proj-env/share/python-wheels/html5lib-1.0.1-py2.py3-none-any.whl
  75. BIN
      proj-env/share/python-wheels/idna-2.6-py2.py3-none-any.whl
  76. BIN
      proj-env/share/python-wheels/ipaddress-0.0.0-py2.py3-none-any.whl
  77. BIN
      proj-env/share/python-wheels/lockfile-0.12.2-py2.py3-none-any.whl
  78. BIN
      proj-env/share/python-wheels/packaging-19.0-py2.py3-none-any.whl
  79. BIN
      proj-env/share/python-wheels/pip-18.1-py2.py3-none-any.whl
  80. BIN
      proj-env/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl
  81. BIN
      proj-env/share/python-wheels/progress-1.2-py2.py3-none-any.whl
  82. BIN
      proj-env/share/python-wheels/pyparsing-2.2.0-py2.py3-none-any.whl
  83. BIN
      proj-env/share/python-wheels/pytoml-0.1.2-py2.py3-none-any.whl
  84. BIN
      proj-env/share/python-wheels/requests-2.21.0-py2.py3-none-any.whl
  85. BIN
      proj-env/share/python-wheels/retrying-1.3.3-py2.py3-none-any.whl
  86. BIN
      proj-env/share/python-wheels/setuptools-40.8.0-py2.py3-none-any.whl
  87. BIN
      proj-env/share/python-wheels/six-1.12.0-py2.py3-none-any.whl
  88. BIN
      proj-env/share/python-wheels/urllib3-1.24.1-py2.py3-none-any.whl
  89. BIN
      proj-env/share/python-wheels/webencodings-0.5.1-py2.py3-none-any.whl
  90. BIN
      proj-env/share/python-wheels/wheel-0.32.3-py2.py3-none-any.whl
  91. 29
      requirements.txt
  92. 76
      ser-ver/bin/activate
  93. 37
      ser-ver/bin/activate.csh
  94. 75
      ser-ver/bin/activate.fish
  95. 11
      ser-ver/bin/chardetect
  96. 11
      ser-ver/bin/connexion
  97. 11
      ser-ver/bin/easy_install
  98. 11
      ser-ver/bin/easy_install-3.7
  99. 11
      ser-ver/bin/flask
  100. 11
      ser-ver/bin/gunicorn
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitignore vendored

@ -1,3 +1,4 @@
app/readings.db
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/

15
README.md

@ -1,3 +1,14 @@
# midpoint
# Return to Ritherdon: Midpoint
This is a web REST-APIbuilt with Flask and Python. Its main purpose is
to receive the readings from the light meters welding booths in the
Ritherdon factory and make them available for consumption by the
relay-controllers in the gallery. Midpoint is one of three projects
which combine to form the 'Personal Flash in Real-Time' artwork --
which is one of several artworks created as part of the 'Return to
Ritherdon' project. For more information on this repository and
'Return to Ritherdon', please use the links below:
- [Return to Ritherdon Overview](https://git.abbether.net/return-to-ritherdon/rtr-docs)
- [Midpoint Documentation](https://git.abbether.net/return-to-ritherdon/rtr-docs/src/branch/master/midpoint/rtr-midpoint.md)
A web A.P.I. built with Flask and Python. Its main purpose is to receive the readings from the light meters welding booths in the Ritherdon factory and make them available for consumption by the relay-controllers in the gallery.

37
app/api.py

@ -0,0 +1,37 @@
from services import post_services, get_services
'''
API Functions
======================================================================
These functions are what are exposed/referenced in the swagger.yml
file -- they are essentially wrapper functions. The main work is done
in the files in the /services/ folder.
These functions are acting as very light controllers essentially.
'''
def post_a_reading(light_meter, the_reading):
return post_services.add_latest_reading(light_meter, the_reading)
def post_a_status_change(device, the_status_change):
return post_services.log_status_change(device, the_status_change)
def get_latest(light_meter):
return get_services.get_latest_reading(light_meter)
def get_all_readings(light_meter):
return get_services.get_all_readings_from_table(light_meter)
def get_all_readings_for_every_meter():
return get_services.get_all_readings_from_database()
def get_latest_device_status(device):
return get_services.get_latest_status(device)
def get_all_status_log(device):
return get_services.get_all_status_logs_from_table(device)
def get_all_status_logs_for_every_device():
return get_services.get_all_status_changes_from_database()
def get_current_status_for_all_devices():
return get_services.get_latest_status_for_all_devices()

25
app/app.py

@ -0,0 +1,25 @@
from flask import Flask, render_template
from datetime import datetime
import connexion
import config
from services import get_services
# The application instance.
app = config.connex_app
# The yml file configures the app's endpoints.
app.add_api("swagger.yml")
@app.route("/")
def home ():
data = get_services.get_latest_status_for_all_devices()
time = datetime.now()
return render_template("home.html", data=data, time=time)
@app.route("/robots.txt")
@app.route("/robots")
def robots():
return render_template("robots.txt")
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=False)

69
app/build_database.py

@ -0,0 +1,69 @@
import os
from datetime import datetime
from config import db
from models.meters import Meter1, Meter2, Meter3
from models.devices import Device1, Device2, Device3, Device4, Device5, Device6
def get_timestamp():
return datetime.now().strftime(("%Y-%m-%d %H:%M:%S"))
# The initialisation data for the database
READINGS1 =[ {"time":datetime.now(), "reading": 0} ]
READINGS2 =[ {"time":datetime.now(), "reading": 0} ]
READINGS3 =[ {"time":datetime.now(), "reading": 0} ]
DEVICE1 = [ {"time":datetime.now(), "status": "off"} ]
DEVICE2 = [ {"time":datetime.now(), "status": "off"} ]
DEVICE3 = [ {"time":datetime.now(), "status": "off"} ]
DEVICE4 = [ {"time":datetime.now(), "status": "off"} ]
DEVICE5 = [ {"time":datetime.now(), "status": "off"} ]
DEVICE6 = [ {"time":datetime.now(), "status": "off"} ]
# Deletes the database if it already exists
if os.path.exists("readings.db"):
os.remove("readings.db")
# Creates the database
db.create_all()
# Iterates over the READINGS1 structure and populates the database
for info in READINGS1:
r = Meter1(time=info.get("time"), reading=info.get("reading"))
db.session.add(r)
# Iterates over the READINGS2 structure and populates the datebase
for info in READINGS2:
r = Meter2(time=info.get("time"), reading=info.get("reading"))
db.session.add(r)
# Iterates over the READINGS3 structure and populates the datebase.
for info in READINGS3:
r = Meter3(time=info.get("time"), reading=info.get("reading"))
db.session.add(r)
# These are the light-meters in Ritherdon.
for info in DEVICE1:
r = Device1(time=info.get("time"), status=info.get("status"))
db.session.add(r)
for info in DEVICE2:
r = Device2(time=info.get("time"), status=info.get("status"))
db.session.add(r)
for info in DEVICE3:
r = Device3(time=info.get("time"), status=info.get("status"))
db.session.add(r)
# These are the relays in the gallery.
for info in DEVICE4:
r = Device4(time=info.get("time"), status=info.get("status"))
db.session.add(r)
for info in DEVICE5:
r = Device5(time=info.get("time"), status=info.get("status"))
db.session.add(r)
for info in DEVICE6:
r = Device6(time=info.get("time"), status=info.get("status"))
db.session.add(r)
db.session.commit()

24
app/config.py

@ -0,0 +1,24 @@
import os
import connexion
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
basedir = os.path.abspath(os.path.dirname(__file__))
# Creates the Connexion application instance
connex_app = connexion.App(__name__, specification_dir=basedir)
# Gets the underlying Flask app instance
app = connex_app.app
database_uri = "sqlite:////" + os.path.join(basedir, "readings.db")
# Configures the SQLAlchemy part of the app instance
app.config["SQLALCHEMY_ECHO"] = True # Set to false in prod.
app.config["SQLALCHEMY_DATABASE_URI"] = database_uri
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# Creates the SQLAlchemy db instance
db = SQLAlchemy(app)
# Initialises Marshmallow
ma = Marshmallow(app)

82
app/models/devices.py

@ -0,0 +1,82 @@
from datetime import datetime
from config import db, ma
'''
Note on Duplication Levels
======================================================================
While the code in this file seems very duplicated, it is just the
result of using SQL-Alchemy (ORM) and the repetitive nature of the
project as a whole. At the time of writing, the expected amount of
devices is six. They must keep their info. separate from each other.
This means a table in the database for each device. This is the main
cause for the repetitive/duplicated code. Because this project has
fixed requirements, the hard-coded nature is a trade-off because of
this. If the project increases the amount of devices it uses, this
will probably need to be refactored.
'''
class Device1(db.Model):
__tablename__ = "device1"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device1Schema(ma.ModelSchema):
class Meta:
model = Device1
sqla_session = db.session
class Device2(db.Model):
__tablename__ = "device2"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device2Schema(ma.ModelSchema):
class Meta:
model = Device2
sqla_session = db.session
class Device3(db.Model):
__tablename__ = "device3"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device3Schema(ma.ModelSchema):
class Meta:
model = Device3
sqla_session = db.session
class Device4(db.Model):
__tablename__ = "device4"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device4Schema(ma.ModelSchema):
class Meta:
model = Device4
sqla_session = db.session
class Device5(db.Model):
__tablename__ = "device5"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device5Schema(ma.ModelSchema):
class Meta:
model = Device5
sqla_session = db.session
class Device6(db.Model):
__tablename__ = "device6"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String)
class Device6Schema(ma.ModelSchema):
class Meta:
model = Device6
sqla_session = db.session

50
app/models/meters.py

@ -0,0 +1,50 @@
from datetime import datetime
from config import db, ma
'''
Note on Duplication Levels
======================================================================
While the code in this file seems very duplicated, it is just the
result of using SQL-Alchemy (ORM) and the repetitive nature of the
project as a whole. At the time of writing, the expected amount of
light meters is three and each one must take their own readings.
But, they must keep their readings separate from each other. This
means a table in the database for each meter. This is the main cause
for the repetitive/duplicated code.
Because this project has fixed requirements, the hard-coded nature is
a trade-off because of this. If the project increases the amount of
light meters it uses, this will probably need to be refactored.
'''
class Meter1(db.Model):
__tablename__ = "meter1"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime, default=datetime.utcnow)
reading = db.Column(db.Integer)
class Meter1Schema(ma.ModelSchema):
class Meta:
model = Meter1
sqla_session = db.session
class Meter2(db.Model):
__tablename__ = "meter2"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime)
reading = db.Column(db.Integer)
class Meter2Schema(ma.ModelSchema):
class Meta:
model = Meter2
sqla_session = db.session
class Meter3(db.Model):
__tablename__ = "meter3"
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime)
reading = db.Column(db.Integer)
class Meter3Schema(ma.ModelSchema):
class Meta:
model = Meter3
sqla_session = db.session

214
app/services/get_services.py

@ -0,0 +1,214 @@
from flask import make_response, abort
from config import db
from models.meters import (Meter1, Meter1Schema, Meter2, Meter2Schema,
Meter3, Meter3Schema)
from models.devices import (Device1, Device1Schema, Device2, Device2Schema,
Device3, Device3Schema, Device4, Device4Schema,
Device5, Device5Schema, Device6, Device6Schema)
'''
Get Services Note
======================================================================
The functions in this file are for retrieving data stored at the (this)
server. If you want to store any readings taken with the light meters
at Ritherdon, you will need to head to the /post_services.py/ file.
It should be in the same directory at this: /services/.
'''
bad_meter_id_message = "Meter Id. not recognised. Must be between 1 and 3."
bad_device_id_message = "Device Id. not recognised. Must be between 1 and 6."
def get_latest_reading(meter):
if meter == 1:
return get_m1_latest()
elif meter == 2:
return get_m2_latest()
elif meter == 3:
return get_m3_latest()
return make_response(bad_meter_id_message, 400)
def get_all_readings_from_table(name):
if name == 1:
return get_all_readings_for_meter1()
elif name == 2:
return get_all_readings_for_meter2()
elif name == 3:
return get_all_readings_for_meter3()
return make_response(bad_meter_id_message, 400)
def get_all_readings_from_database():
return get_all_readings()
def get_latest_status(device):
if device == 1:
return get_d1_latest()
elif device == 2:
return get_d2_latest()
elif device == 3:
return get_d3_latest()
elif device == 4:
return get_d4_latest()
elif device == 5:
return get_d5_latest()
elif device == 6:
return get_d6_latest()
return make_response(bad_device_id_message, 400)
def get_all_status_logs_from_table(device):
if device == 1:
return get_all_status_logs_for_d1()
elif device == 2:
return get_all_status_logs_for_d2()
elif device == 3:
return get_all_status_logs_for_d3()
elif device == 4:
return get_all_status_logs_for_d4()
elif device == 5:
return get_all_status_logs_for_d5()
elif device == 6:
return get_all_status_logs_for_d6()
return make_response(bad_device_id_message, 400)
def get_all_status_changes_from_database():
return get_all_status_logs()
def get_latest_status_for_all_devices():
return get_all_latest_logs()
'''
The Nitty-Gritty Functions
======================================================================
The functions below are the main functions within this file. The files
above act as "header functions" to be called by the functions in /api.py/.
I find it easier to see what the method names are when this file and
/api.py/ are open side-by-side. At the very least it reduces the amount
I need to scroll up and down the file to find what I am after.
'''
def get_m1_latest():
reading = Meter1.query.order_by(Meter1.id.desc()).first()
meter_schema = Meter1Schema()
return meter_schema.dump(reading)
def get_m2_latest():
reading = Meter2.query.order_by(Meter2.id.desc()).first()
meter_schema = Meter2Schema()
return meter_schema.dump(reading)
def get_m3_latest():
reading = Meter3.query.order_by(Meter3.id.desc()).first()
meter_schema = Meter3Schema()
return meter_schema.dump(reading)
def get_all_readings_for_meter1():
readings = Meter1.query.order_by(Meter1.id.desc()).all()
schema = Meter1Schema(many=True)
data = schema.dump(readings)
return data
def get_all_readings_for_meter2():
readings = Meter2.query.order_by(Meter2.id.desc()).all()
schema = Meter2Schema(many=True)
data = schema.dump(readings)
return data
def get_all_readings_for_meter3():
readings = Meter3.query.order_by(Meter3.id.desc()).all()
schema = Meter3Schema(many=True)
data = schema.dump(readings)
return data
def get_all_readings():
m1 = get_all_readings_for_meter1()
m2 = get_all_readings_for_meter2()
m3 = get_all_readings_for_meter3()
readings = {"meter1": m1, "meter2": m2, "meter3": m3}
return readings
def get_d1_latest():
status = Device1.query.order_by(Device1.id.desc()).first()
device_schema = Device1Schema()
return device_schema.dump(status)
def get_d2_latest():
status = Device2.query.order_by(Device2.id.desc()).first()
device_schema = Device2Schema()
return device_schema.dump(status)
def get_d3_latest():
status = Device3.query.order_by(Device3.id.desc()).first()
device_schema = Device3Schema()
return device_schema.dump(status)
def get_d4_latest():
status = Device4.query.order_by(Device4.id.desc()).first()
device_schema = Device4Schema()
return device_schema.dump(status)
def get_d5_latest():
status = Device5.query.order_by(Device5.id.desc()).first()
device_schema = Device5Schema()
return device_schema.dump(status)
def get_d6_latest():
status = Device6.query.order_by(Device6.id.desc()).first()
device_schema = Device6Schema()
return device_schema.dump(status)
def get_all_status_logs_for_d1():
status_logs = Device1.query.order_by(Device1.id.desc()).all()
schema = Device1Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_logs_for_d2():
status_logs = Device2.query.order_by(Device2.id.desc()).all()
schema = Device2Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_logs_for_d3():
status_logs = Device3.query.order_by(Device3.id.desc()).all()
schema = Device3Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_logs_for_d4():
status_logs = Device4.query.order_by(Device4.id.desc()).all()
schema = Device4Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_logs_for_d5():
status_logs = Device5.query.order_by(Device5.id.desc()).all()
schema = Device5Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_logs_for_d6():
status_logs = Device6.query.order_by(Device6.id.desc()).all()
schema = Device6Schema(many=True)
data = schema.dump(status_logs)
return data
def get_all_status_changes_from_database():
d1 = get_all_status_logs_for_d1()
d2 = get_all_status_logs_for_d2()
d3 = get_all_status_logs_for_d3()
d4 = get_all_status_logs_for_d4()
d5 = get_all_status_logs_for_d5()
d6 = get_all_status_logs_for_d6()
logs = {"device 1": d1, "device 2": d2, "device 3": d3,
"device 4": d4, "device 5": d5, "device 6": d6}
return logs
def get_all_latest_logs():
d1 = get_d1_latest()
d2 = get_d2_latest()
d3 = get_d3_latest()
d4 = get_d4_latest()
d5 = get_d5_latest()
d6 = get_d6_latest()
logs = {"device 1": d1, "device 2": d2, "device 3": d3,
"device 4": d4, "device 5": d5, "device 6": d6}
return logs

134
app/services/post_services.py

@ -0,0 +1,134 @@
from flask import make_response, abort
from config import db
from models.meters import (Meter1, Meter1Schema, Meter2, Meter2Schema,
Meter3, Meter3Schema)
from models.devices import (Device1, Device1Schema, Device2, Device2Schema,
Device3, Device3Schema, Device4, Device4Schema,
Device5, Device5Schema, Device6, Device6Schema)
'''
Post Services Note
======================================================================
The functions in this file are for storing the readings taken from the
light meters in Ritherdon, and log changes in state for any of the
devices. It you are wanting to retrieve data from the (this) server,
you will need to head to the /get_services.py/ file. It should be in
the same directory as this: /services/.
'''
# This will need to change if this repo. was cloned and used for
# something outside the realm of the "Return to Ritherdon" project.
device_check_token = "QWERTYuiopasdfghjklzxcvbnm_1234567890"
def add_latest_reading(meter, info):
try:
if info["token"] == device_check_token:
reading = {"reading":info["reading"], "time":info["time"]}
if meter == 1:
return add_reading_to_meter1(reading)
elif meter == 2:
return add_reading_to_meter2(reading)
elif meter == 3:
return add_reading_to_meter3(reading)
return make_response("Meter Id. not recognised. Must be between 1 and 3.", 400)
return make_response("Invalid token.", 400)
except:
return make_response("The data you sent was invalid or incorrectly formatted.", 400)
def log_status_change(device, info):
try:
if info["token"] == device_check_token:
status = {"time":info["time"], "status":info["status"]}
if device == 1:
return add_status_change_to_device1(status)
elif device == 2:
return add_status_change_to_device2(status)
elif device == 3:
return add_status_change_to_device3(status)
elif device == 4:
return add_status_change_to_device4(status)
elif device == 5:
return add_status_change_to_device5(status)
elif device == 6:
return add_status_change_to_device6(status)
return make_response("Device Id. not recognised. Must be between 1 and 6.", 400)
return make_response("Invalid token.", 400)
except:
return make_response("The data you sent was invalid or incorrectly formatted.", 400)
'''
Nitty-Gritty Functions
======================================================================
The functions above are basically "header" functions. It makes it
easier to have multiple files open at once and see what this module
provides function-wise. The functions below do the real work in this
file. Please keep the "public" functions about this comment and defer
the main work to here. The "public" functions should be as thin as
possible to make them as scanable as possible.
'''
reading_message = "Reading successfully stored in database."
status_message = "Status change successfully logged in database."
def add_reading_to_meter1(the_reading):
schema = Meter1Schema()
new_reading = schema.load(the_reading, session=db.session)
db.session.add(new_reading)
db.session.commit()
return make_response(reading_message, 201)
def add_reading_to_meter2(the_reading):
schema = Meter2Schema()
new_reading = schema.load(the_reading, session=db.session)
db.session.add(new_reading)
db.session.commit()
return make_response(reading_message, 201)
def add_reading_to_meter3(the_reading):
schema = Meter3Schema()
new_reading = schema.load(the_reading, session=db.session)
db.session.add(new_reading)
db.session.commit()
return make_response(reading_message, 201)
def add_status_change_to_device1(status):
schema = Device1Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)
def add_status_change_to_device2(status):
schema = Device2Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)
def add_status_change_to_device3(status):
schema = Device3Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)
def add_status_change_to_device4(status):
schema = Device4Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)
def add_status_change_to_device5(status):
schema = Device5Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)
def add_status_change_to_device6(status):
schema = Device6Schema()
new_status = schema.load(status, session=db.session)
db.session.add(new_status)
db.session.commit()
return make_response(status_message, 201)

BIN
app/static/favicons/android-icon-144x144.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
app/static/favicons/android-icon-192x192.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
app/static/favicons/android-icon-36x36.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
app/static/favicons/android-icon-48x48.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
app/static/favicons/android-icon-72x72.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
app/static/favicons/android-icon-96x96.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
app/static/favicons/apple-icon-114x114.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
app/static/favicons/apple-icon-120x120.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
app/static/favicons/apple-icon-144x144.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
app/static/favicons/apple-icon-152x152.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
app/static/favicons/apple-icon-180x180.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
app/static/favicons/apple-icon-57x57.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
app/static/favicons/apple-icon-60x60.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
app/static/favicons/apple-icon-72x72.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
app/static/favicons/apple-icon-76x76.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
app/static/favicons/apple-icon-precomposed.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
app/static/favicons/apple-icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

2
app/static/favicons/browserconfig.xml

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

BIN
app/static/favicons/favicon-16x16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
app/static/favicons/favicon-32x32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
app/static/favicons/favicon-96x96.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
app/static/favicons/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

41
app/static/favicons/manifest.json

@ -0,0 +1,41 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

BIN
app/static/favicons/ms-icon-144x144.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
app/static/favicons/ms-icon-150x150.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
app/static/favicons/ms-icon-310x310.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
app/static/favicons/ms-icon-70x70.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
app/static/images/error.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
app/static/images/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
app/static/images/off.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
app/static/images/on.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

71
app/static/styles/main.css

@ -0,0 +1,71 @@
html {
font-family: arial, sans-serif;
background: #f5f5f5;
color: #424242;
}
main {
display: flex;
justify-content: center;
padding: 20px;
}
main div {
max-width: 800px;
left-margin: auto;
right-margin: auto;
}
main div .header {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
main div .header img {
width: 50px;
}
main div .header h1 {
text-align: center;
font-size: 20px;
}
main div .status-bar {
display: flex;
margin: 5px;
flex-wrap: wrap;
justify-content: space-evenly;
padding: 20px;
border-top: 2px solid #424242;
border-bottom: 2px solid #424242;
margin: 5px 0;
}
.meter {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
main div .status-bar .meter img {
width: 30px;
height: 30px;
}
.meter p {
padding: 0px;
margin: 0px;
}
main div .server-header,
main div .server-time {
margin: 0;
}
main div .server-time {
font-size: 12px;
}

440
app/swagger.yml

@ -0,0 +1,440 @@
swagger: "2.0"
info:
description: >-
The 'Return to Ritherdon' project, by Nicola Ellis, is a two year art residency at Ritherdon & Co Ltd, a manufacturer of metal enclosures based in Darwen, Lancashire U.K. This website is part of the many outcomes produced throughout the duration of project.
version: "1.0.0 - Beta"
title: Return to Ritherdon Project A.P.I.
consumes:
- application/json
produces:
- application/json
basePath: /api
paths:
# Light-Meter A.P.I. Calls
# ====================================================================
/readings/add/{light_meter}:
post:
operationId: api.post_a_reading
tags:
- Log Light-Meter Readings
summary: >-
Posts a reading from one of the project's light meters and store
it in the database.
description: >-
Use this U.R.L. to post a new reading from of the light meters
used in the project. At the time of writing, there are three
light meters taking readings in the Ritherdon factory.
It is important to note which light meter is posting the
reading. Each light meter has its own table in the database
and it will corrupt the data integrity if you post a reading
from a meter into the wrong table. At the time of writing,
there are three meters taking light reading and posting them
to here.
parameters:
- name: light_meter
in: path
description: >-
The Id. of the light meter which has taken the reading. At
the time of writing, it should be a number between 1-3.
type: integer
required: True
- name: the_reading
in: body
description: >-
The data object which represents a single light reading
from light meter 1. It conveys the time the reading was
taken and the light value it recorded. Remember, each light
has their own table in the database so make sure you do not
post the light meter reading to the wrong URL. It will
corrupt the data integrity.
required: True
schema:
type: object
properties:
time:
type: string
format: date-time
example: 2019-10-19 17:04:57
description: >-
The date and time the reading was taken. Make sure
you use the UTC time format. This is because the
A.P.I. has made a design decision to standardise on
it.
reading:
type: integer
example: 23
description: >-
This represents the amount of light the light meter
recorded. This is the most important piece of data
you will post in this data-object.
token:
type: string
example: it-is-not-password-if-you-are-wondering
description: >-
This is basically a token to check the info. sent to
the server is from a valid machine.
responses:
201:
description: >-
The reading was successfully added to the database.
400:
description: >-
The data sent to the sever was invalid or incorrectly
formatted. The most likely reasons are invalid light-meter
Id. specified and incorrect datetime format used.
/readings/latest/{light_meter}:
get:
operationId: api.get_latest
tags:
- Request Light-Meter Readings
summary: >-
Returns the latest reading from the specified light meter.
description: >-
Use this U.R.L. to retrieve the latest reading from the
light meter you specified (in the U.R.L.). At the time of
writing, the project has only three light meters and are
labelled 1-3.
parameters:
- name: light_meter
in: path
description: >-
This is the Id. of the light meter which you are retrieving
the reading for. The Id. consists of a number between 1-3
at the time of writing.
type: integer
required: True
responses:
200:
description: >-
If the server can successfully retrieve the latest reading
for the specified light meter, you should receive a JSON
object like the one below. It should include the Id. of
the light meter it was taken with, the time the reading
was taken and the reading itself.
schema:
type: object
properties:
id:
type: integer
example: 2
description: >-
This is the Id. of the light meter which took the
reading. It should be between 1-3 at the time of
writing.
time:
type: string
example: 2019-10-19 17:04:57
description: >-
The time and date the reading was taken. The A.P.I.
has standardised on the U.T.C. format.
reading:
type: integer
example: 34
description: >-
This is the actual reading taken from the specified
light meter, at the time specified in this response
body (I.E. JSON object).
400:
description: >-
The light-meter Id. specified in invalid.
/readings/all/{light_meter}:
get:
operationId: api.get_all_readings
tags:
- Request Light-Meter Readings
summary: >-
Returns every reading taken by the specified light meter.
description: >-
Use this U.R.L. to retrieve all the reading from the
light meter you specified (in the U.R.L.). At the time of
writing, the project has only three light meters and are
labelled 1-3.
parameters:
- name: light_meter
in: path
description: >-
This is the Id. of the light meter which you are retrieving
the readings for. The Id. consists of a number between 1-3
at the time of writing.
type: integer
required: True
responses:
200:
description: >-
If the server can successfully retrieve all the readings
for the specified light meter, you should receive an array
of JSON objects like the one below. It should include the
database Id. of the reading, the time the reading was
taken and the reading itself.
schema:
type: object
properties:
id:
type: integer
example: 2
description: >-
This is the database Id. of the reading.
time:
type: string
example: 2019-10-19 17:04:57
description: >-
This is the time and date the reading was taken.
The A.P.I. has standardised on the U.T.C. format.
reading:
type: integer
example: 34
description: >-
This is the actual reading taken from the specified
light meter, at the time specified in this response
body (I.E. JSON object).
400:
description: >-
The light-meter Id. specified in invalid.
/readings/all:
get:
operationId: api.get_all_readings_for_every_meter
tags:
- Request Light-Meter Readings
summary: >-
Returns every reading taken by every light meter in the
project.
description: >-
Use this U.R.L. to retrieve all the readings from every light
meter in the project. There is no example of the data returned
because I can't seem to replicate it as a YAML schema which
is understood by Swagger. Because of this, it is registered as
a free-form object. To see what the data looks like when it is
returned, I recommend you use the "Try it out!" button to see a
working example.
responses:
200:
description: >-
All the readings were successfully retrieved from the
database and delivered.
schema:
type: object
additionalProperties: True
# Device A.P.I. Calls
# ====================================================================
/status/update/{device}:
post:
operationId: api.post_a_status_change
tags:
- Log Device Status Change
summary: >-
Logs a change in the status of the specified device.
description: >-
This is mostly to check if the devices included in this project
are turned on, off or an error has occured and they are
unreachable/crashed.
parameters:
- name: device
in: path
description: >-
The Id. of the device with the change in status. 1, 2 and 3
refer to the light-meters in Ritherdon and 4, 5 and 6
refer to the relays in the gallery. The pairing of each
meter and relay is as follows: 1->4, 2->5 and 3->6.
type: integer
required: True
- name: the_status_change
in: body
description: >-
The status change and the time the change occurred.
required: True
schema:
type: object
properties:
time:
type: string
format: date-time
example: 2019-10-19 17:04:57
description: >-
The date and time the change in status occurred. Make
sure to use the U.T.C. time format. This is because
the A.P.I. has made a design decision to standardise
on it.
status:
type: string
example: "on"
description: >-
The current status of the device you would like to log.
The two status types are "on" and "off".
token:
type: string
example: it-is-not-password-if-you-are-wondering
description: >-
This is basically a token to check the info. sent to
the server is from a valid machine.
responses:
201:
description: >-
The status update was successfully added to the database.
400:
description: >-
The data sent to the sever was invalid or incorrectly
formatted. The most likely reasons are invalid device Id.
specified and incorrect datetime format used.
/status/latest/{device}:
get:
operationId: api.get_latest_device_status
tags:
- Request Device Status
summary: >-
Returns the current status of the specified device.
description: >-
Use this U.R.L. to retrieve the current status of the device
you specified (in the U.R.L.). At the time of writing, the
project has six devices in total which are split equally
between Ritherdon and the gallery. Devices 1 to 3 (light-meters)
refer to the devices in Ritherdon and 4 to 6 (relays) are in
the gallery. Each light-meter and relay should pair up in the
following ways: 1->4, 2->5 and 3->6.
parameters:
- name: device
in: path
description: >-
This is the Id. of the device which you are retrieving the
current status for. The Id. should consist of a number
between 1 and 6, at the time of writing.
type: integer
required: True
responses:
200:
description: >-
If the server can successfully retrieve the current status
for the specified device, you should receive a JSON object
like the one below. It should include the Id. of the
device, the current status and the time it was logged.
schema:
type: object
properties:
id:
type: integer
example: 2
description: >-
The is the Id. of the device.
time:
type: string
example: 2019-10-19 17:04:57
description: >-
The time the status change was logged in the
database. The A.P.I. has standardised on the
U.T.C. format.
status:
type: string
example: on
description: The current status of the device.
400:
description: >-
The device Id. specified in invalid.
/status/all/{device}:
get:
operationId: api.get_all_status_log
tags:
- Request Device Status
summary: >-
Returns every status change logged by the specified device.
description: >-
Use this U.R.L. to retrieve every change in the specified
devices state. At the time of writing, the project has six
devices and are labelled 1 to 6. Devices (light-meters) 1 to 3
are located in the Ritherdon factory and 4 to 6 (relays) in the
gallery. The light-meters and relays are paired like so, 1->4,
2->5 and 3->6.
parameters:
- name: device
in: path
description: >-
The Id. of the device you are retrieving the status change
log for. The Id. should be a number between 1 and 6.
type: integer
required: True
responses:
200:
description: >-
If the server can successfully retrieve all the status logs
for the specified device, you should receive an array of
JSON objects like the one in the example below. It should
include the database Id. of the logged status change, the
time the status change was logged and the status itself.
schema:
type: object
properties:
id:
type: integer
example: 3
description: >-
This is the database Id. of the logged status change.
time:
type: string
example: 2019-10-19 17:23:23
description: >-
The time and date the status change was logged. The
A.P.I. has standardised on the U.T.C. format.
status:
type: string
example: off
description: >-
The status of the device after the change occurred.
400:
description: >-
The device Id. specified in invalid.
/status/all:
get:
operationId: api.get_all_status_logs_for_every_device
tags:
- Request Device Status
summary: >-
Returns every logged status change of every device in the
project.
description: >-
Use this U.R.L. to retrieve every logged status change of every
device used in this project. There is no example of the data
returned because I can't seem to replicate it as a YAML schema
which is understood by Swagger. Because of this. the return
type is registered as a free-form object. To see what the data
looks like when it is returned, I recommend you use the "Try it
out!" button to see a working example.
responses:
200:
description: >-
All the logged status changes of every device were
successfully retrieved from the database and delivered.
schema:
type: object
additionalProperties: True
/status/latest:
get:
operationId: api.get_current_status_for_all_devices
tags:
- Request Device Status
summary: >-
Returns the last recorded status change of every device in the
database.
description: >-
Use this U.R.L. to retrieve the last recorded status change of
every device used in this project. There is no example of the
data returned because I can't seem to replicate it as a YAML
schema which is understood by Swagger. Because of this. the
return type is registered as a free-form object. To see what
the data looks like when it is returned, I recommend you use
the "Try it out!" button to see a working example.
responses:
200:
description: >-
The last recorded status change of every device in this
project was retrieved successfully.
schema:
type: object
additionalProperties: True

17
app/templates/favicons.html

@ -0,0 +1,17 @@
<link rel="apple-touch-icon" sizes="57x57" href="{{ url_for('static', filename='favicons/apple-icon-57x57.png') }}">
<link rel="apple-touch-icon" sizes="60x60" href="{{ url_for('static', filename='favicons/apple-icon-60x60.png') }}">
<link rel="apple-touch-icon" sizes="72x72" href="{{ url_for('static', filename='favicons/apple-icon-72x72.png') }}">
<link rel="apple-touch-icon" sizes="76x76" href="{{ url_for('static', filename='favicons/apple-icon-76x76.png') }}">
<link rel="apple-touch-icon" sizes="114x114" href="{{ url_for('static', filename='favicons/apple-icon-114x114.png') }}">
<link rel="apple-touch-icon" sizes="120x120" href="{{ url_for('static', filename='favicons/apple-icon-120x120.png') }}">
<link rel="apple-touch-icon" sizes="144x144" href="{{ url_for('static', filename='favicons/apple-icon-144x144.png') }}">
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='favicons/apple-icon-152x152.png') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='favicons/apple-icon-180x180.png') }}">
<link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='favicons/android-icon-192x192.png') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicons/favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="96x96" href="{{ url_for('static', filename='favicons/favicon-96x96.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicons/favicon-16x16.png') }}">
<link rel="manifest" href="{{ url_for('static', filename='favicons/manifest.json') }}">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="{{ url_for('static', filename='favicons/ms-icon-144x144.png') }}">
<meta name="theme-color" content="#ffffff">

82
app/templates/home.html

@ -0,0 +1,82 @@
{% extends "layout.html" %}
{% block content %}
<main>
<div>
<div class="header">
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="logo"/>
<h1>Return to Ritherdon Project</h1>
</div>
<h2 class="server-header">Artwork Status</h2>
<p class="server-time">Time on Server: {{ time }}</p>
<div class="status-bar">
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 1"].status) }}" alt="logo"/>
<p>Factory 1</p>
</div>
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 2"].status) }}" alt="logo"/>
<p>Factory 2</p>
</div>
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 3"].status) }}" alt="logo"/>
<p>Factory 3</p>
</div>
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 4"].status) }}" alt="logo"/>
<p>Gallery 1</p>
</div>
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 5"].status) }}" alt="logo"/>
<p>Gallery 2</p>
</div>
<div class="meter">
<img src="{{ url_for('static', filename='images/%s.png' % data["device 6"].status) }}" alt="logo"/>
<p>Gallery 3</p>
</div>
</div>
<h2>About the Project</h2>
<p>
"Return to Ritherdon" is a two year residency at Ritherdon & Co Ltd, a manufacturer of metal enclosures based in Darwen, Lancashire U.K.
</p>
<h2>About the Artist: Nicola Ellis</h2>
<p>Nicola is interested in the properties, value, function and circulation of materials. She has a current focus on metals and the companies that work with them, her work draws on the visual and spoken language of industry operations, fabrication and profiling processes. The parameters for her sculpture, installation, drawings and videos include relationships between people, businesses and technology.
</p>
<h2>About the Gallery: Castlefield Gallery</h2>
<p>
Established by artists in 1984, Castlefield Gallery is the first public contemporary visual art gallery to have opened in Manchester. The arrival of Castlefield Gallery in the city was a significant catalyst of what became a period of rapid cultural growth, and the increase of the presence of visual artists in the city and city region. As a registered charity, our mission drives our work to focus on artistic and career development for artists, as well as deepening audiences’ relationship to contemporary art. Over the last three decades we have become an integral part of the North of England’s cultural fabric and a vital support to artists across the North West and further afield.
</p>
<h2>About this Website</h2>
<p>
This website is part of an, unnamed, artwork which is part of the "Return to Ritherdon" project.
</p>
<h2>Links</h2>
<ul>
<li><a href="http://www.nicolaellis.com/" title="Click this to visit Nicola's personal website.">Nicola's Personal Website</a></li>
<li><a href="https://www.castlefieldgallery.co.uk/" title="Click this to visit Castlefield's website.">Castlefield's Website</a></li>
<li><a href="{{ url_for('/api./api_swagger_ui_index') }}" title="Click this to inspect this site's A.P.I.">Swagger A.P.I.</a></li>
</ul>
</div>
</main>
{% endblock content %}

26
app/templates/layout.html

@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="60">
<meta charset="utf-8">
{% if title %}
<title>Return to Ritherdon Project: {{ title }}</title>
{% else %}
<title>Return to Riterdon Project</title>
{% endif %}
<meta name="description" content="The 'Return to Ritherdon' project, by Nicola Ellis, is a two year art residency at Ritherdon & Co Ltd, a manufacturer of metal enclosures based in Darwen, Lancashire U.K. This website is part of the many outcomes produced throughout the duration of project.">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Nicola Ellis"/>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/main.css') }}">
{% include "favicons.html" %}
</head>
<body>
<!--[if IE]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience and security.</p>
<![endif]-->
{% block content %}{% endblock %}
</body>
</html>

5
app/templates/robots.txt

@ -0,0 +1,5 @@
# www.robotstxt.org/
# Disallow The Wayback Machine
User-agent: ia_archiver
Disallow:/

76
proj-env/bin/activate vendored

@ -0,0 +1,76 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "$1" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/mnt/dev-shed/midpoint/proj-env"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
if [ "x(proj-env) " != x ] ; then
PS1="(proj-env) ${PS1:-}"
else
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
fi
export PS1
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi

37
proj-env/bin/activate.csh vendored

@ -0,0 +1,37 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/mnt/dev-shed/midpoint/proj-env"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
if ("proj-env" != "") then
set env_name = "proj-env"
else
if (`basename "VIRTUAL_ENV"` == "__") then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
else
set env_name = `basename "$VIRTUAL_ENV"`
endif
endif
set prompt = "[$env_name] $prompt"
unset env_name
endif
alias pydoc python -m pydoc
rehash

75
proj-env/bin/activate.fish vendored

@ -0,0 +1,75 @@
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
# you cannot run it directly
function deactivate -d "Exit virtualenv and return to normal shell environment"
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
functions -e fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
set -e VIRTUAL_ENV
if test "$argv[1]" != "nondestructive"
# Self destruct!
functions -e deactivate
end
end
# unset irrelevant variables
deactivate nondestructive
set -gx VIRTUAL_ENV "/mnt/dev-shed/midpoint/proj-env"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# unset PYTHONHOME if set
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# fish uses a function instead of an env var to generate the prompt.
# save the current fish_prompt function as the function _old_fish_prompt
functions -c fish_prompt _old_fish_prompt
# with the original prompt function renamed, we can override with our own.
function fish_prompt
# Save the return status of the last command
set -l old_status $status
# Prompt override?
if test -n "(proj-env) "
printf "%s%s" "(proj-env) " (set_color normal)
else
# ...Otherwise, prepend env
set -l _checkbase (basename "$VIRTUAL_ENV")
if test $_checkbase = "__"
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
else
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
end
end
# Restore the return status of the previous command.
echo "exit $old_status" | .
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

10
proj-env/bin/chardetect vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from chardet.cli.chardetect import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/connexion vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from connexion.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/easy_install vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/easy_install-3.7 vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/flask vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from flask.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/gunicorn vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from gunicorn.app.wsgiapp import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(run())

10
proj-env/bin/jsonschema vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from jsonschema.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/openapi-spec-validator vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from openapi_spec_validator.__main__ import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/pip vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/pip3 vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

10
proj-env/bin/pip3.7 vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
proj-env/bin/python vendored

@ -0,0 +1 @@
python3

1
proj-env/bin/python3 vendored

@ -0,0 +1 @@
/usr/bin/python3

10
proj-env/bin/virtualenv vendored

@ -0,0 +1,10 @@
#!/mnt/dev-shed/midpoint/proj-env/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from virtualenv import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
proj-env/lib64 vendored

@ -0,0 +1 @@
lib

3
proj-env/pyvenv.cfg vendored

@ -0,0 +1,3 @@
home = /usr/bin
include-system-site-packages = false
version = 3.7.3

BIN
proj-env/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/appdirs-1.4.3-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/certifi-2018.8.24-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/chardet-3.0.4-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/colorama-0.3.7-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/distlib-0.2.8-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/distro-1.3.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/html5lib-1.0.1-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/idna-2.6-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/ipaddress-0.0.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/lockfile-0.12.2-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/packaging-19.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/pip-18.1-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/progress-1.2-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/pyparsing-2.2.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/pytoml-0.1.2-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/requests-2.21.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/retrying-1.3.3-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/setuptools-40.8.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/six-1.12.0-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/urllib3-1.24.1-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/webencodings-0.5.1-py2.py3-none-any.whl vendored

Binary file not shown.

BIN
proj-env/share/python-wheels/wheel-0.32.3-py2.py3-none-any.whl vendored

Binary file not shown.

29
requirements.txt

@ -0,0 +1,29 @@
certifi==2019.9.11
chardet==3.0.4
Click==7.0
clickclick==1.2.2
connexion==2.3.0
Flask==1.1.1
flask-marshmallow==0.10.1
Flask-SQLAlchemy==2.4.0
Flask-WTF==0.14.2
gunicorn==20.0.4
idna==2.8
inflection==0.3.1
itsdangerous==1.1.0
Jinja2==2.10.1
jsonschema==2.6.0
MarkupSafe==1.1.1
marshmallow==3.2.1
marshmallow-sqlalchemy==0.19.0
openapi-spec-validator==0.2.8
pkg-resources==0.0.0
PyYAML==5.1.2
requests==2.22.0
six==1.12.0
SQLAlchemy==1.3.8
swagger-ui-bundle==0.0.5
urllib3==1.25.5
virtualenv==16.7.9
Werkzeug==0.16.0
WTForms==2.2.1

76
ser-ver/bin/activate

@ -0,0 +1,76 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/ubuntu/www/midpoint/ser-ver"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
if [ "x(ser-ver) " != x ] ; then
PS1="(ser-ver) ${PS1:-}"
else
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
fi
export PS1
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi

37
ser-ver/bin/activate.csh

@ -0,0 +1,37 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/home/ubuntu/www/midpoint/ser-ver"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
if ("ser-ver" != "") then
set env_name = "ser-ver"
else
if (`basename "VIRTUAL_ENV"` == "__") then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
else
set env_name = `basename "$VIRTUAL_ENV"`
endif
endif
set prompt = "[$env_name] $prompt"
unset env_name
endif
alias pydoc python -m pydoc
rehash

75
ser-ver/bin/activate.fish

@ -0,0 +1,75 @@
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
# you cannot run it directly
function deactivate -d "Exit virtualenv and return to normal shell environment"
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
functions -e fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
set -e VIRTUAL_ENV
if test "$argv[1]" != "nondestructive"
# Self destruct!
functions -e deactivate
end
end
# unset irrelevant variables
deactivate nondestructive
set -gx VIRTUAL_ENV "/home/ubuntu/www/midpoint/ser-ver"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# unset PYTHONHOME if set
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# fish uses a function instead of an env var to generate the prompt.
# save the current fish_prompt function as the function _old_fish_prompt
functions -c fish_prompt _old_fish_prompt
# with the original prompt function renamed, we can override with our own.
function fish_prompt
# Save the return status of the last command
set -l old_status $status
# Prompt override?
if test -n "(ser-ver) "
printf "%s%s" "(ser-ver) " (set_color normal)
else
# ...Otherwise, prepend env
set -l _checkbase (basename "$VIRTUAL_ENV")
if test $_checkbase = "__"
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
else
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
end
end
# Restore the return status of the previous command.
echo "exit $old_status" | .
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

11
ser-ver/bin/chardetect

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from chardet.cli.chardetect import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
ser-ver/bin/connexion

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from connexion.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
ser-ver/bin/easy_install

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
ser-ver/bin/easy_install-3.7

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
ser-ver/bin/flask

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from flask.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

11
ser-ver/bin/gunicorn

@ -0,0 +1,11 @@
#!/home/ubuntu/www/midpoint/ser-ver/bin/python3.7
# -*- coding: utf-8 -*-
import re
import sys
from gunicorn.app.wsgiapp import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(run())

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