diff --git a/.idea/workspace.xml b/.idea/workspace.xml index ce51060..71e2364 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,8 +2,17 @@ + + + + + + + + + @@ -46,6 +55,24 @@ @@ -207,6 +333,7 @@ frictionEstimate simLoops fill + arraycopy @@ -620,8 +747,8 @@ @@ -637,14 +764,13 @@ - - + @@ -657,65 +783,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -988,8 +1056,8 @@ - - + + @@ -1006,7 +1074,7 @@ - + @@ -1067,14 +1135,6 @@ - - - - - - - - @@ -1089,7 +1149,29 @@ - + + + + + + + + + + + + + + + + + + + + + + + @@ -1098,7 +1180,7 @@ - + @@ -1107,7 +1189,25 @@ - + + + + + + + + + + + + + + + + + + + @@ -1123,7 +1223,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1142,7 +1316,7 @@ - + @@ -1165,7 +1339,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1173,7 +1421,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1304,13 +1626,6 @@ - - - - - - - @@ -1332,32 +1647,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1370,15 +1659,6 @@ - - - - - - - - - @@ -1386,7 +1666,25 @@ - + + + + + + + + + + + + + + + + + + + @@ -1394,7 +1692,81 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1402,14 +1774,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..22dee7d --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Henry POC +## Written in Java for Intel Edison Board + +# Edison Configuration +After configuring the Intel Edison via the config utility, software should be installed: + +## SD Card Configuration +The Mongo DB will be stored on the SD card. This will ensure that the OS partition does not fill up. Insert an SD Card formatted to FAT32 into the SD card slot. +``` +mkdir /media/sdcard/db +mkdir /data +ln -s /media/sdcard/db /data/db +``` + + + + +## Mongo DB +We'll be installing version 2.6.12 since it's the last version to support 32-bit OS. +``` +cd ~ +wget https://fastdl.mongodb.org/linux/mongodb-linux-i686-2.6.12.tgz +mkdir ~/bin +cd ~/bin +tar -xvzf ../mongodb-linux-i686-2.6.12.tgz +``` + +Create a systemd script at /etc/systemd/system/mongod.service with the contents: +``` +[Unit] +Description=Mongo is a scalable, document-oriented database. +After=syslog.target network.target + +[Service] +ExecStart=/home/root/bin/mongodb-linux-i686-2.6.12/bin/mongod --journal + +[Install] +WantedBy=multi-user.target +``` + +Enable the systemd script with: +``` +systemctl enable mongod.service +``` diff --git a/src/main/java/com/henrypump/poc/Database.java b/src/main/java/com/henrypump/poc/Database.java index 046b9f6..d398654 100644 --- a/src/main/java/com/henrypump/poc/Database.java +++ b/src/main/java/com/henrypump/poc/Database.java @@ -15,6 +15,9 @@ import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.Sorts; import org.bson.Document; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; import java.time.ZonedDateTime; import com.mongodb.client.MongoCursor; @@ -234,4 +237,69 @@ public class Database { collection.insertOne(doc); return collection.count(); } + + static String readFile(String file) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(file)); + String line = null; + StringBuilder stringBuilder = new StringBuilder(); + String ls = System.getProperty("line.separator"); + + try { + while((line = reader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append(ls); + } + + return stringBuilder.toString(); + } finally { + reader.close(); + } + } + + public long storeWellSetup(Well thisWell){ + MongoCollection collection = database.getCollection("wellConfiguration"); + + ArrayList taperArr = new ArrayList(); + for (int i = 1; i <= thisWell.getNumTapers(); i++){ + Document tap = new Document("length", thisWell.getRodLength(i)) + .append("diameter", thisWell.getRodDiameter(i)) + .append("material", thisWell.getRodMaterial(i)) + .append("dampingFactor", thisWell.getDampingFactor(i)); + taperArr.add(tap); + } + + + Document doc = new Document("timestamp", Date.from(ZonedDateTime.now().toInstant())) + .append("wellName", thisWell.getWellName()) + .append("deltaT", thisWell.getDt()) + .append("pumpDiameter", thisWell.getPumpDiameter()) + .append("fluidGradient", thisWell.getFluidGradient()) + .append("tubingID", thisWell.getTubingID()) + .append("tubingOD", thisWell.getTubingOD()) + .append("tubingAnchorDepth", thisWell.getTubingAnchorDepth()) + .append("structuralRating", thisWell.getStructuralRating()) + .append("stuffingBoxFriction", thisWell.getSbfriction()) + .append("tubingHeadPressure", thisWell.getTubingHeadPressure()) + .append("tapers", taperArr) + .append("storedBy", "poc"); + + collection.insertOne(doc); + return collection.count(); + } + + public Document getLatestWellConfiguration(){ + MongoCollection wellConfigCollection = database.getCollection("wellConfiguration"); + MongoCursor cursor = wellConfigCollection.find().sort(Sorts.descending("timestamp")).limit(1).iterator(); + Document lastConfig = new Document(); + try { + while (cursor.hasNext()) { + lastConfig = cursor.next(); + } + } finally { + cursor.close(); + } + return lastConfig; + } + + } diff --git a/src/main/java/com/henrypump/poc/IOControl.java b/src/main/java/com/henrypump/poc/IOControl.java index a910d5b..16200d1 100644 --- a/src/main/java/com/henrypump/poc/IOControl.java +++ b/src/main/java/com/henrypump/poc/IOControl.java @@ -15,8 +15,8 @@ public class IOControl implements Runnable { IOControl(POC poc){ this.poc = poc; // IO - startBtn = new DigitalIn(8); - stopBtn = new DigitalIn(9); + startBtn = new DigitalIn(99); + stopBtn = new DigitalIn(99); led2 = new DigitalOut(2, 0); led3 = new DigitalOut(3, 0); led4 = new DigitalOut(4, 0); diff --git a/src/main/java/com/henrypump/poc/POC.java b/src/main/java/com/henrypump/poc/POC.java index a04c528..556e2ae 100644 --- a/src/main/java/com/henrypump/poc/POC.java +++ b/src/main/java/com/henrypump/poc/POC.java @@ -11,24 +11,22 @@ import java.time.ZonedDateTime; public class POC implements Runnable{ protected Well thisWell; private Thread t; - - private boolean ioEnabled; - POC(String wellSetupJsonFile, String dbHostname){ + POC(String dbHostname){ ioEnabled = true; thisWell = new Well(dbHostname, 99, 99, 7); - thisWell.parseJSONFile(wellSetupJsonFile); + thisWell.getWellSetup(); } - POC(String wellSetupJsonFile, String simFileName, boolean ioEnabled, String dbHostname){ + POC(String simFileName, boolean ioEnabled, String dbHostname){ this.ioEnabled = ioEnabled; if (this.ioEnabled) { thisWell = new Well(dbHostname, simFileName,99, 99, 7); } else { thisWell = new Well(dbHostname, simFileName,99, 99, 99); } - thisWell.parseJSONFile(wellSetupJsonFile); + thisWell.getWellSetup(); } @@ -41,18 +39,15 @@ public class POC implements Runnable{ thisWell.setupFluidRatio(0.50, 0.50, 1.12); thisWell.checkSafeties(); while (true) { -// while (thisWell.getRunStatus() == Well.RUNSTATUS_RUNNING || thisWell.getRunStatus() == Well.RUNSTATUS_STARTING) { - for (int i = 0; i <= thisWell.sim.getLastFilledIndex(); i++) { + for (int i = 0; i <= thisWell.sim.getLastFilledIndex(); i++) { + thisWell.eval(i); - thisWell.eval(i); - - try { - Thread.sleep(sleepMilliseconds); - } catch (InterruptedException e) { - e.printStackTrace(); - } + try { + Thread.sleep(sleepMilliseconds); + } catch (InterruptedException e) { + e.printStackTrace(); } -// } + } } } @@ -67,12 +62,41 @@ public class POC implements Runnable{ public static void main(String[] args) { + if (args[0].equals("help")){ + System.out.println("Pass command line parameters..."); + System.out.println("============="); + System.out.println(""); + System.out.println("Simulation Mode:"); + System.out.println("-------------"); + System.out.println(" "); + System.out.println(""); + System.out.println("IO Mode:"); + System.out.println("-------------"); + System.out.println(""); + System.out.println(""); + System.out.println("If updating config via json file, place a config file named 'wellSetup.json' in the project directory."); + System.exit(2); + } + + String dbHostname = "localhost"; if (args.length > 3){ dbHostname = args[3]; } - final POC thisPOC = new POC(args[0], args[1], args[2].equals("true"), dbHostname); - thisPOC.start(); + + if (args.length == 1){ + dbHostname = args[1]; + } + + if (args.length < 2){ + final POC realPOC = new POC(dbHostname); + realPOC.start(); + } else { + final POC simPOC = new POC(args[0], args[1].equals("true"), dbHostname); + simPOC.start(); + } + + } } diff --git a/src/main/java/com/henrypump/poc/Well.java b/src/main/java/com/henrypump/poc/Well.java index 1c38680..453ba9c 100644 --- a/src/main/java/com/henrypump/poc/Well.java +++ b/src/main/java/com/henrypump/poc/Well.java @@ -6,19 +6,21 @@ import de.vandermeer.asciitable.v2.V2_AsciiTable; import de.vandermeer.asciitable.v2.render.V2_AsciiTableRenderer; import de.vandermeer.asciitable.v2.render.WidthAbsoluteEven; import de.vandermeer.asciitable.v2.themes.V2_E_TableThemes; +import org.bson.Document; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; - import static java.lang.Math.exp; import static java.lang.Math.pow; import static java.lang.Math.sqrt; - +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.nio.file.*; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; /** * Created by patrickjmcd on 1/31/17. @@ -117,7 +119,7 @@ public class Well { private int direction = DIRECTION_UNKNOWN; private int lastDirection = DIRECTION_UNKNOWN; - // Modes + // MODES private volatile int runMode; public static final int RUNMODE_POC = 0; public static final int RUNMODE_MANUAL = 1; @@ -601,10 +603,13 @@ public class Well { return wtPerFt; }; - void parseJSONFile(String jsonFilename){ + void getWellSetup(){ + String jsonFilename = "wellSetup.json"; JSONParser parser = new JSONParser(); try { + Object obj = parser.parse(new FileReader(jsonFilename)); + System.out.println("Reading well configuration from JSON file 'wellSetup.json"); JSONObject well = (JSONObject) obj; Object newWellName = well.get("wellName"); @@ -656,8 +661,65 @@ public class Well { if (newDampingFactor != null) setDampingFactor(currentTaperNum, (Double) newDampingFactor); } + Path fromFile = Paths.get(jsonFilename); + Path toFile = Paths.get(jsonFilename + ".bak"); + Files.move(fromFile, toFile); + + } catch (FileNotFoundException e) { + System.out.println("No configuration file found. Pulling latest value from database."); + Document newConfigDoc = db.getLatestWellConfiguration(); + + Object newWellName = newConfigDoc.get("wellName"); + if (newWellName != null) wellName = (String) newWellName; + + Object newDeltaT = newConfigDoc.get("deltaT"); + if (newDeltaT != null) dt = (Double) newDeltaT; + + Object newPumpDiameter = newConfigDoc.get("pumpDiameter"); + if (newPumpDiameter != null) setPumpDiameter((Double) newPumpDiameter); + + Object newFluidGradient = newConfigDoc.get("fluidGradient"); + if (newFluidGradient != null) fluidGradient = (Double) newFluidGradient; + + Object newTubingID = newConfigDoc.get("tubingID"); + if (newTubingID != null) setTubingID((Double) newTubingID); + + Object newTubingOD = newConfigDoc.get("tubingOD"); + if (newTubingOD != null) setTubingOD((Double) newTubingOD); + + Object newTubingAnchorDepth = newConfigDoc.get("tubingAnchorDepth"); + if (newTubingAnchorDepth != null) tubingAnchorDepth = (Double) newTubingAnchorDepth; + + Object newStructuralRating = newConfigDoc.get("structuralRating"); + if (newStructuralRating != null) structuralRating = (Double) newStructuralRating; + + Object newStuffingBoxFriction = newConfigDoc.get("stuffingBoxFriction"); + if (newStuffingBoxFriction != null) setSbfriction((Double) newStuffingBoxFriction); + + Object newTubingHeadPressure = newConfigDoc.get("tubingOD"); + if (newTubingHeadPressure != null) setTubingOD((Double) newTubingHeadPressure); + + ArrayList tapers = (ArrayList) newConfigDoc.get("tapers"); + numTapers = tapers.size(); + for (int i = 0; i < numTapers; i++) { + int currentTaperNum = i + 1; + Document taperObj = tapers.get(i); + + Object newLength = taperObj.get("length"); + if (newLength != null) setRodLength(currentTaperNum, (Double) newLength); + + Object newDiameter = taperObj.get("diameter"); + if (newDiameter != null) setRodDiameter(currentTaperNum, (Double) newDiameter); + + Object newMaterial = taperObj.get("material"); + if (newMaterial != null) setRodYM(currentTaperNum, (String) newMaterial); + + Object newDampingFactor = taperObj.get("dampingFactor"); + if (newDampingFactor != null) setDampingFactor(currentTaperNum, (Double) newDampingFactor); + } } catch (IOException | ParseException e) { e.printStackTrace(); + System.exit(3); } updateTapers(); @@ -822,6 +884,9 @@ public class Well { if (dbFrictionEstimate != -1){ frictionEstimate = dbFrictionEstimate; } + + + db.storeWellSetup(this); } private double position(int p) @@ -1182,7 +1247,7 @@ public class Well { public static void main( String[] args ){ Well thisWell = new Well(args[1], 99, 99, 99); - thisWell.parseJSONFile(args[0]); + thisWell.getWellSetup(); thisWell.printTapers(); } diff --git a/www/pocwww/pocwww/__init__.py b/www/pocwww/pocwww/__init__.py index 86df0a9..87317ea 100644 --- a/www/pocwww/pocwww/__init__.py +++ b/www/pocwww/pocwww/__init__.py @@ -137,9 +137,14 @@ def main(global_config, **settings): config.add_route('welltests_all', '/welltests') config.add_route('json_welltests_all', '/json/welltests') + config.add_route('runstatus_page', '/runstatus/{page_num}') config.add_route('runstatus', '/runstatus') + config.add_route('json_runstatus_page', '/json/runstatus/{page_num}') config.add_route('json_runstatus', '/json/runstatus') + config.add_route('json_config', '/json/config') + config.add_route('config', '/config') + # JSON-ONLY ROUTES config.add_route('json_lastcard', "/json/lastcard") config.add_route('json_runstatusnow', "/json/runstatusnow") diff --git a/www/pocwww/pocwww/templates/config.jinja2 b/www/pocwww/pocwww/templates/config.jinja2 new file mode 100644 index 0000000..50e1e25 --- /dev/null +++ b/www/pocwww/pocwww/templates/config.jinja2 @@ -0,0 +1,68 @@ +{% from 'pagination.jinja2' import render_pagination %} +{% extends "layout.jinja2" %} + +{% block content %} +
+
+
+

Well Configuration

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+ +
+
+
+
+{% endblock content %} diff --git a/www/pocwww/pocwww/templates/dashboard.jinja2 b/www/pocwww/pocwww/templates/dashboard.jinja2 index 225a6fd..2258f2a 100644 --- a/www/pocwww/pocwww/templates/dashboard.jinja2 +++ b/www/pocwww/pocwww/templates/dashboard.jinja2 @@ -71,5 +71,9 @@ success: drawCards }); + $(function () { + $('[data-toggle="popover"]').popover({html: true}) + }) + {% endblock content %} diff --git a/www/pocwww/pocwww/templates/layout.jinja2 b/www/pocwww/pocwww/templates/layout.jinja2 index 512af19..1893b4a 100644 --- a/www/pocwww/pocwww/templates/layout.jinja2 +++ b/www/pocwww/pocwww/templates/layout.jinja2 @@ -63,7 +63,7 @@
  • Gauge-Off
  • Fluid Shots
  • Well Tests
  • -
  • Configuration
  • +
  • Configuration
  • diff --git a/www/pocwww/pocwww/templates/runstatus.jinja2 b/www/pocwww/pocwww/templates/runstatus.jinja2 index a164774..b050ff1 100644 --- a/www/pocwww/pocwww/templates/runstatus.jinja2 +++ b/www/pocwww/pocwww/templates/runstatus.jinja2 @@ -1,3 +1,4 @@ +{% from 'pagination.jinja2' import render_pagination %} {% extends "layout.jinja2" %} {% block content %} @@ -6,6 +7,9 @@

    Run Status Log

    {% if data|length > 0 %} +
    + {{render_pagination(pagination, "/runstatus")}} +
    @@ -27,7 +31,7 @@
    {% else %} -

    No fluid shots yet...

    +

    No statuses stored yet...

    {% endif %}
    diff --git a/www/pocwww/pocwww/views.py b/www/pocwww/pocwww/views.py index d771010..6f01d08 100644 --- a/www/pocwww/pocwww/views.py +++ b/www/pocwww/pocwww/views.py @@ -1,5 +1,6 @@ from pyramid.view import view_config from datetime import datetime, timedelta +from math import ceil from .view_helpers import * @@ -117,6 +118,24 @@ def welltests_all(request): @view_config(route_name="runstatus", renderer="templates/runstatus.jinja2") @view_config(route_name="json_runstatus", renderer="prettyjson") -def welltests_all(request): - runStatuses = list(request.db['runStatus'].find()) - return {'navgroup': 'runstatus', 'data': runStatuses} +@view_config(route_name="runstatus_page", renderer="templates/runstatus.jinja2") +@view_config(route_name="json_runstatus_page", renderer="prettyjson") +def run_status(request): + page_num = 1 + try: + page_num = int(request.matchdict['page_num']) + except KeyError: + pass + + num_per_page = 100 + num_cards = request.db['runStatus'].count() + pages = ceil(num_cards / num_per_page) + runStatuses = list(request.db['runStatus'].find().sort("timestamp", -1).skip(num_per_page * (page_num - 1)).limit(num_per_page)) + return {'navgroup': 'runstatus', 'data': runStatuses, 'pagination': Pagination(page_num, num_per_page, num_cards)} + + +@view_config(route_name="config", renderer="templates/config.jinja2") +@view_config(route_name="json_config", renderer="prettyjson") +def well_config(request): + current_configuration = list(request.db['wellConfiguration'].find().sort("timestamp", -1).limit(1))[0] + return {'navgroup': 'config', 'config': current_configuration}