Merged feature/config-page into develop

This commit is contained in:
Patrick McDonagh
2016-02-05 14:59:14 -06:00
11 changed files with 375 additions and 24 deletions

View File

@@ -21,14 +21,14 @@ case "$1" in
# run application you want to start
#python /home/poconsole/src/dataLogger/alarmLogger.py &
#python /home/poconsole/src/dataLogger/dataLogger.py &
/usr/bin/python /home/poconsole/tagserver/python/tagserver_SQLite.py > /dev/null 2>&1 & echo $! > "/root/solar_ww.pid"
/usr/bin/python /home/poconsole/tagserver/python/tagserver_SQLite.py > /dev/null 2>&1 & echo $! > "/root/tagserver.pid"
;;
stop)
echo "Stopping loggers"
# kill application you want to stop
#killall python
kill -9 $(cat /root/solar_ww.pid)
kill -9 $(cat /root/tagserver.pid)
;;
*)
@@ -37,4 +37,4 @@ case "$1" in
;;
esac
exit 0
exit 0

View File

@@ -37,5 +37,4 @@ case "$1" in
;;
esac
exit 0
exit 0

View File

@@ -37,20 +37,50 @@ def readTag(addr, tag):
c.close()
def main():
with con:
cur = con.cursor()
query = "SELECT * FROM tags WHERE deleted = 0;"
cur.execute(query)
tags = cur.fetchall()
PLC_IP_ADDRESS = "10.10.10.3" # MAKE THIS A db VALUE
scan_rate = 10
configObj = {}
with con:
cur = con.cursor()
query = "SELECT parameter, val FROM config GROUP BY parameter;"
cur.execute(query)
config = cur.fetchall()
for x in config:
configObj[x[0]] = x[1]
try:
PLC_IP_ADDRESS = str(configObj['ip_address'])
print("FYI, using PLC IP Address from the database {0}".format(PLC_IP_ADDRESS))
except KeyError:
print("FYI, there is no PLC IP Address stored in the database, defaulting to 192.168.1.10")
PLC_IP_ADDRESS = "192.168.1.10"
try:
scan_rate = int(configObj['scan_rate'])
print("FYI, using Scan Rate from the database {0}".format(scan_rate))
except KeyError:
print("FYI, there is no Scan Rate stored in the database, defaulting to 10 seconds")
scan_rate = 10
tagList = []
print("\nScan List\n--------------")
if len(tags) > 0:
for t in tags:
tagList.append({"id": int(t[0]), "name": t[1], "val": None, "lastVal": None})
print(tagList)
print(t[1])
print("--------------\n")
while True:
try:
@@ -61,7 +91,7 @@ def main():
with con:
cur = con.cursor()
aQuery = """INSERT INTO vals (tagID, val) VALUES ('%d', '%f');""" % (r["id"], float(r["val"]))
print(aQuery)
# print(aQuery)
cur.execute(aQuery)
con.commit()
r["lastVal"] = r["val"]

View File

@@ -65,17 +65,22 @@ var angular = function(req, res) {
res.render('angularIndex');
};
app.post('/json/tag/add', fns.createTag); // Adds a tag to the scan list
app.post('/json/tag/update/', fns.updateTag); // Updates tag data
app.get('/json/tag/delete/:tag', fns.deleteTag); // Removes a tag from the scan list
app.get('/json/tag/:id', fns.getTag); // Lists all tags in the scan list
app.get('/json/tag', fns.getAllTags); // Lists all tags in the scan list
app.get('/json/val/:tag', fns.latestValueSingleTag); // Gets the latest value of a single tag
app.get('/json/series/:tag/:hours', fns.seriesTagValues); // Gets all the values of a tag for the last X hours
app.get('/json/valBetween/:tag/:startDatetime/:endDatetime', fns.seriesTagValuesBetween); // Gets the latest value of a single tag
app.get('/json/CSV/:tag/:startDatetime/:endDatetime', fns.seriesCSV); // Gets all the values of a tag for the last X hours
app.get('/json/CSV/:tag/:hours', fns.seriesCSV); // Gets all the values of a tag for the last X hours
app.get('/json/all', fns.latestValueAllTags); // Gets the latest values of all tags in the scan list
app.post('/json/tag/add', fns.createTag); // Adds a tag to the scan list
app.post('/json/tag/update/', fns.updateTag); // Updates tag data
app.get('/json/tag/delete/:tag', fns.deleteTag); // Removes a tag from the scan list
app.get('/json/tag/:id', fns.getTag); // Gets a specific tag in the scan list
app.get('/json/tag', fns.getAllTags); // Lists all tags in the scan list
app.get('/json/val/:tag', fns.latestValueSingleTag); // Gets the latest value of a single tag
app.get('/json/series/:tag/:hours', fns.seriesTagValues); // Gets all the values of a tag for the last X hours
app.get('/json/valBetween/:tag/:startDatetime/:endDatetime', fns.seriesTagValuesBetween); // Gets the values of a tag between the start time and end time
app.get('/json/CSV/:tag/:startDatetime/:endDatetime', fns.seriesCSV); // Gets a CSV of the values of a tag between the start time and end time
app.get('/json/CSV/:tag/:hours', fns.seriesCSV); // Gets a CSV of the values of a tag for the last x hours
app.get('/json/all', fns.latestValueAllTags); // Gets the latest values of all tags in the scan list
app.get('/json/config', fns.getSetup); // Gets the contents of the config table
app.post('/json/config', fns.updateSetup); // Adds a new parameter to the config table
app.get('/json/logger/status', fns.checkLoggerStatus); // Gets the status of the data logger
app.get('/json/logger/restart', fns.restartLogger); // Restarts the data logger
app.get('*', angular);

View File

@@ -16,3 +16,10 @@ CREATE TABLE IF NOT EXISTS vals (
val REAL,
dateAdded TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS config (
id INTEGER PRIMARY KEY,
parameter TEXT,
val TEXT,
dateAdded TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@@ -277,3 +277,79 @@ exports.latestValueAllTags = function(req, res){
});
});
};
exports.checkLoggerStatus = function(req, res){
var fs = require('fs');
// var ps = require("ps-node");
var running = require("is-running");
fs.readFile('/root/tagserver.pid', function (derr,ddata) {
if (derr) {
console.log("Problem getting PID of tagserver");
res.json({status:"error", message: "Problem getting PID of tagserver"});
} else {
res.json({status: "OK", running: running(ddata)});
}
});
};
exports.restartLogger = function(req, res){
var exec = require('child_process').exec;
exec('/etc/init.d/loggers start', function(error, stdout, stderr){
if (error){
res.json({status:"error", message:error});
} else {
res.json({status:"OK"});
}
});
};
exports.getSetup = function(req, res){
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(dbFile);
var query = "SELECT parameter, val, dateAdded FROM config GROUP BY parameter;";
var prepQuery = db.prepare(query);
prepQuery.all(req.params.id, function(err, rows) {
prepQuery.finalize();
db.close();
if (err) {
res.json({status:"error", message:err});
console.log(err);
} else {
res.json({status:"OK", config:rows});
}
});
};
exports.updateSetup = function(req, res){
var exec = require('child_process').exec;
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(dbFile);
console.log(req.body.parameter, req.body.val);
db.serialize(function(){
var query = db.prepare('INSERT INTO config (parameter, val) VALUES (?, ?)');
query.run(req.body.parameter, req.body.val, function(err) {
query.finalize();
db.close();
if (err) {
console.log({runErr:err});
res.json({status:"error", message:err, query:query});
} else {
res.redirect("/#/setup");
exec('/etc/init.d/loggers stop', function(error, stdout, stderr){
if (error){
console.log({status:"error", message:error, query:query});
}
setTimeout(function(){
exec('/etc/init.d/loggers start', function(error, stdout, stderr){
if (error){
console.log({status:"error", message:error, query:query});
}
});
},5000);
});
}
});
});
};

View File

@@ -13,7 +13,8 @@
"mysql": "*",
"serve-favicon": "*",
"sqlite3": "*",
"n3-charts": "*"
"n3-charts": "*",
"is-running": "*"
},
"devDependencies": {},
"scripts": {

View File

@@ -246,6 +246,82 @@ tsCtrlrs.factory('tags',function($q, $http, $log){
};
});
tsCtrlrs.factory('config',function($q, $http, $log){
var getConfig = function(){
var deferred = $q.defer();
$http.get('/json/config/').success(function(data) {
if(data.status == "OK"){
deferred.resolve({
config:data.config,
status: data.status
});
} else {
deferred.resolve({
status:data.status,
message: data.message
});
}
});
return deferred.promise;
};
var submitParameter = function(entry){
$http.post('/json/config', {
parameter: entry.parameter,
val: entry.val
}).success(function(data){
return data;
});
};
var getLoggerStatus = function(){
var deferred = $q.defer();
$http.get('/json/logger/status').success(function(data) {
if(data.status == "OK"){
deferred.resolve({
running:data.running,
status: data.status
});
} else {
deferred.resolve({
status:data.status,
message: data.message,
});
}
});
return deferred.promise;
};
var restartLogger = function(){
var deferred = $q.defer();
$http.get('/json/logger/restart').success(function(data) {
if(data.status == "OK"){
deferred.resolve({
status: data.status
});
} else {
deferred.resolve({
status:data.status,
message: data.message
});
}
});
return deferred.promise;
};
return {
getConfig:getConfig,
submitParameter: submitParameter,
getLoggerStatus: getLoggerStatus,
restartLogger: restartLogger
};
});
tsCtrlrs.controller('mainCtrl', function($scope, Page, Alerts) {
$scope.Page = Page;
$scope.Alerts = Alerts;
@@ -408,6 +484,80 @@ tsCtrlrs.controller('tagValsCtrl', function($scope, $route, $http, $routeParams,
$scope.loadTagVals($scope.startDatetime, $scope.endDatetime);
});
tsCtrlrs.controller('configCtrl', function($scope, Page, Alerts, $log, config) {
Page.setTitle('Configuration');
Page.setPage('configuration');
$scope.loadConfig = function(){
$scope.loading = true;
var getConfig = config.getConfig();
getConfig.then(function(data) {
$scope.loading = false;
if (data.status == "OK"){
$scope.config = data.config;
$scope.error = false;
} else {
$scope.error = data.message;
}
});
};
$scope.loadConfig();
$scope.paramError = null;
var selString = "Select a parameter...";
$scope.newParam = {
pSelected: selString,
parameter: null,
val: null
};
$scope.addParameter = function(){
if ($scope.newParam.pSelected == selString){
$scope.paramError = "No parameter selected";
} else {
if ($scope.newParam.pSelected == "other") {
$scope.newParam.parameter = $scope.newParam.pEntry;
} else {
$scope.newParam.parameter = $scope.newParam.pSelected;
}
config.submitParameter($scope.newParam);
$scope.loadConfig();
}
};
$scope.checkLogger = function(){
$scope.loggerLoading = true;
var checkLoggerStatus = config.getLoggerStatus();
checkLoggerStatus.then(function(data){
$scope.loggerLoading = false;
if (data.status == "OK"){
$scope.loggerRunning = data.running;
$scope.error = false;
} else {
$scope.error = data.message;
}
});
};
$scope.checkLogger();
$scope.restartLogger = function(){
var restartLogger = config.restartLogger();
restartLogger.then(function(data){
if (data.status == "OK"){
$scope.error = false;
$scope.checkLogger();
} else {
$scope.error = data.message;
}
});
};
});
//*---- FILTERS -----*//
tsCtrlrs.filter('dString', function myDateFormat($filter){
return function(text){
var tempdate= new Date(text);

View File

@@ -11,6 +11,9 @@ tagserver.config([
}).when('/tag/:tagID', {
templateUrl: '/partials/tagVals.html',
controller: 'tagValsCtrl'
}).when('/config', {
templateUrl: '/partials/config.html',
controller: 'configCtrl'
}).when('/', {
templateUrl: '/partials/dashboard.html',
controller: 'dashboardCtrl'

View File

@@ -0,0 +1,80 @@
<div ng-if="loading" class="container">
<div class="row">
<div class="col-md-12 well" style="text-align:center;">
<h1>Loading Config...</h1>
<img class="img-responsive" src="/img/loading.gif" style="margin:0 auto;"/>
</div>
</div>
</div>
<div ng-if="!loading">
<div ng-if="error" class="container">
<div class="row">
<div class="col-md=12">
<h1>Error Caught!</h1>
<pre>{{message}}</pre>
<button ng-click="loadDashboard()" class="btn btn-large btn-danger"><i class="fa fa-refresh"></i> Reload Dashboard</button>
</div>
</div>
</div>
<div ng-if="!error" class="container">
<div class="row well">
<div class="col-md-12">
<h1 ng-if="!loggerLoading">Logger Status:
<span ng-if="loggerRunning" class="label label-success">Running</span>
<span ng-if="!loggerRunning" class="label label-danger">Not Running</span>
</h1>
<h1 ng-if="loggerLoading">
<span class="label label-warning">Checking Logger Status...</span>
</h1>
<button class="btn btn-primary btn-large" ng-click="checkLogger()">Check Logger</button> <button class="btn btn-warning btn-large" ng-click="restartLogger()">Restart Logger</button>
</div>
</div>
<div class="row">
<h1>Configuration Parameters</h1>
<button ng-click="loadConfig()" class="btn btn-large btn-success"><i class="fa fa-refresh"></i> Reload Config</button>
<table class="table">
<thead>
<tr>
<th>Parameter</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="param in config">
<td>{{param.parameter}}</td>
<td>{{param.val}}</td>
</tr>
</tbody>
</table>
</div>
<div class="row well">
<h2>New Parameter</h2>
<form>
<div class="form-group">
<label for="pSelected">Parameter</label>
<select class="form-control" id="pSelected" ng-model="newParam.pSelected">
<option value="ip_address">PLC IP Address</option>
<option value="scan_rate">Scan Rate</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group" ng-if="newParam.pSelected=='other'">
<label for="pEntry">Parameter Entry</label>
<input type="text" class="form-control" id="val" ng-model="newParam.pEntry" placeholder="Parameter Name">
</div>
<div class="form-group">
<label for="val">Value</label>
<input type="text" class="form-control" id="val" ng-model="newParam.val" placeholder="Parameter Value">
</div>
<button class="btn btn-primary" ng-click="addParameter()">Set Parameter</button>
</form>
<!--<pre>{{newParam}}</pre>-->
</div>
</div>
</div>

View File

@@ -51,12 +51,12 @@
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li ng-class="{active: Page.page() == 'dashboard'}"><a href="/#/">Dashboard</a></li>
<li ng-class="{active: Page.page() == 'tags'}"><a href="/#/tags">Tags</a></li>
<li ng-class="{active: Page.page() == 'dashboard'}"><a href="/#/"><i class="fa fa-home"></i> Dashboard</a></li>
<li ng-class="{active: Page.page() == 'tags'}"><a href="/#/tags"><i class="fa fa-tags"></i> Tags</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-class="{active: Page.page() == 'setup'}"><a href="/#/setup">Setup</a></li>
<li ng-class="{active: Page.page() == 'configuration'}"><a href="/#/config"><i class="fa fa-cog"></i> Configuration</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->