Skip to content

Commit

Permalink
initial add
Browse files Browse the repository at this point in the history
  • Loading branch information
j12y committed Aug 17, 2017
1 parent f9a48a8 commit d93dc45
Show file tree
Hide file tree
Showing 61 changed files with 182,362 additions and 2 deletions.
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
build/
dist/
eggs/
.eggs/
*.egg-info/
*.egg

# Web UI
node_modules
bower_components

# Generated docs
app/docs/html*
app/docs/doctree*

# Vendored dependencies
vendor/*

# Shell Environment
.bash_history
.cache/
.cf/

# Project-specific
environment.sh
manifest.yml

# Testing
.tox/
.coverage
coverage/
.coverage.*
nosetests.xml
coverage.xml
*,cover
.buildinfo
12 changes: 12 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

# Developers

When developing you may want to run the volcano app on your local development
machine instead of in the Predix Cloud. You can do that by running:

```
export FLASK_CONFIG=dev
python manage.py runserver
```

From there you can reference localhost.
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Copyright (c) 2017, General Electric Company.

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions aremet:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of General Electric Company or GE Digital nor the names of
their contributors, or any trademarks of General Electric Company or GE Digital
may be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn manage:app
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,56 @@
# COMING SOON

Summer 2017
# Introduction

To test our ability to digitize the natural world and take the first step
toward creating better predictive systems, GE embarked on an expedition to see
how industrial big data and predictive analytics can inform communities about
dangerous volcanic activity.

This repository is home to the source code, data, and documentation for the
Digital Volcano. The App is a simple reference demonstrating the use of Predix
Services to help you learn how to extend it. It is based on the data set
collected from industrial sensors installed in the Masaya Volcano near
Nicaragua's capital Managua.

Learn more about the project by taking the Digital Expedition and view the
sample app.

- [Digital Expedition Story][story]
- [Digtal Volcano Demo App][volcanoapp]
- [Documentation][docs]

# Getting Started

To run this application you will need to complete the following steps:

- [ ] Sign up for a [Free Predix Account][signup] (no credit card required)
- [ ] Install Python dependencies and libraries in requirements.txt
- [ ] Run from the setup directory both `create_services.py` and `ingest_data.py`
- [ ] Deploy your app with `cf push`

For more detailed descriptions of these steps view the [Getting Started Guide][quickstart].

# Predix Services Used

The following services have Free trial plans sufficient to run this
application.

- [Predix User Account and Authentication][uaa] (UAA)
- [Predix Time Series][timeseries]
- [Predix Asset][asset]
- [Predix UI][ui]
- [PredixPy][predixpy]


[![Analytics](https://ga-beacon.appspot.com/UA-82773213-1/predix-sdks/readme?pixel)](https://github.com/PredixDev)

[story]: https://ge.com/digitalvolcano
[volcanoapp]: https://predix-volcano.run.aws-usw02-pr.ice.predix.io
[docs]: https://predix-volcano.run.aws-usw02-pr.ice.predix.io/docs
[quickstart]: https://predix-volcano.run.aws-usw02-pr.ice.predix.io/docs/html/quickstart/index.html
[signup]: https://www.predix.io/registration/
[uaa]: https://www.predix.io/services/service.html?id=1172
[timeseries]: https://www.predix.io/services/service.html?id=1177
[asset]: https://www.predix.io/services/service.html?id=1171
[ui]: https://www.predix-ui.com/#/home/
[predixpy]:Include://github.com/predixpy/predixpy
26 changes: 26 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

from config import config

from flask import Flask
from flask_bower import Bower

def create_app(config_name):
app = Flask(__name__, static_folder='dashboard/static')
if not config_name in config:
raise ValueError("Invalid FLASK_CONFIG, choose one of %s" %
str.join(', ', config.keys()))
app.config.from_object(config[config_name])
config[config_name].init_app(app)

from .api_1_0 import api as api_1_0_blueprint
app.register_blueprint(api_1_0_blueprint, url_prefix='/api/1.0')

from .dashboard import dashboard
app.register_blueprint(dashboard)

from .docs import docs
app.register_blueprint(docs, url_prefix='/docs')

Bower(app)

return app
5 changes: 5 additions & 0 deletions app/api_1_0/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

from flask import Blueprint
api = Blueprint('api', __name__)

from . import volcano, node, sensor, datatype, datapoint, health
98 changes: 98 additions & 0 deletions app/api_1_0/datapoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@

import logging

from flask import jsonify
from flask import request

import predix.data.timeseries

from . import api

timeseries = predix.data.timeseries.TimeSeries()

@api.route('/datapoints')
def datapoints():
"""
Data points collected for the given nodes and sensors.
- *x*: epoch in millisecond timestamp for when data points collected
Additionally each selected sensor will be returned as the key with the
corresponding value being the reading for the timestamp.
.. http:get:: /api/1.0/datapoints?node=/node/c5e39fa0&sensor=GP_CO2
Responds with collected data for node and sensor.
**Example request**:
.. sourcecode:: http
GET /api/1.0/datapoints? HTTP/1.1
Host: predix-volcano.run.aws-usw02-pr.ice.predix.io
Accept: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"GP_CO2": 32.035,
"x": 1471421209000
},
{
"GP_CO2": 32.035,
"x": 1471423009000
},
{
"GP_CO2": 32.035,
"x": 1471424807000
},
{
"GP_CO2": 32.035,
"x": 1471426606000
},
...
]
"""
# TODO: better error handling for no node/sensors selected
node = request.args.get('node')
sensors = request.args.get('sensor').split(',')
logging.debug("Query: %s, %s" % (node, sensors))

response = timeseries.get_datapoints(sensors, start='5y-ago', limit=10000,
attributes={'node': node})

# get_datapoints() returns data like this...
# {"tags": [{"name": "HUMA", "results": [{"values": [
# [1471266639000,83.3,1],
# [1471270237000,87.2,1], ... ]}]},
# {"name": "PA", "results": [{"values": [ ... ]}]}]}
# We need to transform it for px-vis-timeseries which expects this...
# [{'x': 1471266639000, 'TAG1': 83.3, 'TAG2': 57.3}, ...]
#
# [{'x': 1471266639000, 'TAG1': 83.3}, {'x': 1471266639000, 'TAG2':
# 57.3}] does not
# and requires them to be sorted by x to render properly

data = {}
for tag in response['tags']:
name = tag['name']
for result in tag['results']:
for value in result['values']:
timestamp = value[0]
if timestamp not in data:
data[timestamp] = {'x': timestamp}

data[timestamp][name] = value[1]

datapoints = []
for key in sorted(data.keys()):
datapoints.append(data[key])

return jsonify(datapoints)
80 changes: 80 additions & 0 deletions app/api_1_0/datatype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

from flask import jsonify

import predix.data.asset

from . import api

asset = predix.data.asset.Asset()

@api.route('/datatypes')
def datatypes():
"""
Resource representing data types available.
.. http:get:: /api/1.0/datatypes
Responds with a list of available datatypes.
**Example request**:
.. sourcecode:: http
GET /api/1.0/datatypes HTTP/1.1
Host: predix-volcano.run.aws-usw02-pr.ice.predix.io
Accept: application/json
[
{
"data_type": "temperature",
"tag": "TCA",
"unit": "celcius",
"uri": "/datatype/35dcb3c0-8679-11e6-bda3-ef77801087ee"
},
{
"data_type": "pressure",
"tag": "PA",
"unit": "pascal",
"uri": "/datatype/35dcb3c1-8679-11e6-bda3-ef77801087ee"
},
...
]
"""
datatypes = asset.get_collection('/datatype')
return jsonify(datatypes)

@api.route('/datatype/<guid>')
def datatype(guid):
"""
A specific datatype instance.
.. http:get:: /api/1.0/datatype/:guid
Responds with metadata for a single data type
**Example request**:
.. sourcecode:: http
GET /api/1.0/datatype/35dcb3c2-8679-11e6-bda3-ef77801087ee HTTP/1.1
Host: predix-volcano.run.aws-usw02-pr.ice.predix.io
Accept: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Content-Type: application/json
{
"data_type": "humidity",
"tag": "HUMA",
"unit": "relative humidity",
"uri": "/datatype/35dcb3c2-8679-11e6-bda3-ef77801087ee"
}
"""
datatypes = asset.get_collection("/datatype/%s" % (guid))
return jsonify(datatypes[0])
Loading

0 comments on commit d93dc45

Please sign in to comment.