-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
194 lines (182 loc) · 6.46 KB
/
index.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
require('dotenv').config();
const request = require('request');
const fs = require('fs');
const { GraphQLClient } = require('graphql-request');
const userMail = process.env.USERMAIL;
const userName = process.env.USERNAME;
const userPw = process.env.USERPW;
const backendLocation = process.env.BACKENDLOCATION;
const cacheUpdateInterval = process.env.CACHEUPDATEINTERVAL; // in seconds
const camRequestInterval = process.env.CAMREQUESTINTERVAL; // in seconds
const backOffInterval = process.env.BACKOFFINTERVAL; // in seconds
const mediaSourcesAddresses = process.env.MEDIASOURCESADDRESSES;
var graphQLClient = new GraphQLClient(backendLocation);
var authToken = ''; // needed for the image upload, since it uses a different uploader client
var activeMediaStreamsCache = {}; // holds a list of active media streams from server
var lastCacheUpdateTimeStamp = null; // last update of cache
var mediaSources = {};
main();
async function main() {
// startup process
console.log('Startup...');
// login or register input user
await loginOrRegister();
// populate the initial active media streams cache
await updateMediaStreamsCache();
// start media retrieval process
mediaSourcesAddresses.split(',').forEach(source => {
source = source.split(':');
console.log('Setup source at ' + source[1] + '..');
let mediaSource = { sourceAddress: source[1], lastTimeStamp: 0, lastError: 0 };
mediaSources[source[0]] = mediaSource;
setInterval(uploadImage, camRequestInterval * 1000, source[0]);
});
console.log(`Setup cache update with ${cacheUpdateInterval}s interval..`);
setInterval(updateMediaStreamsCache, cacheUpdateInterval * 1000);
console.log('Startup done!');
}
async function uploadImage(mediaFilesName) {
// check if media stream exists
let mediaStream = null;
for (let i = 0; i < activeMediaStreamsCache.length; i++) {
if (activeMediaStreamsCache[i].mediaFilesName === mediaFilesName) {
// found it
mediaStream = activeMediaStreamsCache[i];
break;
}
}
if (!mediaStream) return; // no active stream exists for this file name
// check if update is too recent or error
if (new Date() - mediaSources[mediaFilesName].lastTimeStamp <
mediaStream.updateFrequency * 1000
||
new Date() - mediaSources[mediaFilesName].lastError <
backOffInterval * 1000
) {
return;
}
// temporary cache the last time stamp to reset it if needed
let oldLastTimeStampMainView = mediaSources[mediaFilesName].lastTimeStamp;
mediaSources[mediaFilesName].lastTimeStamp = new Date();
request('http://' + mediaSources[mediaFilesName].sourceAddress, { timeout: mediaStream.updateFrequency * 1000 })
.on('error', function (err) {
console.log(`Stream request error for ${mediaFilesName}: ${err}`);
mediaSources[mediaFilesName].lastTimeStamp = oldLastTimeStampMainView;
mediaSources[mediaFilesName].lastError = new Date();
return;
}).pipe(
fs.createWriteStream(`${mediaFilesName}.jpg`)
.on('error', function (err) {
console.log(`Stream write error for ${mediaFilesName}: ${err}`);
[mediaFilesName].lastTimeStamp = oldLastTimeStampMainView;
mediaSources[mediaFilesName].lastError = new Date();
return;
})
).on('close', function () {
let formData = {
mediaStreamName: mediaFilesName,
mediaMimeType: 'IMAGE_JPG',
mediaTimeStamp: mediaSources[mediaFilesName].lastTimeStamp.toJSON(),
mediaData: fs.createReadStream(`${mediaFilesName}.jpg`),
};
request.post({
url: `${backendLocation}/uploadMedia`,
headers: {
'Authorization': 'Bearer ' + authToken
},
formData: formData
}, function callback(err, httpResponse, identifier) {
if (err) {
mediaSources[mediaFilesName].lastTimeStamp = oldLastTimeStampMainView;
mediaSources[mediaFilesName].lastError = new Date();
console.log(`Failed upload for ${mediaFilesName}: ${err}`);
} else {
// TODO: check, if data was acutally stored on server, only correct upload is checked for here
console.log(`File for ${mediaFilesName} send, server returned identifier: ${identifier}`);
}
});
});
}
async function loginOrRegister() {
console.log('Login user...');
let mutation = /* GraphQL */ `
mutation signin($email: String!, $password: String!) {
signin(email: $email, password: $password) {
token
}
}
`;
let variables = {
email: userMail,
password: userPw
};
try {
let data = await graphQLClient.request(mutation, variables);
authToken = data.signin.token;
graphQLClient = new GraphQLClient(backendLocation, {
headers: {
Authorization: 'Bearer ' + authToken
}
});
console.log('Logged in!');
} catch (e) {
console.log('Login not possible, trying to register new user...');
mutation = /* GraphQL */ `
mutation signup($name: String!, $password: String!, $email: String!) {
signup(name: $name, password: $password, email: $email) {
token
}
}
`;
variables = {
name: userName,
password: userPw,
email: userMail
};
try {
let data = await graphQLClient.request(mutation, variables);
authToken = data.signin.token;
graphQLClient = new GraphQLClient(backendLocation, {
headers: {
Authorization: 'Bearer ' + authToken
}
});
console.log('Registered new user!');
} catch (e) {
// No login and signup possible...
console.log(e);
process.exit(1);
}
}
}
async function updateMediaStreamsCache() {
// temporary cache the "old" last time stamp in case of failure with updating
let oldLastCacheUpdateTimeStamp = lastCacheUpdateTimeStamp;
lastCacheUpdateTimeStamp = new Date();
let query = /* GraphQL */ `
{
mediaStreams(active: true) {
id
mediaFilesName
updateFrequency
brewingStep {
id
}
}
}
`;
try {
let data = await graphQLClient.request(query);
// a bit of data flattening
for (let i = 0; i < data.mediaStreams.length; i++) {
data.mediaStreams[i].brewingStep =
data.mediaStreams[i].brewingStep.id;
}
activeMediaStreamsCache = data.mediaStreams;
console.log(`Updated cache at: ${lastCacheUpdateTimeStamp}`);
} catch (e) {
// "reset" timestamp
lastCacheUpdateTimeStamp = oldLastCacheUpdateTimeStamp;
console.log(`Error, cache not updated: ${e}`);
}
}