Skip to content

Commit 52bcc24

Browse files
committed
All node data CSV export & other fixes/improves
Export all node data (csv) Add "excel timestamp" columns in CSV exports Datepicker support for export date range popup Settings description + tooltips Settings page listview trigger create bug fix Moved "Restart App" in main menu Moved "Uptime" status after main menu Added _example.js event override sample fixed README.md titles Fixed AM/PM bug in SMS messages Updated exports.timeoutOffset Setup script mkdir /data/db so pi would chown it
1 parent 8dc5e1c commit 52bcc24

File tree

8 files changed

+216
-66
lines changed

8 files changed

+216
-66
lines changed

.setup/gatewaysetup.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ sudo npm install --unsafe-perm --build-from-source
9696
sudo npm cache clean #clear any caches/incomplete installs
9797
sudo mkdir $APPSRVDIR/logs -p
9898

99+
#create db and empty placeholders so chown pi will override root permissions
100+
sudo mkdir $APPSRVDIR/data/db -p
101+
touch $APPSRVDIR/data/db/gateway.db
102+
touch $APPSRVDIR/data/db/gateway_nonmatches.db
103+
99104
#create self signed certificate
100105
#WARNING: must do this *AFTER* the gateway app was git-cloned
101106
echo -e "${CYAN}************* STEP: Create self signed HTTPS certificate (5 year) *************${NC}"
@@ -158,7 +163,8 @@ sudo systemctl enable gateway.service
158163
sudo systemctl start gateway.service
159164

160165
echo -e "${RED}Make sure: ${YLW}to edit your gateway settings from the UI or from settings.json5 (and restart to apply changes)${NC}"
161-
echo -e "${RED}By default ${YLW}the gateway app uses the GPIO serial port. If you use MoteinoUSB or another serial port you must edit the serial port setting or else the app will not receive messages from your Moteino nodes.${NC}"
166+
echo -e "${RED}By default ${YLW}the gateway app uses the GPIO serial port. Run ${GRN}raspi-config${NC} and ensure the GPIO serial is enabled and GPIO console is disabled.${NC}"
167+
echo -e "${YLW}If you use MoteinoUSB or another serial port you must edit the serial port setting or the app will not receive messages from your Moteino nodes.${NC}"
162168
echo -e "${RED}App restarts ${YLW}can be requested from the Gateway UI (power symbol button on settings page, or from the terminal via ${RED}sudo systemctl restart gateway.service${NC}"
163169
echo -e "${RED}Don't forget: ${YLW}install proftpd (choose standalone mode) if you plan to FTP transfer files to your Pi (very useful!) with ${GRN}sudo apt-get install proftpd${NC}"
164170
echo -e "${RED}Don't forget: ${YLW}install minicom - useful for serial port debugging with ${GRN}sudo apt-get install minicom${NC}"

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ RaspberryPi Gateway Web Interface for the Moteino IoT Framework
33
By Felix Rusu (lowpowerlab.com/contact)
44
<br/>
55

6-
###Features:
6+
### Features:
77
- SSL Encrypted with self signed certificate
88
- `auth_basic` authenticated
99
- realtime websocket driven using node.js and socket.io
@@ -13,15 +13,15 @@ By Felix Rusu (lowpowerlab.com/contact)
1313
- [nodemailer](https://github.com/andris9/Nodemailer) for sending email (and SMS relayed via email)
1414
- [Font-awesome](http://htmlpreview.github.io/?https://github.com/dotcastle/jquery-mobile-font-awesome/blob/master/index.html) icons for jQuery-Mobile
1515

16-
###License
16+
### License
1717
This source code is released under GPL 3.0 with the following ammendment:<br/>
1818
You are free to use, copy, distribute and transmit this Software for non-commercial purposes.
1919
For more details see [LICENSE](https://github.com/LowPowerLab/RaspberryPi-Gateway/blob/master/LICENSE)
2020

21-
###Details & Setup Guide
21+
### Details & Setup Guide
2222
The full details of how to install this stack along with supporting webserver are published [here](http://lowpowerlab.com/gateway). There you will also find a pre-compiled Pi image that has this stack installed and ready to go. In addition there are hardware guidelines and requirements.
2323

24-
###Quick reference:
24+
### Quick reference:
2525
- Copy the contents of this directory in `/home/pi/gateway`
2626
- run `npm install` in the `/home/pi/gateway` directory to install all node dependencies
2727
- Adjust any email/password/SMS settings in `settings.json5`
@@ -32,8 +32,8 @@ The full details of how to install this stack along with supporting webserver ar
3232
- if you are using a wi-fi dongle, edit your wifi password in `/etc/wpa_supplicant/wpa_supplicant.conf`
3333
- Ensure your `gateway.js` script runs at boot (see the [Pi Stack Setup guide for how to set that up with upstart](http://lowpowerlab.com/gateway/#pisetup) and the [Gateway app setup](http://lowpowerlab.com/gateway/#sourcecode)). You can always use the pre-compiled Pi image that has all these things ready to go (except the settings which you should revisit anyway); this image also has upstart already configured to run the `gateway.js` app at startup. Otherwise if you want to manually start the `gateway.js` app or see the output it generates to the console start it with `node gateway.js &`. If you want to manually start it and ensure it persists after you logout use `nohup node gateway.js &`
3434

35-
###Video Overview & Demo
35+
### Video Overview & Demo
3636
https://www.youtube.com/watch?v=F15dEqZ4pMM
3737

38-
###3rd party custom gateway setup overview
38+
### 3rd party custom gateway setup overview
3939
https://www.youtube.com/watch?v=DP83RJeTpUY

gateway.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ global.sendEmail = function(SUBJECT, BODY) {
125125

126126
global.sendSMS = function(SUBJECT, BODY) {
127127
var mailOptions = {
128-
from: 'Moteino Gateway <[email protected]>',
128+
from: 'Gateway <[email protected]>',
129129
to: settings.credentials.smsAlertsTo.value, //your mobile carrier should have an email address that will generate a SMS to your phone
130130
subject: SUBJECT,
131131
text: BODY
@@ -297,7 +297,7 @@ io.sockets.on('connection', function (socket) {
297297
if (entries.length == 1)
298298
{
299299
var dbNode = entries[0];
300-
Object.keys(dbNode.metrics).forEach(function(mKey,index) {
300+
Object.keys(dbNode.metrics).forEach(function(mKey,index) { //syncronous/blocking call
301301
if (dbNode.metrics[mKey].graph == 1)
302302
dbLog.removeMetricLog(path.join(__dirname, dbDir, dbLog.getLogName(dbNode._id, mKey)));
303303
});
@@ -405,7 +405,29 @@ io.sockets.on('connection', function (socket) {
405405
else
406406
socket.emit('GRAPHDATAREADY', { graphData:graphData, options : graphOptions });
407407
});
408-
408+
409+
socket.on('EXPORTNODELOGSCSV', function (nodeId, start, end, howManyPoints) {
410+
var sts = Math.floor(start / 1000); //get timestamp in whole seconds
411+
var ets = Math.floor(end / 1000); //get timestamp in whole seconds
412+
var sets = [];
413+
414+
db.find({ _id : nodeId }, function (err, entries) {
415+
if (entries.length == 1)
416+
{
417+
var dbNode = entries[0];
418+
Object.keys(dbNode.metrics).forEach(function(mKey,index) { //syncronous/blocking call
419+
if (dbNode.metrics[mKey].graph == 1) {
420+
var logfile = path.join(__dirname, dbDir, dbLog.getLogName(dbNode._id, mKey));
421+
var theData = dbLog.getData(logfile, sts, ets, howManyPoints /*settings.general.graphMaxPoints.value*/);
422+
theData.label = dbNode.metrics[mKey].label || mKey;
423+
sets.push(theData); //100k points when exporting, more points is really pointless
424+
}
425+
});
426+
socket.emit('EXPORTNODELOGSCSVREADY', { sets:sets });
427+
}
428+
});
429+
});
430+
409431
socket.on('UPDATESETTINGSDEF', function (newSettings) {
410432
var settings = nconf.get('settings');
411433

logUtil.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ exports.getData = function(filename, start, end, dpcount) {
3333
filesize = exports.fileSize(filename);
3434
if (filesize == -1) return {data:data, queryTime:0, msg:'no log data'};
3535
fd = fs.openSync(filename, 'r');
36+
37+
//truncate start/end to log time limits if necessary - this ensures good data resolution when time limits are out of bounds
38+
var buff = new Buffer(9);
39+
fs.readSync(fd, buff, 0, 9, 0);
40+
var firstLogTimestamp = buff.readUInt32BE(1);
41+
fs.readSync(fd, buff, 0, 9, filesize-9);
42+
var lastLogTimestamp = buff.readUInt32BE(1); //read timestamp (bytes 0-3 in buffer)
43+
if (start < firstLogTimestamp) start = firstLogTimestamp;
44+
if (end > lastLogTimestamp) end = lastLogTimestamp;
45+
46+
//console.info('getData() [start,end] = ' + start + ', ' + end);
47+
3648
interval = (end - start) / dpcount;
3749

3850
// Ensure that interval request is less than 1, adjust number of datapoints to request if interval = 1
@@ -42,7 +54,6 @@ exports.getData = function(filename, start, end, dpcount) {
4254
}
4355

4456
timetmp = 0;
45-
buff = new Buffer(9);
4657

4758
//first check if sequential reads (much faster) make sense
4859
posStart = exports.binarySearch(fd,start-interval,filesize);

0 commit comments

Comments
 (0)