Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bb21e58582 | |||
| 8eeca803ba | |||
| 5ad715a2a6 | |||
| 8d31ba4924 | |||
| b2792207a5 | |||
| b4236b2eb7 | |||
| 4ff3d76dac | |||
| 0a6fcc8940 | |||
| b4087527a1 | |||
| 5233131f49 | |||
| 6451cca01a | |||
| dbfa941474 | |||
| 0f262eb440 | |||
| dcdb32ae9c | |||
| a1373e6fe4 | |||
| bb73e4b02b | |||
| 765e70a0e0 | |||
| 62591f9039 | |||
| 29c3cb6af0 | |||
| 9ad0b9590c | |||
| d6b17671c4 | |||
| 7795d96aad | |||
| a220885f56 | |||
| ff882328d8 | |||
| 6e98a7749a | |||
| 9c016dceb0 | |||
| ec02f84381 | |||
| 24d7138888 | |||
| c4163f1ce5 | |||
| d1e7d02a3c | |||
| 81bb8e7b98 | |||
| b822215c04 | |||
| 74e6565c27 | |||
| 14f987a49d | |||
| 074e163c95 | |||
| 0b6b551921 | |||
| ace749b742 | |||
| 75cb542795 | |||
| 29325f2165 | |||
| 21ca818ab6 | |||
| 6d7f5d26ee | |||
| 68e4e6ffea | |||
| eeb08342f6 | |||
| 64988aa95a | |||
| e4816e9447 | |||
| b1c92721be | |||
| d27946ed88 | |||
| adc5686033 | |||
| 5f9c91e5e7 | |||
| e5ccd05903 | |||
| 358687c8dd | |||
| 283c3fbb57 | |||
| 8edfaf6224 | |||
| ed511992ea | |||
| 8ebae697b1 | |||
| 93a0888de5 | |||
| c0c23e77ee | |||
| 684a1fa44b | |||
| fb87eb90ca | |||
| 7b22866929 | |||
| aa5db953a8 | |||
| 4e1021acb9 | |||
| 3d763a3e36 | |||
| ad0f54775b | |||
| 251dcfb750 | |||
| 62b60d02e4 | |||
| 82587d7506 | |||
| 51d69d5a97 | |||
| 9319fa131b | |||
| 10cd8c2d1b | |||
| a93d784d16 | |||
| 54bccd0253 | |||
| 363d8aac11 | |||
| f49750a70a | |||
| fc29545948 | |||
| 000722d2d1 | |||
| 9e9dd22bdf | |||
| a6ec77c523 | |||
| 1f1795eb6c | |||
| 373fbafd6c | |||
| e1200a47a1 | |||
| 667469dd50 | |||
| 83816f16d4 | |||
| 92fdfefa30 | |||
| d7bfc9d7c2 | |||
| a0e74c61ee | |||
| 293db99a2e | |||
| a7bea5288c | |||
| 6e05fda2e3 | |||
| 1826a8618b | |||
| 97a3176bd9 | |||
| 2cd467b431 | |||
| 1574883381 | |||
| 78f29fe34c | |||
| 6882cd320f | |||
| b74bbe083d | |||
| cef86f27c2 | |||
| 3b2114b95f | |||
| 3164add2c0 | |||
| 9b5d237928 | |||
| 54be774fe8 | |||
| 52a4dac990 | |||
| 9a3d9689fd |
@@ -23,6 +23,26 @@ createuser biopro -P --interactive
|
||||
|
||||
### Run apiServer on device
|
||||
|
||||
##### Install node.js
|
||||
```
|
||||
sudo apt-get upgrade
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
```
|
||||
### setup_14.x can change to your version
|
||||
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
||||
### install node and npm
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
##### (optional) if the installation of node.js fail
|
||||
```
|
||||
sudo apt update
|
||||
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
##### Clone project
|
||||
```
|
||||
git clone https://gitlab.com/bioproscientific/bioproapiserver.git
|
||||
@@ -35,12 +55,9 @@ vim config.js
|
||||
```
|
||||
change the code following as:
|
||||
```
|
||||
/*
|
||||
change apiserver port to postgres port, 54321 --> 5432 (default)
|
||||
*/
|
||||
export const pgDB = {
|
||||
host: '127.0.0.1', // 服务器地址
|
||||
port: 54321, // 数据库端口号 -----------------> 5432
|
||||
port: 5432, // 数据库端口号
|
||||
username: 'biopro', // 数据库用户名
|
||||
password: 'BioProControlBox', // 数据库密码
|
||||
database: 'postgres' // 数据库名称
|
||||
@@ -60,7 +77,8 @@ sudo vim /etc/rc.local
|
||||
```
|
||||
add the code following as:
|
||||
```
|
||||
nohup node /home/pi/bioproapiserver/dist/app.js > /home/pi/.api_server.out &
|
||||
now=$(date +"%F_%T")
|
||||
sudo -H -u pi nohup node /home/pi/bioproapiserver/dist/app.js > /home/pi/.api_server_$now.out &
|
||||
```
|
||||
|
||||
### Localhost develop
|
||||
@@ -79,4 +97,4 @@ npm run start
|
||||
```
|
||||
|
||||
##### References
|
||||
>https://opensource.com/article/17/10/set-postgres-database-your-raspberry-pi
|
||||
>https://opensource.com/article/17/10/set-postgres-database-your-raspberry-pi
|
||||
|
||||
Generated
+13
@@ -2448,6 +2448,14 @@
|
||||
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.24.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.4"
|
||||
}
|
||||
},
|
||||
"babel-core": {
|
||||
"version": "7.0.0-bridge.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
|
||||
@@ -4860,6 +4868,11 @@
|
||||
"readable-stream": "^2.3.6"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.5",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
|
||||
+2
-1
@@ -7,13 +7,14 @@
|
||||
"scripts": {
|
||||
"start": "gulp nodemon",
|
||||
"dev": "gulp",
|
||||
"build": "babel src -d dist --copy-files",
|
||||
"build": "babel src -d dist",
|
||||
"production": "node dist/app.js",
|
||||
"test": "jest",
|
||||
"link": "eslint .",
|
||||
"link:fix": "eslint --fix ."
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.24.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.11.0",
|
||||
"koa-body": "^4.1.1",
|
||||
|
||||
+26
-26
@@ -1,39 +1,39 @@
|
||||
import path from 'path'
|
||||
|
||||
// 系统配置
|
||||
// system config
|
||||
export const System = {
|
||||
API_server_type: 'http://', // API服务器协议类型,包含"http://"或"https://"
|
||||
API_server_host: 'localhost', // API服务器暴露的域名地址,请勿添加"http://"
|
||||
API_server_port: '3000', // API服务器监听的端口号
|
||||
HTTP_server_type: 'http://', // HTTP服务器协议类型,包含"http://"或"https://"
|
||||
HTTP_server_host: 'www.XXX.com', // HTTP服务器地址,请勿添加"http://" (即前端调用使用的服务器地址,如果是APP请设置为 * )
|
||||
HTTP_server_port: '65534', // HTTP服务器端口号
|
||||
System_country: 'zh-cn', // 所在国家的国家代码
|
||||
System_plugin_path: path.join(__dirname, './plugins'), // 插件路径
|
||||
Session_Key: 'RESTfulAPI', // 生产环境务必随机设置一个值
|
||||
db_type: 'mysql' // 数据库类型
|
||||
API_server_type: 'http://',
|
||||
API_server_host: 'localhost',
|
||||
API_server_port: '3000',
|
||||
HTTP_server_type: 'http://',
|
||||
HTTP_server_host: 'www.XXX.com', // HTTP server address(as client browser location,* if its app )
|
||||
HTTP_server_port: '65534',
|
||||
System_country: 'zh-cn',
|
||||
System_plugin_path: path.join(__dirname, './plugins'),
|
||||
Session_Key: 'RESTfulAPI',
|
||||
db_type: 'mysql'
|
||||
}
|
||||
|
||||
export const DB = {
|
||||
host: 'localhost', // 服务器地址
|
||||
port: 3306, // 数据库端口号
|
||||
username: 'admin', // 数据库用户名
|
||||
password: 'admin888', // 数据库密码
|
||||
database: 'development', // 数据库名称
|
||||
prefix: 'api_' // 默认"api_"
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'admin',
|
||||
password: 'admin888',
|
||||
database: 'development',
|
||||
prefix: 'api_'
|
||||
}
|
||||
|
||||
export const pgDB = {
|
||||
host: '127.0.0.1', // 服务器地址
|
||||
port: 54321, // 数据库端口号
|
||||
username: 'biopro', // 数据库用户名
|
||||
password: 'BioProControlBox', // 数据库密码
|
||||
database: 'postgres' // 数据库名称
|
||||
host: '127.0.0.1',
|
||||
port: 5432,
|
||||
username: 'biopro',
|
||||
password: 'BioProControlBox',
|
||||
database: 'postgres'
|
||||
}
|
||||
|
||||
export const SendEmail = {
|
||||
service: 'smtp.abcd.com', // SMTP服务提供商域名
|
||||
username: 'postmaster%40abcd.com', // 用户名/用户邮箱
|
||||
password: 'password', // 邮箱密码
|
||||
sender_address: '"XX平台 👥" <postmaster@abcd.com>'
|
||||
service: 'smtp.abcd.com',
|
||||
username: 'postmaster%40abcd.com',
|
||||
password: 'password',
|
||||
sender_address: '<postmaster@abcd.com>'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
from scipy import signal
|
||||
import sys
|
||||
|
||||
# argv = _type, order, fs, f0, f1, f2
|
||||
if len(sys.argv) < 7:
|
||||
_type = 'highpass' # 'highpass', 'lowpass', 'bandstop', 'bandpass'
|
||||
order = 20
|
||||
fs = 1000
|
||||
f0 = 48
|
||||
f1 = 52
|
||||
f2 = 25
|
||||
# exit()
|
||||
else:
|
||||
_type = sys.argv[1] # 'highpass', 'lowpass', 'bandstop', 'bandpass'
|
||||
order = int(sys.argv[2])
|
||||
fs = float(sys.argv[3])
|
||||
f0 = float(sys.argv[4])
|
||||
f1 = float(sys.argv[5])
|
||||
f2 = float(sys.argv[6])
|
||||
|
||||
# fs = 1000
|
||||
|
||||
if _type in ['bandstop', 'bandpass']:
|
||||
sos = signal.butter(order, [f0/fs*2,f1/fs*2], _type, output='sos')
|
||||
elif _type in ['highpass', 'lowpass']:
|
||||
sos = signal.butter(order, f2/fs*2, _type, output='sos')
|
||||
else:
|
||||
b, a = signal.iirnotch(f2, order, fs)
|
||||
sos = signal.tf2sos(b, a)
|
||||
|
||||
ret = ''
|
||||
for s_list in sos:
|
||||
for s in s_list:
|
||||
ret += str(s) + ','
|
||||
ret = ret[:-1]
|
||||
ret += '/'
|
||||
|
||||
print(ret[:-2], end='')
|
||||
@@ -1,57 +1,116 @@
|
||||
import RecordingDataMeta from '../../models/file/recording_data_meta'
|
||||
import childProcess from 'child_process'
|
||||
import path from 'path'
|
||||
import { homedir } from 'os'
|
||||
|
||||
const recordingDataMeta = new RecordingDataMeta()
|
||||
|
||||
export const spikeDetect = async (ctx, next) => {
|
||||
const request = ctx.request.body
|
||||
ctx.req.setTimeout(0)
|
||||
|
||||
const id = request.id
|
||||
const controllerId = request.controller_id
|
||||
const metaId = request.meta_id
|
||||
const channel = request.channel
|
||||
const cutOffFreq = request.cut_off_freq
|
||||
const filterOrder = request.filter_order
|
||||
const threshold = request.threshold
|
||||
const waveForm = request.waveForm
|
||||
const retDataType = request.ret_data_type
|
||||
// console.log(id, channel, cutOffFreq, threshold, waveForm)
|
||||
const dataType = request.data_type
|
||||
|
||||
const result = await recordingDataMeta.getByID(metaId)
|
||||
|
||||
const result = await recordingDataMeta.getByID(id)
|
||||
const channels = JSON.parse(result[0].channels)
|
||||
const sampleRate = 8e5 / result[0].parameter_set.ADC_CLOCK / channels.length
|
||||
const timeDuration = result[0].time_duration / 1e6
|
||||
// console.log(sampleRate, timeDuration)
|
||||
const rawData = JSON.stringify(result[0].raw_data[channel])
|
||||
|
||||
const process = childProcess.spawnSync('python3', [
|
||||
path.join(__dirname, '/spikeDetect.py'),
|
||||
'meta_id=' + id,
|
||||
'channel=' + channel,
|
||||
'cut_off_freq=' + cutOffFreq,
|
||||
'threshold=' + threshold,
|
||||
'waveform=' + waveForm,
|
||||
'sample_rate=' + sampleRate,
|
||||
'time_duration=' + timeDuration,
|
||||
'ret_data_type=' + retDataType
|
||||
], { maxBuffer: 2 * 1024 * 1024 * 1024 })
|
||||
function getPromise () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.spawn('python3', [
|
||||
path.join(homedir(), 'bioproanalysis', 'spike_detect', 'main.py'),
|
||||
'controller_id=' + controllerId,
|
||||
'meta_id=' + metaId,
|
||||
'channel=' + channel,
|
||||
'cut_off_freq=' + cutOffFreq,
|
||||
'filter_order=' + filterOrder,
|
||||
'threshold=' + threshold,
|
||||
'waveform=' + waveForm,
|
||||
'sample_rate=' + sampleRate,
|
||||
'time_duration=' + timeDuration,
|
||||
'data_type=' + dataType,
|
||||
'raw_data=' + rawData
|
||||
])
|
||||
|
||||
// console.log('out', process.stdout.toString())
|
||||
console.log('err', process.stderr.toString())
|
||||
let totalString = ''
|
||||
|
||||
ctx.body = process.stdout.toString()
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
const dataString = data.toString()
|
||||
totalString += dataString
|
||||
})
|
||||
|
||||
// const process = child_process.execSync('python3 /Users/lubokai/Desktop/bioproapiserver/src/controllers/analysis/test.py 1089 0')
|
||||
// console.log(process)
|
||||
// process.stdout.on('data', (data) => {
|
||||
// _data += data.toString()
|
||||
// })
|
||||
subprocess.stderr.on('data', (error) => {
|
||||
reject(error)
|
||||
console.error(`Error ${error}`)
|
||||
})
|
||||
|
||||
// process.stderr.on('data', (data) => {
|
||||
// console.error(data.toString())
|
||||
// })
|
||||
subprocess.on('close', (code) => {
|
||||
resolve(totalString)
|
||||
console.log(`spike detect analysis process exited with code ${code}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// process.on('exit', (code) => {
|
||||
// console.log(_data)
|
||||
// console.log(`Child exited with code ${code}`)
|
||||
// })
|
||||
const ret = await getPromise()
|
||||
ctx.body = ret
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const IIRFliter = async (ctx, next) => {
|
||||
const request = ctx.request.body
|
||||
ctx.req.setTimeout(0)
|
||||
|
||||
const type = request.type
|
||||
const order = request.order
|
||||
const fs = request.fs
|
||||
const f0 = request.f0
|
||||
const f1 = request.f1
|
||||
const f2 = request.f2
|
||||
|
||||
function getPromise () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.spawn('python3', [
|
||||
path.join(homedir(), 'bioproanalysis', 'filter', 'IIRFilter.py'),
|
||||
type,
|
||||
order,
|
||||
fs,
|
||||
f0,
|
||||
f1,
|
||||
f2
|
||||
])
|
||||
|
||||
let totalString = ''
|
||||
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
const dataString = data.toString()
|
||||
totalString += dataString
|
||||
})
|
||||
|
||||
subprocess.stderr.on('data', (error) => {
|
||||
reject(error)
|
||||
console.error(`Error ${error}`)
|
||||
})
|
||||
|
||||
subprocess.on('close', (code) => {
|
||||
resolve(totalString)
|
||||
console.log(`iir filter analysis process exited with code ${code}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const ret = await getPromise()
|
||||
ctx.body = ret
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
import sys
|
||||
import ast
|
||||
import psycopg2
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from math import ceil, floor
|
||||
from json import loads, dumps
|
||||
from scipy.fft import fft, fftfreq, rfft, rfftfreq, irfft, ifft
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
params = {}
|
||||
for input in sys.argv[1:]: #Now we're going to iterate over argv[1:] (argv[0] is the program name)
|
||||
param = input.split("=") #Get what's left of the '='
|
||||
params[param[0]] = param[1]
|
||||
|
||||
meta_id = params['meta_id']
|
||||
channel = params['channel']
|
||||
cut_off_freq = int(params['cut_off_freq'])
|
||||
threshold = ast.literal_eval('[' + params['threshold'] + ']')
|
||||
waveform = ast.literal_eval('[' + params['waveform'] + ']')
|
||||
SAMPLE_RATE = int(params['sample_rate'])
|
||||
DURATION = ceil(float(params['time_duration']))
|
||||
DELTA_TIME = 1e6 / SAMPLE_RATE
|
||||
N = SAMPLE_RATE * DURATION
|
||||
ret_data_type = params['ret_data_type']
|
||||
|
||||
# print(meta_id, channel, cut_off_freq, threshold, waveForm, SAMPLE_RATE, DURATION, N)
|
||||
|
||||
conn = psycopg2.connect(database="postgres", user="biopro", password="BioProControlBox", host="127.0.0.1", port="5432")
|
||||
cur = conn.cursor()
|
||||
sql_str = 'SELECT data FROM "public"."' + str(channel) + '_recording_data_raws" WHERE parent = ' + meta_id + 'ORDER BY id ASC'
|
||||
cur.execute(sql_str)
|
||||
ret = None
|
||||
try:
|
||||
ret = cur.fetchall()
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
exit
|
||||
finally:
|
||||
time = np.array([], dtype=int)
|
||||
data = np.array([])
|
||||
|
||||
for sub_data in ret:
|
||||
for split_data in sub_data[0].split('"***"')[:-1]:
|
||||
value = np.array(split_data.split(' '))
|
||||
time = np.append(time, value[::2].astype(np.int))
|
||||
data = np.append(data, value[1::2].astype(np.int))
|
||||
|
||||
# print(len(time), len(data))
|
||||
|
||||
xf = rfftfreq(N, 1 / SAMPLE_RATE)
|
||||
points_per_freq = len(xf) / (SAMPLE_RATE / 2)
|
||||
target_idx = int(points_per_freq * cut_off_freq)
|
||||
|
||||
# print(xf[target_idx])
|
||||
|
||||
yf = rfft(data)
|
||||
yf[:target_idx] = 0
|
||||
new_sig = np.round(irfft(yf, len(data)),3)
|
||||
|
||||
# print(time[-1])
|
||||
# print(len(datas))
|
||||
# print(len(yf),yf)
|
||||
|
||||
if threshold[0] == 'below':
|
||||
th = new_sig < threshold[1]
|
||||
elif threshold[0] == 'over':
|
||||
th = new_sig > threshold[1]
|
||||
elif threshold[0] == 'auto':
|
||||
th = new_sig
|
||||
|
||||
threshold_edges = np.convolve([1, -1], th, mode='same')
|
||||
thresholded_edge_indices = np.where(threshold_edges==1)[0]
|
||||
|
||||
filter_array = []
|
||||
for idx, point in enumerate(thresholded_edge_indices):
|
||||
if idx > 0:
|
||||
if time[thresholded_edge_indices[idx]] - int(waveform[2]) >= time[thresholded_edge_indices[idx-1]]:
|
||||
filter_array.append(True)
|
||||
elif time[thresholded_edge_indices[idx]] - int(waveform[1]) >= time[thresholded_edge_indices[idx-1]]:
|
||||
filter_array.append(True)
|
||||
else:
|
||||
filter_array.append(False)
|
||||
else:
|
||||
if time[thresholded_edge_indices[idx]] - int(waveform[1]) < 0:
|
||||
filter_array.append(False)
|
||||
else:
|
||||
filter_array.append(True)
|
||||
|
||||
timemark_list = thresholded_edge_indices[filter_array]
|
||||
|
||||
if ret_data_type == 'all':
|
||||
print(' '.join(str(x) for x in time))
|
||||
print(' '.join(str(x) for x in new_sig))
|
||||
print(' '.join(str(x) for x in timemark_list))
|
||||
elif ret_data_type == 'partial':
|
||||
return_sub_signal_lists = {}
|
||||
for timemark in timemark_list:
|
||||
start_index = timemark - floor(int(waveform[1] / DELTA_TIME))
|
||||
end_index = timemark + ceil(int(waveform[2] / DELTA_TIME))
|
||||
|
||||
subSignal = new_sig[start_index: end_index + 2]
|
||||
return_sub_signal_lists[str(timemark)] = ' '.join(str(x) for x in subSignal)
|
||||
print(dumps(return_sub_signal_lists))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
exit
|
||||
+118
-11
@@ -1,17 +1,19 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import childProcess from 'child_process'
|
||||
import { readFile, writeFile } from 'fs/promises'
|
||||
import { homedir } from 'os'
|
||||
const axios = require('axios')
|
||||
const crypto = require('crypto')
|
||||
|
||||
const publicKey = fs.readFileSync(path.join(__dirname, '../../publicKey.pub'))
|
||||
|
||||
// 用户登录的时候返回token
|
||||
// let token = jwt.sign({
|
||||
// userInfo: userInfo // 你要保存到token的数据
|
||||
// }, publicKey, { expiresIn: '7d' })
|
||||
const licenseUrl = 'http://52.194.17.114:3000'
|
||||
const apiFuncName = 'apiServer'
|
||||
|
||||
export const getCookie = (ctx, next) => {
|
||||
const token = jwt.sign({
|
||||
userInfo: 'tommy' // 你要保存到token的数据
|
||||
userInfo: 'tommy'
|
||||
}, publicKey, { expiresIn: '7d' })
|
||||
|
||||
ctx.body = token
|
||||
@@ -22,9 +24,6 @@ export const getCookie = (ctx, next) => {
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查授权是否合法
|
||||
*/
|
||||
export const CheckAuth = (ctx, next) => {
|
||||
const token = ctx.request.header.authorization
|
||||
try {
|
||||
@@ -38,7 +37,7 @@ export const CheckAuth = (ctx, next) => {
|
||||
return {
|
||||
status: 403,
|
||||
result: {
|
||||
errInfo: '没有授权'
|
||||
errInfo: 'no auth'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +45,7 @@ export const CheckAuth = (ctx, next) => {
|
||||
return {
|
||||
status: 503,
|
||||
result: {
|
||||
errInfo: '解密错误'
|
||||
errInfo: 'decode fail'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,3 +59,111 @@ export const Post = (ctx, next) => {
|
||||
return CheckAuth(ctx).then(result => { ctx.body = result; next() })
|
||||
}
|
||||
}
|
||||
|
||||
export const updateLicense = async (ctx, next) => {
|
||||
function wgetEXEC (url, name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.exec('wget ' + url + name + ' -O ' + homedir + '/checkToken')
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
})
|
||||
// subprocess.stderr.on('data', (error) => {
|
||||
// // reject(error)
|
||||
// console.error(`Error ${error}`)
|
||||
// })
|
||||
subprocess.on('close', (code) => {
|
||||
resolve(true)
|
||||
console.log(`wgetEXE process exited with code ${code}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function chmodEXEC () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.exec('chmod 777 ' + homedir + '/checkToken')
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
})
|
||||
// subprocess.stderr.on('data', (error) => {
|
||||
// // reject(error)
|
||||
// console.error(`Error ${error}`)
|
||||
// })
|
||||
subprocess.on('close', (code) => {
|
||||
resolve(true)
|
||||
console.log(`wgetEXE process exited with code ${code}`)
|
||||
return true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const mac = await readFile('/sys/class/net/eth0/address')
|
||||
const ret = await axios.post(licenseUrl + '/api/controller/token', {
|
||||
mac_controller: mac.toString().substr(0, 17)
|
||||
})
|
||||
switch (ret.status) {
|
||||
case 200:
|
||||
await writeFile(homedir + '/token.txt', ret.data.token)
|
||||
await writeFile(homedir + '/cute.txt', ret.data.cute)
|
||||
await wgetEXEC(licenseUrl + '/assets/exec/', ret.data.name)
|
||||
await chmodEXEC()
|
||||
ctx.status = 200
|
||||
break
|
||||
case 201:
|
||||
await writeFile(homedir + '/token.txt', ret.data.token)
|
||||
await writeFile(homedir + '/cute.txt', ret.data.cute)
|
||||
await wgetEXEC(licenseUrl + '/assets/exec/', ret.data.name)
|
||||
await chmodEXEC()
|
||||
ctx.status = 200
|
||||
break
|
||||
case 202:
|
||||
await writeFile(homedir + '/token.txt', ret.data.token)
|
||||
await writeFile(homedir + '/cute.txt', ret.data.cute)
|
||||
await wgetEXEC(licenseUrl + '/assets/exec/', ret.data.name)
|
||||
await chmodEXEC()
|
||||
ctx.status = 202
|
||||
break
|
||||
case 203:
|
||||
ctx.status = 203
|
||||
break
|
||||
default:
|
||||
ctx.status = 305
|
||||
break
|
||||
}
|
||||
|
||||
console.log(ret.status, ret.data)
|
||||
// 200 success; 201 doesnt need to update; 202 no license; 203 info fail
|
||||
|
||||
ctx.body = ''
|
||||
next()
|
||||
}
|
||||
|
||||
export const checkLicense = async (ctx, next) => {
|
||||
const mac = await readFile('/sys/class/net/eth0/address')
|
||||
ctx.body = await runCheckToken(mac.toString().substr(0, 17))
|
||||
next()
|
||||
}
|
||||
|
||||
export const runCheckToken = async (mac) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const tokenPath = homedir + '/token.txt'
|
||||
const cutePath = homedir + '/cute.txt'
|
||||
const subprocess = childProcess.exec(homedir + '/./checkToken ' + apiFuncName + ' ' + tokenPath + ' ' + cutePath)
|
||||
let _data = ''
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
_data += data
|
||||
})
|
||||
subprocess.on('close', (code) => {
|
||||
const pass = crypto.createHmac('sha256', mac).update(apiFuncName + 'pass').digest('hex')
|
||||
const outdated = crypto.createHmac('sha256', mac).update(apiFuncName + 'outdated').digest('hex')
|
||||
switch (_data) {
|
||||
case pass:
|
||||
resolve('pass')
|
||||
break
|
||||
case outdated:
|
||||
resolve('outdated')
|
||||
break
|
||||
default:
|
||||
resolve('fail')
|
||||
break
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import RecordingDataMeta from '../../models/file/recording_data_meta'
|
||||
import * as auth from '../../controllers/auth'
|
||||
import RecordingMeta from '../../models/file/bps_recording_meta'
|
||||
|
||||
const recordingDataMeta = new RecordingDataMeta()
|
||||
const recordingMeta = new RecordingMeta() // control system 3.0
|
||||
|
||||
export const create = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
@@ -120,3 +122,19 @@ export const getAll = async (ctx, next) => {
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
// control system 3.0
|
||||
export const getMetaByUUID = async (ctx, next) => {
|
||||
const uuid = ctx.params.uuid
|
||||
const result = await recordingMeta.getMetaByUUID(uuid)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const getMetaAll = async (ctx, next) => {
|
||||
const result = await recordingMeta.getMetaAll()
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
@@ -80,6 +80,26 @@ export const getDataByID = async (ctx, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
export const getSdDataByUUID = async (ctx, next) => {
|
||||
const uuid = ctx.params.uuid
|
||||
const channel = ctx.params.channel
|
||||
const startTime = ctx.params.startTime
|
||||
const endTime = ctx.params.endTime
|
||||
const result = await recordingDataRaw.getSdDataByUUID(uuid, channel, startTime, endTime)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const getSdDataAllTimeslotByUUID = async (ctx, next) => {
|
||||
const uuid = ctx.params.uuid
|
||||
const channel = ctx.params.channel
|
||||
const result = await recordingDataRaw.getSdDataAllTimeslotByUUID(uuid, channel)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByParent = async (ctx, next) => {
|
||||
const index = ctx.params.channel
|
||||
const parent = ctx.params.parent
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
import RecordingDataMeta from '../../../models/file/recording_data_meta'
|
||||
import RecordingDataRaw from '../../../models/file/recording_data_raw'
|
||||
import Controller from '../../../models/product/controller'
|
||||
import childProcess from 'child_process'
|
||||
import path from 'path'
|
||||
import { homedir } from 'os'
|
||||
|
||||
const recordingDataMeta = new RecordingDataMeta()
|
||||
const recordingDataRaw = new RecordingDataRaw()
|
||||
const controller = new Controller()
|
||||
|
||||
const sdPath = [homedir(), 'bioproanalysis', 'sdcard']
|
||||
const sdGetPath = [...sdPath, 'neuLiveSD_C', 'sd_list']
|
||||
const sdDeletePath = [...sdPath, 'neuLiveSD_C', 'sd_remove']
|
||||
const sdUploadPath = [...sdPath, 'sd_download.py']
|
||||
|
||||
const getParameter = async (metaID, parameterName) => {
|
||||
const ret = await recordingDataMeta.getByID(metaID)
|
||||
return ret[0].parameter_set[parameterName]
|
||||
}
|
||||
|
||||
const getPath = async (uuid) => {
|
||||
return getPathByUuid(uuid, getUuidPathArray(await getUuidPathStringPromise()))
|
||||
}
|
||||
|
||||
const getPathByUuid = (uuid, uuidPathArray) => {
|
||||
for (const uuidPath of uuidPathArray) {
|
||||
if (uuidPath[0] === uuid) {
|
||||
return uuidPath[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [uuid1, uuid2, uuid3...]
|
||||
const getUuidList = (uuidPathString) => {
|
||||
return uuidPathString.split('\n').map(val => val.split(' ')[0])
|
||||
}
|
||||
|
||||
// [[uuid1, path1], [uuid2, path2], [uuid3, path3]...]
|
||||
const getUuidPathArray = (uuidPathString) => {
|
||||
return uuidPathString.split('\n').map(val => val.split(' '))
|
||||
}
|
||||
|
||||
// 'uuid1 path1\n uuid2 path2\n uuid3 path3\n....'
|
||||
const getUuidPathStringPromise = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.spawn(path.join(...sdGetPath))
|
||||
|
||||
let dataString = ''
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
dataString += data.toString()
|
||||
})
|
||||
|
||||
subprocess.stderr.on('data', (error) => {
|
||||
console.error(`Error ${error}`)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
subprocess.on('close', (code) => {
|
||||
console.log(`sdcard get process exited with code ${code}`)
|
||||
resolve(dataString)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function uploadPromise (uuid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.spawn('python3', [
|
||||
path.join(...sdUploadPath),
|
||||
uuid,
|
||||
])
|
||||
|
||||
let dataString = ''
|
||||
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
dataString += data.toString()
|
||||
console.log('upload', dataString)
|
||||
})
|
||||
|
||||
subprocess.stderr.on('data', (error) => {
|
||||
reject(error)
|
||||
console.error(`Error ${error}`)
|
||||
})
|
||||
|
||||
subprocess.on('close', (code) => {
|
||||
console.log(`sd card upload process exited with code ${code}`)
|
||||
resolve(dataString)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function deletePromise (uuidPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const subprocess = childProcess.spawn(
|
||||
path.join(...sdDeletePath),
|
||||
[uuidPath, 120]
|
||||
)
|
||||
let dataString = ''
|
||||
subprocess.stdout.on('data', async (data) => {
|
||||
dataString += data.toString()
|
||||
})
|
||||
|
||||
subprocess.stderr.on('data', (error) => {
|
||||
console.error(`Error ${error}`)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
subprocess.on('close', (code) => {
|
||||
console.log(`grep process exited with code ${code}`)
|
||||
resolve(dataString)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const exist = async (ctx, next) => {
|
||||
const request = ctx.request.body
|
||||
// const controllerID = request.controllerID
|
||||
const uuid = request.uuid
|
||||
const path = await getPath(uuid)
|
||||
let result
|
||||
(path !== undefined) ? result = true : result = false
|
||||
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const uploadThenDelete = async (ctx, next) => {
|
||||
const request = ctx.request.body
|
||||
const controllerID = request.controllerID
|
||||
const metaID = request.metaID
|
||||
const uuid = request.uuid
|
||||
|
||||
// timeout defualt 120s to no-limit
|
||||
ctx.req.setTimeout(0)
|
||||
|
||||
// controller column sd_uploading update
|
||||
await controller.update({
|
||||
sd_uploading: true
|
||||
}, controllerID)
|
||||
|
||||
let uploadResult = await uploadPromise(uuid)
|
||||
if (uploadResult === 'true') {
|
||||
// [Region] then doubly check if sd raw data table actually has data
|
||||
const meta = await recordingDataMeta.getByUUID(uuid)
|
||||
const channel = JSON.parse(meta[0].channels)[0]
|
||||
const sdDataRes = await recordingDataRaw.getSdDataAllTimeslotByUUID(uuid, channel)
|
||||
if (sdDataRes.length > 0) {
|
||||
// [EndRegion]
|
||||
await recordingDataMeta.update({
|
||||
sd_data_uploaded: true
|
||||
}, metaID)
|
||||
// await deletePromise(uuidPath)
|
||||
} else {
|
||||
uploadResult = 'false'
|
||||
}
|
||||
}
|
||||
|
||||
// controller column sd_uploading close
|
||||
await controller.update({
|
||||
sd_uploading: false
|
||||
}, controllerID)
|
||||
|
||||
ctx.body = uploadResult
|
||||
next()
|
||||
}
|
||||
|
||||
export const getFileList = async (ctx, next) => {
|
||||
const result = await getUuidPathStringPromise()
|
||||
const uuidList = getUuidList(result)
|
||||
|
||||
ctx.body = uuidList
|
||||
next()
|
||||
}
|
||||
|
||||
// export const deleted = async (ctx, next) => {
|
||||
// const request = ctx.request.body
|
||||
// const controllerID = request.controllerID
|
||||
// const uuid = request.uuid
|
||||
// const uuidPath = await getPath(uuid)
|
||||
|
||||
// // timeout defualt 120s to no-limit
|
||||
// ctx.req.setTimeout(0)
|
||||
|
||||
// // controller column sd_uploading update
|
||||
// await controller.update({
|
||||
// sd_uploading: true
|
||||
// }, controllerID)
|
||||
|
||||
// const result = await deletePromise(uuidPath)
|
||||
|
||||
// // controller column sd_uploading close
|
||||
// await controller.update({
|
||||
// sd_uploading: false
|
||||
// }, controllerID)
|
||||
|
||||
// ctx.body = result
|
||||
|
||||
// next()
|
||||
// }
|
||||
@@ -0,0 +1,25 @@
|
||||
import SDRawNeulive from '../../models/file/sd_raw_neulive'
|
||||
import * as auth from '../auth'
|
||||
|
||||
const sdRawNeulive = new SDRawNeulive()
|
||||
|
||||
export const create = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
const result = await sdRawNeulive.create(data)
|
||||
ctx.body = result
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByParentUUID = async (ctx, next) => {
|
||||
const parent_uuid = ctx.params.parent_uuid
|
||||
const result = await sdRawNeulive.getByParentUUID(parent_uuid)
|
||||
ctx.body = result
|
||||
next()
|
||||
}
|
||||
|
||||
export const clearDeleted = async (ctx, next) => {
|
||||
const parent_uuid = ctx.params.parent_uuid
|
||||
const result = await sdRawNeulive.clearDeleted(parent_uuid)
|
||||
ctx.body = result
|
||||
next()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import RawTrigger from '../../../models/file/bps_raw_trigger'
|
||||
|
||||
const rawTrigger = new RawTrigger()
|
||||
|
||||
export const getRawTriggerByUUID = async (ctx, next) => {
|
||||
const parent_uuid = ctx.params.parent_uuid
|
||||
const result = await rawTrigger.getDataByUUID(parent_uuid)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import * as recordingDataMeta from './file/recording_data_meta'
|
||||
import * as recordingDataRaw from './file/recording_data_raw'
|
||||
import * as recordingDataMini from './file/recording_data_mini'
|
||||
import * as analysis from './analysis'
|
||||
import * as sdCard from './file/sd_card'
|
||||
import * as trigger from './file/trigger'
|
||||
|
||||
export default {
|
||||
upload,
|
||||
@@ -21,5 +23,7 @@ export default {
|
||||
recordingDataMeta,
|
||||
recordingDataRaw,
|
||||
recordingDataMini,
|
||||
analysis
|
||||
analysis,
|
||||
sdCard,
|
||||
trigger,
|
||||
}
|
||||
|
||||
@@ -19,15 +19,6 @@ export const update = async (ctx, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
export const updateByID = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
const id = ctx.params.id
|
||||
const result = await controller.updateByID(data, id)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const updateByAttr = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
const attr = ctx.params.attr
|
||||
@@ -45,6 +36,14 @@ export const clearDeleted = async (ctx, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByName = async (ctx, next) => {
|
||||
const name = ctx.params.name
|
||||
const result = await controller.getByName(name)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByMac = async (ctx, next) => {
|
||||
const mac = ctx.params.mac
|
||||
const result = await controller.getByMac(mac)
|
||||
@@ -53,6 +52,14 @@ export const getByMac = async (ctx, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByMqttId = async (ctx, next) => {
|
||||
const mqttId = ctx.params.mqtt_id
|
||||
const result = await controller.getByMqttId(mqttId)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const getByAttr = async (ctx, next) => {
|
||||
const attr = ctx.params.attr
|
||||
const value = ctx.params.value
|
||||
|
||||
@@ -11,17 +11,9 @@ export const create = async (ctx, next) => {
|
||||
}
|
||||
|
||||
export const update = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
const result = await device.update(data)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export const updateByID = async (ctx, next) => {
|
||||
const data = ctx.request.body
|
||||
const id = ctx.params.id
|
||||
const result = await device.updateByID(data, id)
|
||||
const result = await device.update(data, id)
|
||||
ctx.body = result
|
||||
|
||||
next()
|
||||
|
||||
+6
-2
@@ -28,10 +28,10 @@ db.tasks = require('./schema/task.model')(sequelize, Sequelize)
|
||||
db.devices = require('./schema/device.model')(sequelize, Sequelize)
|
||||
db.collections = require('./schema/collection.model')(sequelize, Sequelize)
|
||||
db.recording_data_metas = require('./schema/recording_data_meta.model')(sequelize, Sequelize)
|
||||
for (let i = 0; i < 32; i++) {
|
||||
for (let i = 0; i < 64; i++) {
|
||||
db[i + '_recording_data_raws'] = require('./schema/recording_data_raw.model')(sequelize, Sequelize, i)
|
||||
}
|
||||
for (let i = 0; i < 32; i++) {
|
||||
for (let i = 0; i < 64; i++) {
|
||||
db[i + '_recording_data_minis'] = require('./schema/recording_data_mini.model')(sequelize, Sequelize, i)
|
||||
}
|
||||
for (let i = 256; i < 288; i++) {
|
||||
@@ -40,6 +40,10 @@ for (let i = 256; i < 288; i++) {
|
||||
for (let i = 256; i < 288; i++) {
|
||||
db[i + '_recording_data_minis'] = require('./schema/recording_data_mini.model')(sequelize, Sequelize, i)
|
||||
}
|
||||
db.recording_meta = require('./schema/bps_recording_meta.model')(sequelize, Sequelize)
|
||||
db.raw_trigger = require('./schema/bps_raw_trigger.model')(sequelize, Sequelize)
|
||||
|
||||
db.sd_raw_neulive = require('./schema/sd_raw_neulive.model')(sequelize, Sequelize)
|
||||
|
||||
db.sequelize.sync()
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
module.exports = (sequelize, Sequelize) => {
|
||||
const TriggerDataRaw = sequelize.define('bps_raw_trigger', {
|
||||
channel: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: -1
|
||||
},
|
||||
parent_uuid: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: ''
|
||||
},
|
||||
data: {
|
||||
type: Sequelize.TEXT,
|
||||
defaultValue: ''
|
||||
},
|
||||
timestamp: {
|
||||
type: Sequelize.TEXT,
|
||||
defaultValue: ''
|
||||
},
|
||||
start_time: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '-1'
|
||||
},
|
||||
end_time: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '-1'
|
||||
},
|
||||
},
|
||||
{
|
||||
freezeTableName: true
|
||||
}
|
||||
)
|
||||
|
||||
return TriggerDataRaw
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
module.exports = (sequelize, Sequelize) => {
|
||||
const RecordingMeta = sequelize.define('bps_recording_meta', {
|
||||
uuid: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '',
|
||||
primaryKey: true
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING
|
||||
},
|
||||
series: {
|
||||
type: Sequelize.STRING
|
||||
},
|
||||
folder_id: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: -1
|
||||
},
|
||||
task_uuid: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: ''
|
||||
},
|
||||
device: {
|
||||
type: Sequelize.JSONB,
|
||||
defaultValue: {}
|
||||
},
|
||||
description: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: ''
|
||||
},
|
||||
size: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: -1
|
||||
},
|
||||
sd_size: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: -1
|
||||
},
|
||||
time_duration_sec: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
},
|
||||
time_duration_micro: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
},
|
||||
sample_rate: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: -1
|
||||
},
|
||||
deleted: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
tag: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '-1'
|
||||
},
|
||||
parameter_set: {
|
||||
type: Sequelize.ARRAY(Sequelize.JSONB),
|
||||
defaultValue: []
|
||||
},
|
||||
create_date: {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
|
||||
},
|
||||
channel: {
|
||||
type: Sequelize.ARRAY(Sequelize.INTEGER),
|
||||
defaultValue: []
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: false
|
||||
}
|
||||
)
|
||||
|
||||
return RecordingMeta
|
||||
}
|
||||
@@ -104,6 +104,10 @@ module.exports = (sequelize, Sequelize) => {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: ''
|
||||
},
|
||||
sd_uploading: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
deleted: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
|
||||
@@ -25,6 +25,10 @@ module.exports = (sequelize, Sequelize) => {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '-1'
|
||||
},
|
||||
start_time_abs: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '0'
|
||||
},
|
||||
time_duration: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: '0'
|
||||
@@ -73,6 +77,14 @@ module.exports = (sequelize, Sequelize) => {
|
||||
type: Sequelize.TEXT,
|
||||
defaultValue: ''
|
||||
},
|
||||
sd_data_record: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: true
|
||||
},
|
||||
sd_data_uploaded: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
deleted: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
module.exports = (sequelize, Sequelize, i) => {
|
||||
const RecordingDataRaw = sequelize.define('bps_sd_raw_neulive', {
|
||||
channel: {
|
||||
type: Sequelize.INTEGER
|
||||
},
|
||||
parent_uuid: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
data: {
|
||||
type: Sequelize.TEXT,
|
||||
defaultValue: ''
|
||||
},
|
||||
data_time: {
|
||||
type: Sequelize.TEXT,
|
||||
defaultValue: ''
|
||||
},
|
||||
start_time_sec: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
},
|
||||
end_time_sec: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
},
|
||||
start_time_micro: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
},
|
||||
end_time_micro: {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
}
|
||||
)
|
||||
|
||||
return RecordingDataRaw
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
const db = require('../../db/database')
|
||||
const { Transform } = require("stream")
|
||||
|
||||
class RawTrigger {
|
||||
async getDataByUUID (parent_uuid) {
|
||||
const ret = await db.raw_trigger.findAllWithStream(
|
||||
{
|
||||
where: {
|
||||
parent_uuid: parent_uuid
|
||||
},
|
||||
attributes: [
|
||||
'data'
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
const transformer = new Transform({
|
||||
transform(chunk, encoding, callback) {
|
||||
const chunkDataStr = chunk.toString('utf8')
|
||||
// replace: ref https://dmitripavlutin.com/replace-all-string-occurrences-javascript/#2-replace-with-a-global-regular-expression
|
||||
// slice: remove last ','
|
||||
const transformDataArr = JSON.parse(chunkDataStr)[0].data.replace(/[@#$]/g, '').slice(0, -1).split(',')
|
||||
const step = 3
|
||||
let transformData = ''
|
||||
for (let startPos = 0; startPos < transformDataArr.length; startPos += step) {
|
||||
// array chunking algo. comparison: https://www.better.dev/javascript-algorithms-array-chunking
|
||||
let temp = transformDataArr.slice(startPos, startPos + step)
|
||||
const date = new Date(parseInt(temp[0]))
|
||||
temp[0] = date
|
||||
temp[1] = parseInt(temp[1]) + 1
|
||||
temp.splice(1, 0, [date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()].join(':'))
|
||||
transformData += (temp.join() + '\n') // join: https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/join
|
||||
}
|
||||
callback(null, transformData)
|
||||
},
|
||||
})
|
||||
|
||||
return ret.pipe(transformer)
|
||||
}
|
||||
}
|
||||
|
||||
export default RawTrigger
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
const db = require('../../db/database')
|
||||
|
||||
class RecordingMeta {
|
||||
async getMetaByUUID (uuid) {
|
||||
const ret = await db.recording_meta.findAll(
|
||||
{
|
||||
where: {
|
||||
uuid: uuid
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async getMetaAll () {
|
||||
const ret = await db.recording_meta.findAll({
|
||||
order: [
|
||||
['create_date', 'DESC']
|
||||
]
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
async clearDeleted (uuid) {
|
||||
const ret = await db.recording_meta.destroy(
|
||||
{
|
||||
where: {
|
||||
uuid: uuid
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
export default RecordingMeta
|
||||
@@ -1,10 +1,15 @@
|
||||
import RecordingDataRaw from './recording_data_raw'
|
||||
import RecordingDataMini from './recording_data_mini'
|
||||
import SDRawNeulive from './sd_raw_neulive'
|
||||
import RecordingMeta from '../../models/file/bps_recording_meta'
|
||||
|
||||
const db = require('../../db/database')
|
||||
// const RecordingDataMini = require('./recording_data_mini')
|
||||
|
||||
const recordingDataRaw = new RecordingDataRaw()
|
||||
const recordingDataMini = new RecordingDataMini()
|
||||
const sdRawNeulive = new SDRawNeulive()
|
||||
const recordingMeta = new RecordingMeta() // control system 3.0
|
||||
|
||||
const Op = db.Sequelize.Op
|
||||
|
||||
@@ -47,7 +52,8 @@ class RecordingDataMeta {
|
||||
attributes: [
|
||||
'id',
|
||||
'raw_data',
|
||||
'mini_data'
|
||||
'mini_data',
|
||||
'uuid'
|
||||
],
|
||||
where: {
|
||||
deleted: true
|
||||
@@ -62,18 +68,14 @@ class RecordingDataMeta {
|
||||
recordingDataRaw.clearDeleted(channel)
|
||||
}
|
||||
if (meta.mini_data[channel] != null) {
|
||||
if (meta.mini_data[channel]['10'] !== undefined) {
|
||||
await recordingDataMini.updateByIDs({ deleted: true }, meta.mini_data[channel]['10'], channel)
|
||||
}
|
||||
if (meta.mini_data[channel]['100'] !== undefined) {
|
||||
await recordingDataMini.updateByIDs({ deleted: true }, meta.mini_data[channel]['100'], channel)
|
||||
}
|
||||
if (meta.mini_data[channel]['1000'] !== undefined) {
|
||||
await recordingDataMini.updateByIDs({ deleted: true }, meta.mini_data[channel]['1000'], channel)
|
||||
for (const miniID in meta.mini_data[channel]) {
|
||||
await recordingDataMini.updateByIDs({ deleted: true }, meta.mini_data[channel][miniID], channel)
|
||||
}
|
||||
recordingDataMini.clearDeleted(channel)
|
||||
}
|
||||
}
|
||||
recordingMeta.clearDeleted(meta.uuid) // control system 3.0
|
||||
sdRawNeulive.clearDeleted(meta.uuid)
|
||||
}
|
||||
ret = await db.recording_data_metas.destroy(
|
||||
{
|
||||
@@ -181,7 +183,8 @@ class RecordingDataMeta {
|
||||
{
|
||||
where: {
|
||||
uuid: uuid
|
||||
}
|
||||
},
|
||||
raw: true
|
||||
}
|
||||
)
|
||||
return ret
|
||||
|
||||
@@ -103,6 +103,67 @@ class RecordingDataRaw {
|
||||
return ret
|
||||
}
|
||||
|
||||
// ref: https://stackoverflow.com/questions/47498083/find-the-closest-smaller-value-of-an-array
|
||||
findClosestSmalllerValIndex (arr, val) {
|
||||
const targetVal = arr.slice().reverse().find(e => e <= val) // why additionally use slice: see https://stackoverflow.com/questions/30610523/reverse-array-in-javascript-without-mutating-original-array
|
||||
if (targetVal !== undefined) {
|
||||
return arr.findIndex(e => e === targetVal)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
async getSdDataByUUID (uuid, channel, startTime, endTime) {
|
||||
const timeSlots = await this.getSdDataAllTimeslotByUUID(uuid, channel)
|
||||
const startTimeArr = timeSlots.map(x => parseInt(x.start_time_sec) * 1e6 + parseInt(x.start_time_micro))
|
||||
const endTimeArr = timeSlots.map(x => parseInt(x.end_time_sec) * 1e6 + parseInt(x.end_time_micro))
|
||||
|
||||
const startIndex = this.findClosestSmalllerValIndex(startTimeArr, parseInt(startTime))
|
||||
let endIndex
|
||||
const findEndIndex = endTimeArr.findIndex(el => el >= parseInt(endTime))
|
||||
findEndIndex !== -1 ? endIndex = findEndIndex : endIndex = timeSlots.length - 1
|
||||
|
||||
const idList = timeSlots.slice(startIndex, endIndex + 1).map(x => x.id)
|
||||
|
||||
const ret = await db['sd_raw_neulive'].findAll(
|
||||
{
|
||||
where: {
|
||||
id: idList
|
||||
},
|
||||
order: [
|
||||
['start_time_sec', 'ASC'],
|
||||
['start_time_micro', 'ASC']
|
||||
],
|
||||
raw: true,
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async getSdDataAllTimeslotByUUID (uuid, channel) {
|
||||
const ret = await db['sd_raw_neulive'].findAll(
|
||||
{
|
||||
where: {
|
||||
parent_uuid: uuid,
|
||||
channel: channel,
|
||||
},
|
||||
attributes: [
|
||||
'id',
|
||||
'start_time_sec',
|
||||
'end_time_sec',
|
||||
'start_time_micro',
|
||||
'end_time_micro',
|
||||
],
|
||||
order: [
|
||||
['start_time_sec', 'ASC'],
|
||||
['start_time_micro', 'ASC']
|
||||
],
|
||||
raw: true,
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async getByAttrID (id, attr, index) {
|
||||
const attrList = attr.split('-')
|
||||
const ret = await db[index + '_recording_data_raws'].findAll(
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
const db = require('../../db/database')
|
||||
|
||||
class SDRawNeulive {
|
||||
async create (req) {
|
||||
return db['sd_raw_neulive'].create(
|
||||
req
|
||||
)
|
||||
}
|
||||
|
||||
async getByParentUUID (parent_uuid) {
|
||||
const ret = await db['sd_raw_neulive'].findAllWithStream(
|
||||
{
|
||||
batchSize: 1000,
|
||||
where: {
|
||||
parent_uuid: parent_uuid
|
||||
},
|
||||
order: [
|
||||
['id', 'ASC']
|
||||
],
|
||||
attributes: [
|
||||
'data',
|
||||
'start_time',
|
||||
'end_time'
|
||||
]
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async clearDeleted (parent_uuid) {
|
||||
const ret = await db['sd_raw_neulive'].destroy(
|
||||
{
|
||||
where: {
|
||||
parent_uuid: parent_uuid
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
export default SDRawNeulive
|
||||
@@ -31,19 +31,6 @@ class ControllerModel {
|
||||
}
|
||||
}
|
||||
|
||||
async updateByID (req, id) {
|
||||
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
|
||||
const ret = await db.controllers.update(
|
||||
req,
|
||||
{
|
||||
where: {
|
||||
id: id
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async updateByAttr (req, attr, value) {
|
||||
const whereObj = {}
|
||||
const attrList = attr.split('-')
|
||||
@@ -105,6 +92,17 @@ class ControllerModel {
|
||||
return ret
|
||||
}
|
||||
|
||||
async getByMqttId (mqttId) {
|
||||
const ret = await db.controllers.findAll(
|
||||
{
|
||||
where: {
|
||||
mqtt_id: mqttId
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async getByAttr (attr, value) {
|
||||
const whereObj = {}
|
||||
const attrList = attr.split('-')
|
||||
|
||||
@@ -35,19 +35,6 @@ class DeviceModel {
|
||||
}
|
||||
}
|
||||
|
||||
async updateByID (req, id) {
|
||||
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
|
||||
const ret = await db.devices.update(
|
||||
req,
|
||||
{
|
||||
where: {
|
||||
id: id
|
||||
}
|
||||
}
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
async updateByMac (req, mac) {
|
||||
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
|
||||
const ret = await db.devices.update(
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import controllers from '../../controllers'
|
||||
|
||||
// '/api/analysis'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/analysis'
|
||||
return [
|
||||
['POST', prefix + '/spike_detect', controllers.analysis.spikeDetect],
|
||||
['POST', prefix + '/iir_filter', controllers.analysis.IIRFliter]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import controllers from '../../controllers'
|
||||
|
||||
// '/api/controller'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/controller'
|
||||
return [
|
||||
['POST', prefix + '/create', controllers.controller.create],
|
||||
['POST', prefix + '/update/:id', controllers.controller.update],
|
||||
['POST', prefix + '/update_by_attr/:attr/:value', controllers.controller.updateByAttr],
|
||||
['GET', prefix + '/get_by_name/:name', controllers.controller.getByName],
|
||||
['GET', prefix + '/get_by_mqtt_id/:mqtt_id', controllers.controller.getByMqttId],
|
||||
['GET', prefix + '/get_by_mac/:mac', controllers.controller.getByMac],
|
||||
['GET', prefix + '/get_by_attr/:attr/:value', controllers.controller.getByAttr],
|
||||
['GET', prefix + '/get/all', controllers.controller.getAll]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import controllers from '../../controllers'
|
||||
|
||||
// '/api/device'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/device'
|
||||
return [
|
||||
['POST', prefix + '/create', controllers.device.create],
|
||||
['POST', prefix + '/update/:id', controllers.device.update],
|
||||
['POST', prefix + '/update_by_mac/:mac', controllers.device.updateByMac],
|
||||
['POST', prefix + '/update_by_attr/:attr/:value', controllers.device.updateByAttr],
|
||||
['GET', prefix + '/clear_deleted/:id', controllers.device.clearDeleted],
|
||||
['GET', prefix + '/get_by_mac/:mac', controllers.device.getByMac],
|
||||
['GET', prefix + '/get_by_attr/:attr/:value', controllers.device.getByAttr],
|
||||
['GET', prefix + '/get/all', controllers.device.getAll]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/collection'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/collection'
|
||||
return [
|
||||
['POST', prefix + '/create', controllers.collection.create],
|
||||
['POST', prefix + '/update/:id', controllers.collection.update],
|
||||
['GET', prefix + '/clear_deleted/:controller_id', controllers.collection.clearDeleted],
|
||||
['GET', prefix + '/get_by_id/:id', controllers.collection.getByID],
|
||||
['GET', prefix + '/get_by_name/:name/:controller_id', controllers.collection.getByName],
|
||||
['GET', prefix + '/get_by_parent/:type/:parent', controllers.collection.getByParent],
|
||||
['GET', prefix + '/get_by_parent_name/:type/:parent/:name', controllers.collection.getByParentName],
|
||||
['GET', prefix + '/get/all/:controller_id', controllers.collection.getAll],
|
||||
['GET', prefix + '/get_by_name/:name', controllers.collection.getByName],
|
||||
['GET', prefix + '/get/all', controllers.collection.getAll],
|
||||
['GET', prefix + '/clear_deleted', controllers.collection.clearDeleted]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import collection from './collection'
|
||||
import meta from './meta'
|
||||
import mini from './mini'
|
||||
import raw from './raw'
|
||||
import sdcard from './sdcard'
|
||||
import trigger from './trigger'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/file'
|
||||
return [
|
||||
...collection(prefix),
|
||||
...meta(prefix),
|
||||
...mini(prefix),
|
||||
...raw(prefix),
|
||||
...sdcard(prefix),
|
||||
...trigger(prefix)
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/meta'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/meta'
|
||||
return [
|
||||
['POST', prefix + '/create', controllers.recordingDataMeta.create],
|
||||
['POST', prefix + '/update/:id', controllers.recordingDataMeta.update],
|
||||
['GET', prefix + '/clear_deleted/', controllers.recordingDataMeta.clearDeleted],
|
||||
['GET', prefix + '/get_by_name/:name', controllers.recordingDataMeta.getByName],
|
||||
['GET', prefix + '/get_by_uuid/:uuid', controllers.recordingDataMeta.getByUUID],
|
||||
['GET', prefix + '/get_by_id/:id', controllers.recordingDataMeta.getByID],
|
||||
['GET', prefix + '/get_by_path/:path', controllers.recordingDataMeta.getByPath],
|
||||
['GET', prefix + '/get_by_parent/:type/:parent', controllers.recordingDataMeta.getByParent],
|
||||
['GET', prefix + '/get_count_by_parent/:type/:parent', controllers.recordingDataMeta.getCountByParent],
|
||||
['GET', prefix + '/get_by_parent_with_limit/:type/:parent/:limit/:offset/:order', controllers.recordingDataMeta.getByParentWithLimit],
|
||||
['GET', prefix + '/get_by_attr_parent_with_limit/:type/:parent/:limit/:offset/:order/:attr', controllers.recordingDataMeta.getByAttrsParentWithLimit],
|
||||
['GET', prefix + '/get_or_create_by_path/:path', controllers.recordingDataMeta.getOrCreateByPath],
|
||||
['GET', prefix + '/get/all', controllers.recordingDataMeta.getAll],
|
||||
// control system 3.0
|
||||
['GET', prefix + '/get_meta_by_uuid/:uuid', controllers.recordingDataMeta.getMetaByUUID],
|
||||
['GET', prefix + '/get_meta_all', controllers.recordingDataMeta.getMetaAll],
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/mini'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/mini'
|
||||
return [
|
||||
['POST', prefix + '/create/:channel', controllers.recordingDataMini.create],
|
||||
['POST', prefix + '/update/:channel/:id', controllers.recordingDataMini.update],
|
||||
['GET', prefix + '/clear_deleted/:channel/:id', controllers.recordingDataMini.clearDeleted],
|
||||
['GET', prefix + '/get_by_id/:channel/:id', controllers.recordingDataMini.getByID],
|
||||
['GET', prefix + '/get_by_parent/:channel/:parent', controllers.recordingDataMini.getByParent],
|
||||
['GET', prefix + '/get_attr_by_id/:channel/:id/:attr', controllers.recordingDataMini.getAttrByID],
|
||||
['GET', prefix + '/get_attr_by_parent/:channel/:parent/:attr', controllers.recordingDataMini.getAttrByParent],
|
||||
['GET', prefix + '/random/get_by_id/:channel/:id', controllers.recordingDataMini.getRandomDataByID],
|
||||
['GET', prefix + '/mean/get_by_id/:channel/:id', controllers.recordingDataMini.getMeanDataByID]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/raw'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/raw'
|
||||
return [
|
||||
['POST', prefix + '/create/:channel', controllers.recordingDataRaw.create],
|
||||
['POST', prefix + '/update/:channel/:id', controllers.recordingDataRaw.update],
|
||||
['POST', prefix + '/update_sd_data/:channel/:id', controllers.recordingDataRaw.updateSdData],
|
||||
['GET', prefix + '/clear_deleted/:channel/:id', controllers.recordingDataRaw.clearDeleted],
|
||||
['GET', prefix + '/get_by_id/:channel/:id', controllers.recordingDataRaw.getByID],
|
||||
['GET', prefix + '/get_by_ids/:channel/:id', controllers.recordingDataRaw.getByIDs],
|
||||
['GET', prefix + '/get_data_by_id/:channel/:id', controllers.recordingDataRaw.getDataByID],
|
||||
['GET', prefix + '/get_sd_data_by_uuid/:uuid/:channel/:startTime/:endTime', controllers.recordingDataRaw.getSdDataByUUID],
|
||||
['GET', prefix + '/get_sd_data_all_timeslot_by_uuid/:uuid/:channel', controllers.recordingDataRaw.getSdDataAllTimeslotByUUID],
|
||||
['GET', prefix + '/get_by_parent/:channel/:parent', controllers.recordingDataRaw.getByParent],
|
||||
['GET', prefix + '/get_attr_by_id/:channel/:id/:attr', controllers.recordingDataRaw.getAttrByID],
|
||||
['GET', prefix + '/get_attr_by_ids/:channel/:id/:attr', controllers.recordingDataRaw.getAttrByIDs],
|
||||
['GET', prefix + '/get_attr_by_parent/:channel/:parent/:attr', controllers.recordingDataRaw.getAttrByParent]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/sdcard'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/sdcard'
|
||||
return [
|
||||
['GET', prefix + '/get', controllers.sdCard.getFileList],
|
||||
['POST', prefix + '/exist', controllers.sdCard.exist],
|
||||
['POST', prefix + '/upload', controllers.sdCard.uploadThenDelete],
|
||||
// ['POST', prefix + '/delete', controllers.sdCard.deleted]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/file/trigger'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/trigger'
|
||||
return [
|
||||
['GET', prefix + '/get_raw_by_uuid/:parent_uuid', controllers.trigger.getRawTriggerByUUID],
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import file from './file'
|
||||
import project from './project'
|
||||
import device from './device'
|
||||
import controller from './controller'
|
||||
import analysis from './analysis'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/api'
|
||||
|
||||
return [
|
||||
...file(prefix),
|
||||
...project(prefix),
|
||||
...device(prefix),
|
||||
...controller(prefix),
|
||||
...analysis(prefix)
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import task from './task'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/project'
|
||||
return [
|
||||
...task(prefix)
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import controllers from '../../../controllers'
|
||||
|
||||
// '/api/task'
|
||||
|
||||
export default function (_prefix) {
|
||||
const prefix = _prefix + '/task'
|
||||
return [
|
||||
['POST', prefix + '/create', controllers.task.create],
|
||||
['POST', prefix + '/update/:id', controllers.task.update],
|
||||
['POST', prefix + '/update_by_attr/:attr/:value', controllers.task.updateByAttr],
|
||||
['GET', prefix + '/get_by_id/:id', controllers.task.getByID],
|
||||
['GET', prefix + '/get_by_attr/:attr/:value', controllers.task.getByAttr],
|
||||
['GET', prefix + '/get/all', controllers.task.getAll]
|
||||
]
|
||||
}
|
||||
+26
-102
@@ -1,111 +1,35 @@
|
||||
import KoaRouter from 'koa-router'
|
||||
import controllers from '../controllers'
|
||||
import api from './api'
|
||||
|
||||
const router = new KoaRouter()
|
||||
|
||||
export default router
|
||||
.get('/public/get', function (ctx, next) {
|
||||
ctx.body = '禁止访问!'
|
||||
})
|
||||
.all('/upload', controllers.upload)
|
||||
.get('/public/api/:name', controllers.api.Get)
|
||||
.post('/api/:name', controllers.api.Post)
|
||||
.put('/api/:name', controllers.api.Put)
|
||||
.del('/api/:name', controllers.api.Delete)
|
||||
.post('/auth/:action', controllers.auth.Post)
|
||||
router
|
||||
// .get('/public/get', function (ctx, next) {
|
||||
// ctx.body = 'no access'
|
||||
// })
|
||||
// .all('/upload', controllers.upload)
|
||||
// .get('/public/api/:name', controllers.api.Get)
|
||||
// .post('/api/:name', controllers.api.Post)
|
||||
// .put('/api/:name', controllers.api.Put)
|
||||
// .del('/api/:name', controllers.api.Delete)
|
||||
// .post('/auth/:action', controllers.auth.Post)
|
||||
// user
|
||||
.get('/public/auth/get_cookie', controllers.auth.getCookie)
|
||||
.get('/public/auth/update_license', controllers.auth.updateLicense)
|
||||
.get('/public/auth/check_license', controllers.auth.checkLicense)
|
||||
|
||||
// collection
|
||||
.post('/api/file/collection/create', controllers.collection.create)
|
||||
.post('/api/file/collection/update/:id', controllers.collection.update)
|
||||
.get('/api/file/collection/clear_deleted/:controller_id', controllers.collection.clearDeleted)
|
||||
.get('/api/file/collection/get_by_id/:id', controllers.collection.getByID)
|
||||
.get('/api/file/collection/get_by_name/:name/:controller_id', controllers.collection.getByName)
|
||||
.get('/api/file/collection/get_by_parent/:type/:parent', controllers.collection.getByParent)
|
||||
.get('/api/file/collection/get_by_parent_name/:type/:parent/:name', controllers.collection.getByParentName)
|
||||
.get('/api/file/collection/get/all/:controller_id', controllers.collection.getAll)
|
||||
for (const _route of api('')) {
|
||||
switch (_route[0]) {
|
||||
case 'GET':
|
||||
router.get(_route[1], _route[2])
|
||||
break
|
||||
case 'POST':
|
||||
router.post(_route[1], _route[2])
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
.get('/api/file/collection/get_by_name/:name', controllers.collection.getByName)
|
||||
.get('/api/file/collection/get/all', controllers.collection.getAll)
|
||||
.get('/api/file/collection/clear_deleted/', controllers.collection.clearDeleted)
|
||||
|
||||
// meta
|
||||
.post('/api/file/meta/create', controllers.recordingDataMeta.create)
|
||||
.post('/api/file/meta/update/:id', controllers.recordingDataMeta.update)
|
||||
.get('/api/file/meta/clear_deleted/', controllers.recordingDataMeta.clearDeleted)
|
||||
.get('/api/file/meta/get_by_name/:name', controllers.recordingDataMeta.getByName)
|
||||
.get('/api/file/meta/get_by_uuid/:uuid', controllers.recordingDataMeta.getByUUID)
|
||||
.get('/api/file/meta/get_by_id/:id', controllers.recordingDataMeta.getByID)
|
||||
.get('/api/file/meta/get_by_path/:path', controllers.recordingDataMeta.getByPath)
|
||||
.get('/api/file/meta/get_by_parent/:type/:parent', controllers.recordingDataMeta.getByParent)
|
||||
.get('/api/file/meta/get_count_by_parent/:type/:parent', controllers.recordingDataMeta.getCountByParent)
|
||||
.get('/api/file/meta/get_by_parent_with_limit/:type/:parent/:limit/:offset/:order', controllers.recordingDataMeta.getByParentWithLimit)
|
||||
.get('/api/file/meta/get_by_attr_parent_with_limit/:type/:parent/:limit/:offset/:order/:attr', controllers.recordingDataMeta.getByAttrsParentWithLimit)
|
||||
|
||||
.get('/api/file/meta/get_or_create_by_path/:path', controllers.recordingDataMeta.getOrCreateByPath)
|
||||
.get('/api/file/meta/get/all', controllers.recordingDataMeta.getAll)
|
||||
|
||||
// raw
|
||||
.post('/api/file/raw/create/:channel', controllers.recordingDataRaw.create)
|
||||
.post('/api/file/raw/update/:channel/:id', controllers.recordingDataRaw.update)
|
||||
.post('/api/file/raw/update_sd_data/:channel/:id', controllers.recordingDataRaw.updateSdData)
|
||||
.get('/api/file/raw/clear_deleted/:channel/:id', controllers.recordingDataRaw.clearDeleted)
|
||||
.get('/api/file/raw/get_by_id/:channel/:id', controllers.recordingDataRaw.getByID)
|
||||
.get('/api/file/raw/get_by_ids/:channel/:id', controllers.recordingDataRaw.getByIDs)
|
||||
.get('/api/file/raw/get_data_by_id/:channel/:id', controllers.recordingDataRaw.getDataByID)
|
||||
.get('/api/file/raw/get_by_parent/:channel/:parent', controllers.recordingDataRaw.getByParent)
|
||||
.get('/api/file/raw/get_attr_by_id/:channel/:id/:attr', controllers.recordingDataRaw.getAttrByID)
|
||||
.get('/api/file/raw/get_attr_by_ids/:channel/:id/:attr', controllers.recordingDataRaw.getAttrByIDs)
|
||||
.get('/api/file/raw/get_attr_by_parent/:channel/:parent/:attr', controllers.recordingDataRaw.getAttrByParent)
|
||||
|
||||
// mini
|
||||
.post('/api/file/mini/create/:channel', controllers.recordingDataMini.create)
|
||||
.post('/api/file/mini/update/:channel/:id', controllers.recordingDataMini.update)
|
||||
.get('/api/file/mini/clear_deleted/:channel/:id', controllers.recordingDataMini.clearDeleted)
|
||||
.get('/api/file/mini/get_by_id/:channel/:id', controllers.recordingDataMini.getByID)
|
||||
.get('/api/file/mini/get_by_parent/:channel/:parent', controllers.recordingDataMini.getByParent)
|
||||
.get('/api/file/mini/get_attr_by_id/:channel/:id/:attr', controllers.recordingDataMini.getAttrByID)
|
||||
.get('/api/file/mini/get_attr_by_parent/:channel/:parent/:attr', controllers.recordingDataMini.getAttrByParent)
|
||||
.get('/api/file/mini/random/get_by_id/:channel/:id', controllers.recordingDataMini.getRandomDataByID)
|
||||
.get('/api/file/mini/mean/get_by_id/:channel/:id', controllers.recordingDataMini.getMeanDataByID)
|
||||
|
||||
// device
|
||||
.post('/api/device/create', controllers.device.create)
|
||||
.post('/api/device/update/all', controllers.device.update)
|
||||
.post('/api/device/update_by_id/:id', controllers.device.updateByID)
|
||||
.post('/api/device/update_by_mac/:mac', controllers.device.updateByMac)
|
||||
.post('/api/device/update_by_attr/:attr/:value', controllers.device.updateByAttr)
|
||||
.get('/api/device/clear_deleted/:id', controllers.device.clearDeleted)
|
||||
.get('/api/device/get_by_mac/:mac', controllers.device.getByMac)
|
||||
.get('/api/device/get_by_attr/:attr/:value', controllers.device.getByAttr)
|
||||
.get('/api/device/get/all', controllers.device.getAll)
|
||||
|
||||
.post('/api/device/update_by_id/:id', controllers.device.updateByID)
|
||||
.post('/api/device/update', controllers.device.update)
|
||||
|
||||
// controller
|
||||
.post('/api/controller/create', controllers.controller.create)
|
||||
.post('/api/controller/update/:id', controllers.controller.update)
|
||||
.post('/api/controller/update/all', controllers.controller.update)
|
||||
.post('/api/controller/update_by_attr/:attr/:value', controllers.controller.updateByAttr)
|
||||
.get('/api/controller/get_by_mac/:mac', controllers.controller.getByMac)
|
||||
.get('/api/controller/get_by_attr/:attr/:value', controllers.controller.getByAttr)
|
||||
.get('/api/controller/get/all', controllers.controller.getAll)
|
||||
|
||||
.post('/api/controller/update_by_id/:id', controllers.controller.updateByID)
|
||||
.post('/api/controller/update', controllers.controller.update)
|
||||
|
||||
// task
|
||||
.post('/api/task/create', controllers.task.create)
|
||||
.post('/api/task/update/:id', controllers.task.update)
|
||||
.post('/api/task/update_by_attr/:attr/:value', controllers.task.updateByAttr)
|
||||
.post('/api/task/update/all', controllers.task.update)
|
||||
.get('/api/task/get_by_id/:id', controllers.task.getByID)
|
||||
.get('/api/task/get_by_attr/:attr/:value', controllers.task.getByAttr)
|
||||
.get('/api/task/get/all', controllers.task.getAll)
|
||||
|
||||
.post('/api/task/update', controllers.task.update)
|
||||
.post('/api/task/update_by_id/:id', controllers.task.updateByID)
|
||||
// analyze
|
||||
.post('/api/analysis/spike_detect', controllers.analysis.spikeDetect)
|
||||
export default router
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Elite: 53
|
||||
# Neulive: 101 or 95
|
||||
ssh -NL 54321:localhost:5432 pi@192.168.2.1
|
||||
Reference in New Issue
Block a user