-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
159 lines (134 loc) · 3.66 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
const dotenv = require('dotenv');
const path = require('path');
const paths = require('./paths');
const fs = require("fs-extra");
const chokidar = require("chokidar");
const spawn = require("child_process").spawn;
const FormData = require('form-data');
const sleep = require('await-sleep');
dotenv.config({
path: paths.configFilePath
});
if ( typeof process.env.deviceID === 'undefined' ) {
console.error( 'please configure the application before starting')
process.exit( 1 );
} else {
console.log( 'starting camera', process.env.deviceID );
}
var pic = null;
var fileWatch = null;
var uploadingLock = false;
var delay = process.env.cameraDelay || 5;
var dt = new Date();
var secInterval = setInterval( () => {
dt = new Date();
if( dt.getSeconds() % delay === 0 ) {
clearInterval( secInterval );
startCamera();
}
}, 1000 );
/**
* start the camera application
*/
async function startCamera() {
if( process.env.NODE_ENV === 'development' ) {
// send message for emulate.js to start image updates
process.send( 'start timer' );
} else {
var args = [
// '-v',
'-vf',
'-hf',
'-w', '1920',
'-h', '1080',
'-o', process.env.imageFilePath,
'-t', '999999999',
'-tl', delay*1000,
'-a', 4+8,
// '-a', 'test',
];
pic = spawn('raspistill', args);
pic.stdout.on('data', (data) => {
console.log( 'stdout: ', data );
});
pic.on('close', code => {
console.log( 'raspistill ended with code:', code );
});
}
}
/**
* asynchronously wait for the file to exist
*
* @param {string} file path to file
*/
async function waitForFile( file ) {
while( true ) {
const exists = await fs.exists( file );
if( exists ) return true;
await sleep( 333 );
}
}
// watch for changes on the file and upload them to the server
// using native fs for now, switching to something better later
( async() => {
// wait for file to be created
await waitForFile( process.env.imageFilePath );
// watch the file
fileWatch = chokidar.watch( path.dirname( process.env.imageFilePath ), {
persistent: true,
});
fileWatch.on( 'change', async( path, stats ) => {
if( path !== process.env.imageFilePath ) {
return;
}
if( uploadingLock ) {
console.error( 'uploading is still locked');
return;
}
uploadingLock = true;
unixTimestamp = Math.round( ( new Date() ).getTime() / 1000 );
try {
var form = new FormData();
form.append( 'filedata', fs.createReadStream( process.env.imageFilePath ) );
const uploadPath = process.env.uploadURL + [ '/upload', process.env.deviceID, unixTimestamp ].join('/');
await form.submit( uploadPath, err => {
if ( err ) {
console.error( 'error submitting form', err );
uploadingLock = false;
}
});
} catch( error ) {
console.error( 'error trying to read the image and upload it', error );
}
uploadingLock = false;
});
})();
/**
* gracefully shut the application down
*/
async function shutdown() {
console.info( 'shutting down...' );
// stop raspistill if it running
if( pic !== null ) {
console.info( 'stopping raspistill...' );
pic.kill('SIGINT');
}
if( fileWatch !== null ) {
console.info( 'removing file watch...' );
fileWatch.close();
}
console.info( 'done...' );
process.exit(0);
}
// listen for SIGINT and clean up
process.on('SIGINT', async () => {
console.info( '\r\n\r\n', 'SIGINT signal recieved' );
shutdown();
});
// windows
process.on('message', (msg) => {
if (msg == 'shutdown') {
shutdown();
}
})