Compare commits

..

65 Commits

Author SHA1 Message Date
Jordan Hsu 14f987a49d [add] get meta all api 2022-01-26 16:24:08 +08:00
Jordan Hsu 074e163c95 [add] trigger raw & meta download 2022-01-26 10:24:00 +08:00
TommyXin 29325f2165 Merge remote-tracking branch 'origin/feature/sd_data' into feature/sd_data 2022-01-13 23:17:02 +08:00
TommyXin 21ca818ab6 remove 54321 2022-01-13 23:16:43 +08:00
warren30815 6d7f5d26ee Update README.md 2022-01-12 06:05:23 +00:00
TommyXin 68e4e6ffea add ads_start_time in meta 2021-12-23 17:49:47 +08:00
TommyXin eeb08342f6 Merge remote-tracking branch 'origin/feature/sd_data' into feature/sd_data 2021-12-02 16:10:21 +08:00
TommyXin 64988aa95a db 64 channel 2021-12-02 16:10:06 +08:00
peterlu14 e4816e9447 [update] sd card error handling 2021-11-23 12:43:15 +08:00
peterlu14 b1c92721be [update] sd card api rebuild 2021-11-19 18:06:44 +08:00
peterlu14 d27946ed88 [update] IIRFilter path 2021-11-19 11:43:18 +08:00
peterlu14 adc5686033 [update] change new path 2021-11-18 15:44:45 +08:00
TommyXin 5f9c91e5e7 status 202 2021-11-18 11:05:38 +08:00
TommyXin e5ccd05903 wlan to eth 2021-11-17 22:02:14 +08:00
TommyXin 358687c8dd Merge remote-tracking branch 'origin/feature/sd_data' into feature/sd_data 2021-11-17 19:58:24 +08:00
TommyXin 283c3fbb57 eth0 to wlan0 2021-11-17 19:27:18 +08:00
warren30815 8edfaf6224 Update README.md 2021-11-17 11:14:56 +00:00
TommyXin ed511992ea fix update license ret.status 2021-11-17 18:25:35 +08:00
TommyXin 8ebae697b1 fix routes prefix 2021-11-17 16:49:25 +08:00
TommyXin 93a0888de5 Merge remote-tracking branch 'origin/feature/sd_data' into feature/sd_data 2021-11-17 16:46:34 +08:00
TommyXin c0c23e77ee opt main-routes 2021-11-17 16:46:22 +08:00
warren30815 684a1fa44b Update README.md 2021-11-17 06:19:39 +00:00
TommyXin fb87eb90ca crypto func name 2021-11-17 11:34:19 +08:00
TommyXin 7b22866929 add token cute path 2021-11-17 11:20:35 +08:00
TommyXin aa5db953a8 remove :mac on routes 2021-11-16 16:16:47 +08:00
TommyXin 4e1021acb9 fix reading mac 2021-11-16 16:15:54 +08:00
TommyXin 3d763a3e36 read mac 2021-11-16 15:53:12 +08:00
TommyXin ad0f54775b add cute & check license 2021-11-16 14:52:07 +08:00
TommyXin 251dcfb750 update license 2021-11-15 17:21:44 +08:00
TommyXin 62b60d02e4 [README] install nodejs 2021-11-01 11:26:46 +08:00
TommyXin 82587d7506 change iir filter.py order 2021-10-27 16:07:47 +08:00
TommyXin 51d69d5a97 change iir filter path 2021-10-26 15:14:16 +08:00
TommyXin 9319fa131b iir notch 2021-10-25 10:47:19 +08:00
peterlu14 10cd8c2d1b [update] remove device table transmission_type column 2021-10-25 10:44:50 +08:00
weiting2 a93d784d16 [update] sd_data get uuid list update 2021-10-21 14:53:38 +08:00
Jordan Hsu 54bccd0253 Merge branch 'master' into feature/sd_data 2021-10-18 17:51:51 +08:00
peterlu14 f49750a70a [update] remove useless route 2021-10-15 11:32:29 +08:00
peterlu14 fc29545948 [update] remove update_by_id 2021-10-15 11:24:55 +08:00
peterlu14 000722d2d1 [update] add device table column 'transmission_type' 2021-10-15 11:22:32 +08:00
peterlu14 9e9dd22bdf [update] fix eslint style error 2021-10-13 19:08:55 +08:00
peterlu14 a6ec77c523 [update] change directory name 2021-10-12 11:05:19 +08:00
TommyXin 1f1795eb6c Merge remote-tracking branch 'origin/feature/sd_data' into feature/sd_data 2021-10-08 18:12:08 +08:00
TommyXin 373fbafd6c iir filter 2021-10-08 18:08:39 +08:00
peterlu14 e1200a47a1 [update] add filterOrder 2021-10-08 17:37:31 +08:00
peterlu14 667469dd50 [update] name fix 2021-10-08 15:30:33 +08:00
peterlu14 83816f16d4 [update] delete spike_detect & name fix 2021-10-08 15:27:55 +08:00
peterlu14 92fdfefa30 [update] change spike index.js 2021-10-05 10:19:22 +08:00
peterlu14 d7bfc9d7c2 [update] recover spike code 2021-09-27 16:07:35 +08:00
peterlu14 a0e74c61ee [update] fix mac compare 2021-09-24 17:54:57 +08:00
peterlu14 293db99a2e [update] controller add column sd_uploading 2021-09-24 12:43:47 +08:00
peterlu14 6e05fda2e3 [update] reformat promise & upload req setTimeout 120s to unlimit 2021-09-23 17:52:13 +08:00
peterlu14 1826a8618b [update] avoid uuid read error & promise rebuild 2021-09-22 14:13:15 +08:00
peterlu14 97a3176bd9 [update] sd get function spawnSync to spawn 2021-09-16 13:47:44 +08:00
peterlu14 2cd467b431 [update] avoid sd_card decode key error 2021-09-15 02:28:47 +08:00
peterlu14 1574883381 [update] record default true & mac None 2021-09-14 13:27:01 +08:00
peterlu14 78f29fe34c [update] change sd get output & recover exist api 2021-09-14 11:40:58 +08:00
peterlu14 6882cd320f [update] add sd_data_record & remove sd_data_exist 2021-09-14 00:39:49 +08:00
peterlu14 b74bbe083d [update] sd_delete 2021-09-13 16:39:11 +08:00
peterlu14 cef86f27c2 [update] mac address update 2021-09-13 13:31:02 +08:00
peterlu14 3b2114b95f [update] fix sd card upload data format 2021-09-10 12:18:15 +08:00
peterlu14 3164add2c0 [update] update naming and remove \n 2021-09-08 16:20:00 +08:00
peterlu14 9b5d237928 [update] sd route change 2021-09-08 10:49:43 +08:00
peterlu14 54be774fe8 [update] add sd card api 2021-09-08 10:35:52 +08:00
peterlu14 52a4dac990 [update] down sample 2021-09-03 19:02:59 +08:00
peterlu14 9a3d9689fd Merge branch 'master' into feature/spike_detect 2021-09-03 19:01:53 +08:00
64 changed files with 1018 additions and 58470 deletions
+24 -6
View File
@@ -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
+13
View File
@@ -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
View File
@@ -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
View File
@@ -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 addressas 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: 5432, // 数据库端口号
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>'
}
+38
View File
@@ -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='')
+86 -38
View File
@@ -1,68 +1,116 @@
import RecordingDataMeta from '../../models/file/recording_data_meta'
import childProcess from 'child_process'
import path from 'path'
import { createReadStream } from 'fs'
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 getCSV = async (ctx, next) => {
const name = ctx.query.name
ctx.type = 'stream'
// ctx.attachment = name + '.csv'
ctx.set('Content-disposition', `attachment; filename=${name}.csv`)
ctx.body = createReadStream(path.resolve(__dirname, '../../../../data-analysis/csv_file', 'output.csv'))
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()
}
-110
View File
@@ -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
View File
@@ -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
}
})
})
}
-39
View File
@@ -1,39 +0,0 @@
import ConfigurationModal from '../../models/configuration/configuration'
const configuration = new ConfigurationModal()
export const create = async (ctx, next) => {
const data = ctx.request.body
const result = await configuration.create(data)
ctx.body = result
next()
}
export const update = async (ctx, next) => {
const data = ctx.request.body
const id = ctx.params.id
const result = await configuration.update(data, id)
ctx.body = result
next()
}
export const get = async (ctx, next) => {
const configurationType = ctx.query.type
const id = ctx.query.id
const library = ctx.query.library
const query = { id: id, library: library }
const result = await configuration.get(configurationType, query)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const controllerID = ctx.params.controller_id
const result = await configuration.clearDeleted(controllerID)
ctx.body = result
next()
}
-27
View File
@@ -19,33 +19,6 @@ export const update = async (ctx, next) => {
next()
}
export const get = async (ctx, next) => {
const id = ctx.query.id
const name = ctx.query.name
const type = ctx.query.type
const controllerId = ctx.query.controllerId
// folder
const parent = ctx.query.parent
const limit = ctx.query.limit
const offset = ctx.query.offset
const order = ctx.query.order
const attrs = ctx.query.attrs
const query = {}
let result = ''
if (id) query.id = id
if (name) query.name = name
if (type) query.type = type
if (controllerId) query.controllerId = controllerId
if (id || name) result = await collection.getByQueryWithAttrs(query, attrs)
if (type === 'folder') result = await collection.getByParentWithOffsetLimitOrder(type, parent, limit, offset, order)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const controllerID = ctx.params.controller_id
const result = await collection.clearDeleted(controllerID)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-105
View File
@@ -1,105 +0,0 @@
import psycopg2
import pandas as pd
import numpy as np
def log(df, channel):
# TODO: not sure need use 32 or 64?
df[f'{channel}_log'] = np.log10(np.absolute(df[channel].astype(np.int32)))
return df
def integral(df, x_channel, y_channel, pre_last_x, pre_last_y, integral_result):
offset = df[x_channel]
offset = offset.shift(periods=1)
offset[0] = pre_last_x
x_diff = df[x_channel].astype(np.int32) - offset.astype(np.int32)
# print('x_diff\n', x_diff)
offset = df[y_channel]
offset = offset.shift(periods=1)
offset[0] = pre_last_y
y_avg = (offset.astype(np.int32) + df[y_channel].astype(np.int32)) / 2
# print('y_avg:', y_avg)
# print('y_avg: ', y_avg)
local_integral = x_diff * y_avg
local_integral[0] += integral_result
# TODO: if user don't need, then can remove it
df[f'{x_channel}_{y_channel}_integral_delta'] = local_integral
df[f'{x_channel}_{y_channel}_integral'] = local_integral.cumsum()
# print(df)
pre_last_x = df[x_channel].iat[-1]
pre_last_y = df[y_channel].iat[-1]
integral_result = df[f'{x_channel}_{y_channel}_integral'].iat[-1]
# print('next run info: ', pre_last_x, pre_last_y, integral_result)
return df, pre_last_x, pre_last_y, integral_result
def differential(df, x_channel, y_channel, pre_last_x, pre_last_y):
offset = df[x_channel]
offset = offset.shift(periods=1)
offset[0] = pre_last_x
x_diff = df[x_channel].astype(np.int32) - offset.astype(np.int32)
offset = df[y_channel]
offset = offset.shift(periods=1)
offset[0] = pre_last_y
y_diff = df[y_channel].astype(np.int32) - offset.astype(np.int32)
local_diff = y_diff / x_diff
print(local_diff)
# TODO: if user don't need, then can remove it
df[f'{x_channel}_{y_channel}_diff'] = local_diff
pre_last_x = df[x_channel].iat[-1]
pre_last_y = df[y_channel].iat[-1]
return df, pre_last_x, pre_last_y
if __name__ == '__main__':
# TODO: function parameters: id, mode, x_channel, y_channel
conn = psycopg2.connect(database="postgres", user="biopro", password="BioProControlBox", host="127.0.0.1", port="5432")
cur = conn.cursor()
id = 1262
# id = 407
# id = 1073
# id = 968
mode = 'differential'
# mode = 'integral'
# mode = 'log'
sql_str = f'select "raw_data" from "recording_data_metas" WHERE id = {id}' # recording_data_metas: meta info to get the raw_data table
# sql_str = 'select "raw_data" from "recording_data_metas" WHERE id = 407' # recording_data_metas: meta info to get the raw_data table
# sql_str = 'select * from "0_recording_data_raws" WHERE id = 33384'
cur.execute(sql_str)
raw_data_list = None
# x_
try:
raw_data_list = cur.fetchall()[0][0]
# print(ret[0][0]['0'])
channels = list(raw_data_list.keys())
df = pd.DataFrame()
df_time = []
pre_last_x = 0
pre_last_y = 0
integral_result = 0
# print('len(raw_data_list[channels[0]]): ', len(raw_data_list[channels[0]]))
for raw_data_pages in range(len(raw_data_list[channels[0]])):
for channel in channels:
sql_str = f'select "data" from "{channel}_recording_data_raws" WHERE id = {raw_data_list[channel][raw_data_pages]}'
cur.execute(sql_str)
data_value = cur.fetchall()[0][0].replace('"***"', ' ')
data_value = data_value.split(' ')[:-1]
if df.empty:
df_time = data_value[::2]
df[channel] = data_value
df = df.iloc[lambda x: x.index % 2 == 1].reset_index(drop=True)
df.insert(0, 'time', df_time)
if mode == 'log':
x_channel = '1'
df = log(df, x_channel)
elif mode == 'integral':
# TODO: x_channel and y_channel will need to be set as parameters
x_channel = 'time'
y_channel = '0'
df, pre_last_x, pre_last_y, integral_result = integral(df, x_channel, y_channel, pre_last_x, pre_last_y, integral_result)
elif mode == 'differential':
x_channel = '1'
y_channel = '0'
df, pre_last_x, pre_last_y = differential(df, x_channel, y_channel, pre_last_x, pre_last_y)
# print(df)
df.to_csv(f"csv_test/{id}.csv", mode='a', index=False, header=False)
df = pd.DataFrame()
except BaseException as e:
print(e)
exit
@@ -31,49 +31,6 @@ export const clearDeleted = async (ctx, next) => {
next()
}
export const findWithIdRange = async (ctx, next) => {
const id = JSON.parse(ctx.query.id)
const range = JSON.parse(ctx.query.range)
const result = await recordingDataMeta.findWithIdRange1(id, range)
ctx.body = result
next()
}
export const get = async (ctx, next) => {
const id = ctx.query.id
const name = ctx.query.name
const uuid = ctx.query.uuid
const type = ctx.query.type
const time = ctx.query.time
// folder
const parent = ctx.query.parent
const limit = ctx.query.limit
const offset = ctx.query.offset
const order = ctx.query.order
const attrs = ctx.query.attrs
const group = ctx.query.group
// project
const project = ctx.query.project
const query = {}
let result = ''
if (id) query.id = id
if (name) query.name = name
if (uuid) query.uuid = uuid
if (time) query.time = time
if ((id || name || uuid || time) || type === undefined) result = await recordingDataMeta.getByQueryWithAttrs(query, limit, offset, order, attrs, group)
if (type === 'folder' && parent) result = await recordingDataMeta.getByFolderWithParentLimitOffsetOrderAttrs(type, parent, limit, offset, order, attrs)
if (type === 'project' && project) result = await recordingDataMeta.getByProject(project)
ctx.body = result
next()
}
export const getByID = async (ctx, next) => {
const id = ctx.params.id
const result = await recordingDataMeta.getByID(id)
@@ -91,16 +48,6 @@ export const getByParent = async (ctx, next) => {
next()
}
export const getAttrByParent = async (ctx, next) => {
const type = ctx.params.type
const parent = ctx.params.parent
const attr = ctx.params.attr
const result = await recordingDataMeta.getByAttrParent(type, parent, attr)
ctx.body = result
next()
}
export const getCountByParent = async (ctx, next) => {
const type = ctx.params.type
const parent = ctx.params.parent
@@ -61,15 +61,6 @@ export const getByID = async (ctx, next) => {
next()
}
export const getExistOrNotByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await recordingDataMini.getExistOrNotByID(id, index)
ctx.body = result
next()
}
export const getByIDs = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
@@ -80,6 +80,15 @@ export const getDataByID = async (ctx, next) => {
next()
}
export const getSdDataByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await recordingDataRaw.getSdDataByID(id, index)
ctx.body = result
next()
}
export const getByParent = async (ctx, next) => {
const index = ctx.params.channel
const parent = ctx.params.parent
+195
View File
@@ -0,0 +1,195 @@
import RecordingDataMeta from '../../../models/file/recording_data_meta'
import Controller from '../../../models/product/controller'
import childProcess from 'child_process'
import path from 'path'
import { homedir } from 'os'
const recordingDataMeta = new RecordingDataMeta()
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 (uuidPath, uuid, ampGain) {
return new Promise((resolve, reject) => {
const subprocess = childProcess.spawn('python3', [
path.join(...sdUploadPath),
uuidPath,
uuid,
ampGain
])
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
const uuidPath = await getPath(uuid)
const ampGain = await getParameter(metaID, 'AMP_GAIN')
// timeout defualt 120s to no-limit
ctx.req.setTimeout(0)
// controller column sd_uploading update
await controller.update({
sd_uploading: true
}, controllerID)
const uploadResult = await uploadPromise(uuidPath, uuid, ampGain)
if (uploadResult === 'true') {
// meta sd_card_uploaded true
await recordingDataMeta.update({
sd_data_uploaded: true
}, metaID)
await deletePromise(uuidPath)
}
// 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()
// }
-60
View File
@@ -1,60 +0,0 @@
time 0 1 2 3 time_0_integral
0 0 -73922 -836265 -848970 0 0.000000e+00
1 10500 -84368 -834380 -848548 0 -8.310225e+08
2 21000 -84389 -834380 -848126 0 -1.716997e+09
3 31500 -84332 -835637 -847704 0 -2.602782e+09
4 42500 -84166 -835637 -847283 0 -3.529521e+09
... ... ... ... ... .. ...
1462 15390500 -45761 -449806 -466674 0 -9.716838e+11
1463 15401000 -45833 -449806 -466445 0 -9.721646e+11
1464 15411500 -45790 -451063 -466216 0 -9.726457e+11
1465 15422500 -45638 -449806 -465988 0 -9.731485e+11
1466 15432500 -45674 -449806 -465759 0 -9.736051e+11
[1467 rows x 6 columns]
next run info: 15432500 -45674 -973605066500.0
time 0 1 2 3 time_0_integral
0 15443000 -45689 -448549 -465531 0 -9.740847e+11
1 15453500 -45689 -448549 -465531 0 -9.745645e+11
2 15464000 -45631 -449178 -465303 0 -9.750439e+11
3 15474500 -45581 -447921 -465075 0 -9.755227e+11
4 15485500 -45646 -447921 -464847 0 -9.760245e+11
... ... ... ... ... .. ...
1443 30720000 -24971 -248122 -259749 0 -1.497382e+12
1444 30730500 -24920 -247950 -259624 0 -1.497644e+12
1445 30741000 -24920 -248381 -259624 0 -1.497905e+12
1446 30751500 -24791 -248036 -259500 0 -1.498166e+12
1447 30762000 -24856 -247346 -259376 0 -1.498427e+12
[1448 rows x 6 columns]
next run info: 30762000 -24856 -1498426872750.0
time 0 1 2 3 time_0_integral
0 30772500 -24913 -247669 -259251 0 -1.498688e+12
1 30783000 -24848 -247669 -259127 0 -1.498949e+12
2 30794000 -24805 -247669 -259003 0 -1.499222e+12
3 30804000 -24805 -247454 -259003 0 -1.499471e+12
4 30814500 -24870 -247238 -258879 0 -1.499731e+12
... ... ... ... ... .. ...
1456 46091500 -13496 -134943 -147002 0 -1.783935e+12
1457 46102000 -13510 -134921 -146934 0 -1.784077e+12
1458 46112500 -13510 -134123 -146934 0 -1.784219e+12
1459 46123000 -13597 -134339 -146866 0 -1.784361e+12
1460 46134000 -13525 -134598 -146799 0 -1.784510e+12
[1461 rows x 6 columns]
next run info: 46134000 -13525 -1784510350500.0
time 0 1 2 3 time_0_integral
0 46144500 -13366 -134210 -146732 0 -1.784652e+12
1 46154500 -13460 -134210 -146665 0 -1.784786e+12
2 46165500 -13503 -134016 -146597 0 -1.784934e+12
3 46176000 -13503 -134102 -146597 0 -1.785076e+12
4 46186500 -13431 -134167 -146530 0 -1.785217e+12
.. ... ... ... ... .. ...
583 52277500 -10487 -105193 -117883 0 -1.858083e+12
584 52288000 -10573 -105042 -117830 0 -1.858194e+12
585 52298500 -10595 -105106 -117778 0 -1.858305e+12
586 52309000 -10494 -105085 -117725 0 -1.858415e+12
587 52319500 -10523 -105085 -117672 0 -1.858526e+12
[588 rows x 6 columns]
next run info: 52319500 -10523 -1858525771000.0
+28
View File
@@ -0,0 +1,28 @@
import RecordingMeta from '../../../models/file/bps_recording_meta'
import TriggerRaw from '../../../models/file/bps_trigger_raw'
const recordingMeta = new RecordingMeta()
const triggerRaw = new TriggerRaw()
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()
}
export const getTriggerRawByUUID = async (ctx, next) => {
const parent_uuid = ctx.params.parent_uuid
const result = await triggerRaw.getDataByUUID(parent_uuid)
ctx.body = result
next()
}
+4 -8
View File
@@ -9,10 +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 project from './project/project'
import * as projectReport from './project/project_report'
import * as projectMeta from './project/project_meta'
import * as chart from './configuration/chart'
import * as sdCard from './file/sd_card'
import * as trigger from './file/trigger'
export default {
upload,
@@ -26,8 +24,6 @@ export default {
recordingDataRaw,
recordingDataMini,
analysis,
project,
projectReport,
projectMeta,
chart
sdCard,
trigger,
}
+16 -9
View File
@@ -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
+1 -9
View File
@@ -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()
-62
View File
@@ -1,62 +0,0 @@
import ProjectModal from '../../models/project/project'
const project = new ProjectModal()
export const create = async (ctx, next) => {
const data = ctx.request.body
console.log('create', data)
const result = await project.create(data)
ctx.body = result
next()
}
export const update = async (ctx, next) => {
const data = ctx.request.body
const id = ctx.params.id
const result = await project.update(data, id)
ctx.body = result
next()
}
export const updateByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await project.updateByAttr(attr, value)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const result = await project.clearDeleted()
ctx.body = result
next()
}
export const getByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await project.getByID(id, index)
ctx.body = result
next()
}
export const getByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await project.getByAttr(attr, value)
ctx.body = result
next()
}
export const getAll = async (ctx, next) => {
const result = await project.getAll()
ctx.body = result
next()
}
-82
View File
@@ -1,82 +0,0 @@
import ProjectMeta from '../../models/project/project_meta'
const projectMeta = new ProjectMeta()
export const create = async (ctx, next) => {
const data = ctx.request.body
console.log('create', data)
const result = await projectMeta.create(data)
ctx.body = result
next()
}
export const update = async (ctx, next) => {
const data = ctx.request.body
const id = ctx.params.id
const result = await projectMeta.update(data, id)
ctx.body = result
next()
}
export const updateByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await projectMeta.updateByAttr(attr, value)
ctx.body = result
next()
}
export const get = async (ctx, next) => {
const id = ctx.query.id
const name = ctx.query.name
const uuid = ctx.query.uuid
const attrs = ctx.query.attrs
const order = ctx.query.order
const query = {}
let result = ''
if (id) query.id = id
if (name) query.name = name
if (uuid) query.uuid = uuid
result = await projectMeta.getByQueryWithAttrs(query, attrs, order)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const result = await projectMeta.clearDeleted()
ctx.body = result
next()
}
export const getByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await projectMeta.getByID(id, index)
ctx.body = result
next()
}
export const getByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await projectMeta.getByAttr(attr, value)
ctx.body = result
next()
}
export const getAll = async (ctx, next) => {
const result = await projectMeta.getAll()
ctx.body = result
next()
}
-82
View File
@@ -1,82 +0,0 @@
import ProjectReport from '../../models/project/project_report'
const projectReport = new ProjectReport()
export const create = async (ctx, next) => {
const data = ctx.request.body
console.log('create', data)
const result = await projectReport.create(data)
ctx.body = result
next()
}
export const update = async (ctx, next) => {
const data = ctx.request.body
const id = ctx.params.id
const result = await projectReport.update(data, id)
ctx.body = result
next()
}
export const updateByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await projectReport.updateByAttr(attr, value)
ctx.body = result
next()
}
export const get = async (ctx, next) => {
const id = ctx.query.id
const name = ctx.query.name
const uuid = ctx.query.uuid
const attrs = ctx.query.attrs
const order = ctx.query.order
const query = {}
let result = ''
if (id) query.id = id
if (name) query.name = name
if (uuid) query.uuid = uuid
result = await projectReport.getByQueryWithAttrs(query, attrs, order)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const result = await projectReport.clearDeleted()
ctx.body = result
next()
}
export const getByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await projectReport.getByID(id, index)
ctx.body = result
next()
}
export const getByAttr = async (ctx, next) => {
const attr = ctx.params.attr
const value = ctx.params.value
const result = await projectReport.getByAttr(attr, value)
ctx.body = result
next()
}
export const getAll = async (ctx, next) => {
const result = await projectReport.getAll()
ctx.body = result
next()
}
+10 -12
View File
@@ -27,23 +27,21 @@ db.controllers = require('./schema/controller.model')(sequelize, Sequelize)
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.projects = require('./schema/project.model')(sequelize, Sequelize)
db.project_reports = require('./schema/project_report.model')(sequelize, Sequelize)
db.project_metas = require('./schema/project_meta.model')(sequelize, Sequelize)
db.recording_data_metas = require('./schema/recording_data_meta.model')(sequelize, Sequelize)
db.charts = require('./schema/configuration/chart.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++) {
// db[i + '_recording_data_raws'] = require('./schema/recording_data_raw.model')(sequelize, Sequelize, i)
// }
// for (let i = 256; i < 288; i++) {
// db[i + '_recording_data_minis'] = require('./schema/recording_data_mini.model')(sequelize, Sequelize, i)
// }
for (let i = 256; i < 288; i++) {
db[i + '_recording_data_raws'] = require('./schema/recording_data_raw.model')(sequelize, Sequelize, 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.trigger_raw = require('./schema/bps_trigger_raw.model')(sequelize, Sequelize)
db.sequelize.sync()
+67
View File
@@ -0,0 +1,67 @@
module.exports = (sequelize, Sequelize) => {
const RecordingMeta = sequelize.define('bps_recording_meta', {
uuid: {
type: Sequelize.STRING,
defaultValue: '',
primaryKey: true
},
name: {
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
},
time_duration: {
type: Sequelize.STRING,
defaultValue: '0'
},
start_time: {
type: Sequelize.STRING,
defaultValue: '-1'
},
end_time: {
type: Sequelize.STRING,
defaultValue: '-1'
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
tag: {
type: Sequelize.STRING,
defaultValue: '-1'
},
parameter_set: {
type: Sequelize.JSONB,
defaultValue: {}
},
create_date: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
},
{
timestamps: false
}
)
return RecordingMeta
}
+30
View File
@@ -0,0 +1,30 @@
module.exports = (sequelize, Sequelize) => {
const TriigerDataRaw = sequelize.define('bps_trigger_raw', {
channel: {
type: Sequelize.INTEGER,
defaultValue: -1
},
parent_uuid: {
type: Sequelize.STRING,
defaultValue: ''
},
data: {
type: Sequelize.TEXT,
defaultValue: ''
},
start_time: {
type: Sequelize.STRING,
defaultValue: '-1'
},
end_time: {
type: Sequelize.STRING,
defaultValue: '-1'
},
},
{
freezeTableName: true
}
)
return TriigerDataRaw
}
-47
View File
@@ -1,47 +0,0 @@
module.exports = (sequelize, Sequelize) => {
const Configuration = sequelize.define('configuration', {
name: {
type: Sequelize.STRING
},
library: {
type: Sequelize.STRING
},
layout: {
type: Sequelize.JSONB
},
chart: {
type: Sequelize.JSONB
},
parameter: {
type: Sequelize.JSONB
},
user_auth: {
type: Sequelize.JSONB,
defaultValue: {
owner: [],
maintainer: [],
guest: []
}
},
locked: {
type: Sequelize.BOOLEAN
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
},
{
timestamps: false
})
return Configuration
}
@@ -1,48 +0,0 @@
module.exports = (sequelize, Sequelize) => {
const Chart = sequelize.define('chart', {
name: {
type: Sequelize.STRING
},
description: {
type: Sequelize.STRING
},
library: {
type: Sequelize.STRING
},
num: {
type: Sequelize.INTEGER
},
data: {
type: Sequelize.JSONB
},
user_auth: {
type: Sequelize.JSONB,
defaultValue: {
owner: [],
maintainer: [],
guest: []
}
},
locked: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
},
{
timestamps: false
})
return Chart
}
+4
View File
@@ -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
-51
View File
@@ -1,51 +0,0 @@
module.exports = (sequelize, Sequelize) => {
const Project = sequelize.define('project', {
name: {
type: Sequelize.STRING
},
desc: {
type: Sequelize.STRING
},
task: {
type: Sequelize.JSONB,
defaultValue: {}
},
cycle: {
type: Sequelize.JSONB,
defaultValue: []
},
device: {
type: Sequelize.JSONB,
defaultValue: {}
},
uuid: {
type: Sequelize.STRING,
defaultValue: ''
},
user_auth: {
type: Sequelize.JSONB,
defaultValue: {
owner: [],
maintainer: [],
guest: []
}
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
},
{
timestamps: false
})
return Project
}
-35
View File
@@ -1,35 +0,0 @@
module.exports = (sequelize, Sequelize) => {
const ProjectMeta = sequelize.define('project_metas', {
project: {
type: Sequelize.STRING
},
cycle: {
type: Sequelize.JSONB,
defaultValue: []
},
task: {
type: Sequelize.JSONB,
defaultValue: {}
},
serial_number: {
type: Sequelize.INTEGER
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
},
{
timestamps: false
})
return ProjectMeta
}
-52
View File
@@ -1,52 +0,0 @@
module.exports = (sequelize, Sequelize) => {
const ProjectReport = sequelize.define('project_report', {
name: {
type: Sequelize.STRING,
default: ''
},
desc: {
type: Sequelize.STRING,
default: ''
},
task: {
type: Sequelize.JSONB,
defaultValue: {}
},
cycle: {
type: Sequelize.JSONB,
defaultValue: []
},
device: {
type: Sequelize.JSONB,
defaultValue: {}
},
uuid: {
type: Sequelize.STRING(36)
},
user_auth: {
type: Sequelize.JSONB,
defaultValue: {
owner: [],
maintainer: [],
guest: []
}
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
},
{
timestamps: false
})
return ProjectReport
}
+12 -3
View File
@@ -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'
@@ -53,9 +57,6 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.JSONB,
defaultValue: {}
},
project: {
type: Sequelize.INTEGER
},
parameter_set: {
type: Sequelize.JSONB,
defaultValue: {}
@@ -76,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
@@ -43,6 +43,10 @@ module.exports = (sequelize, Sequelize, i) => {
type: Sequelize.TEXT,
defaultValue: ''
},
sd_data: {
type: Sequelize.TEXT,
defaultValue: ''
},
compressed: {
type: Sequelize.BOOLEAN,
defaultValue: false
-79
View File
@@ -1,79 +0,0 @@
const db = require('../../db/database')
const Op = db.Sequelize.Op
class ConfigurationModel {
async create (req) {
return db.charts.create(
req
)
}
async update (req, id) {
if (id != null) {
const ret = await db.charts.update(
req,
{
where: {
id: id
}
}
)
return ret
} else {
const ret = await db.charts.update(
req,
{
where: {}
}
)
return ret
}
}
async clearDeleted () {
const ret = await db.charts.destroy(
{
where: {
deleted: true
}
}
)
return ret
}
async get (type, query) {
let where = {}
if (type === 'chart') {
where = {
chart: {
[Op.ne]: null
}
}
}
Object.assign(query, where)
const ret = await db.charts.findAll(
{
where: where
}
)
return ret
}
async getByQueryWithAttrs (query, limit, offset, order, attrs, group) {
const attrList = attrs ? attrs.split('-') : undefined
const ret = await db.charts.findAll(
{
// where: db.Sequelize.where(db.Sequelize.fn('DATE', db.Sequelize.col('created_at')), '2022-12-02'),
where: query,
attributes: attrList,
order: order,
limit: limit,
offset: offset
}
)
return ret
}
}
export default ConfigurationModel
+28
View File
@@ -0,0 +1,28 @@
const db = require('../../db/database')
const Op = db.Sequelize.Op
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: [
['start_time', 'DESC']
]
})
return ret
}
}
export default RecordingMeta
+37
View File
@@ -0,0 +1,37 @@
const db = require('../../db/database')
const { Transform } = require("stream")
class TriggerRaw {
async getDataByUUID (parent_uuid) {
const ret = await db.trigger_raw.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
transformData += transformDataArr.slice(startPos, startPos + step).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 TriggerRaw
-38
View File
@@ -19,44 +19,6 @@ class CollectionModel {
return ret
}
async getByQueryWithAttrs (query, attrs) {
const attrList = attrs ? attrs.split('-') : undefined
const ret = await db.collections.findAll(
{
where: query,
attributes: attrList
}
)
return ret
}
async getByParentWithOffsetLimitOrder (type, parent, limit, offset, order, attrs) {
const attrList = attrs ? attrs.split('-') : undefined
const orderList = order ? order.split('-') : ['id', 'desc']
const collectionType = type + '::jsonb'
const parentOp = {}
console.log('getByParentWithOffsetLimitOrder', type, parent, limit, offset, order, attrs)
parentOp[collectionType] = {
[Op.contains]: '[' + parent + ']'
}
const ret = await db.collections.findAndCountAll(
{
where: {
parent: parentOp
},
attributes: attrList,
order: [
orderList
],
limit: limit,
offset: offset
}
)
return ret
}
async clearDeleted (controllerID) {
let ret
if (controllerID == null) {
-278
View File
@@ -98,27 +98,6 @@ class RecordingDataMeta {
return ret
}
async getByAttrParent (type, parent, attr) {
const attrList = attr.split('-')
const collectionType = type + '::jsonb'
const parentOp = {}
parentOp[collectionType] = {
[Op.contains]: '[' + parent + ']'
}
const ret = await db.recording_data_metas.findAll(
{
where: {
parent: parentOp
},
attributes: attrList,
order: [
['id', 'DESC']
]
}
)
return ret
}
async getCountByParent (type, parent) {
const collectionType = type + '::jsonb'
const parentOp = {}
@@ -246,263 +225,6 @@ class RecordingDataMeta {
})
return ret
}
async getByQueryWithAttrs (query, limit, offset, order, attrs, group) {
console.log('getByQueryWithAttrs', query, limit, offset, order, attrs, group)
const result = {}
let attrList = attrs ? attrs.split('-') : undefined
// group by time
if (group === 'time') {
const timeGroupNum = await db.recording_data_metas.findAll(
{
attributes: [[db.Sequelize.fn('COUNT', db.Sequelize.fn('DISTINCT', db.Sequelize.fn('DATE', db.Sequelize.col('created_at')))), 'GroupCount']]
}
)
result.counts = timeGroupNum
attrList = [[db.Sequelize.fn('DATE', db.Sequelize.col('created_at')), 'date'], [db.sequelize.fn('COUNT', 'date'), 'count']]
group = [db.Sequelize.fn('DATE', db.Sequelize.col('created_at')), 'date']
order = [[db.Sequelize.fn('DATE', db.Sequelize.col('created_at')), 'desc']]
}
// group by project
if (group === 'project') {
attrList = [['project', 'project']]
group = ['project', 'project']
order = [['project', 'desc']]
}
// query by time
if (query.time) {
const start = new Date(query.time)
const end = new Date(query.time)
end.setDate(end.getDate() + 1)
delete query.time
query.created_at = {
[Op.gte]: start,
[Op.lte]: end
}
}
const ret = await db.recording_data_metas.findAll(
{
// where: db.Sequelize.where(db.Sequelize.fn('DATE', db.Sequelize.col('created_at')), '2022-12-02'),
where: query,
attributes: attrList,
group: group,
order: order,
limit: limit,
offset: offset
}
)
result.rows = ret
return result
}
async getByFolderWithParentLimitOffsetOrderAttrs (type, parent, limit, offset, order, attrs) {
const attrList = attrs ? attrs.split('-') : undefined
const orderList = order ? order.split('-') : ['id', 'desc']
const collectionType = type + '::jsonb'
const parentOp = {}
console.log('getByFolderWithParentLimitOffsetOrderAttr', type, parent, limit, offset, order, attrs)
parentOp[collectionType] = {
[Op.contains]: '[' + parent + ']'
}
const ret = await db.recording_data_metas.findAndCountAll(
{
where: {
parent: parentOp
},
attributes: attrList,
order: [
[orderList[0], orderList[1]]
],
limit: limit,
offset: offset
}
)
return ret
}
async getByProject (uuid) {
const [results, _] = await db.sequelize.query(`
WITH ProjectData AS (SELECT * FROM project_reports WHERE uuid='${uuid}')
SELECT rdm.* FROM ProjectData pr
LEFT JOIN project_metas pm ON pr.uuid = pm.project
LEFT JOIN recording_data_metas rdm ON pm.id = rdm.project
ORDER BY rdm.id desc
`)
return results
}
async findWithIdRange1 (metaIdArray, range) {
/* get x channel & range, y channel & range */
const channelX = range[0][0]
const rangeX = range[0].slice(1, 3).sort(function (a, b) {
return a - b
})
const channelY = range[1][0]
const rangeY = range[1].slice(1, 3).sort(function (a, b) {
return a - b
})
// console.log(channelX, rangeX, channelY, rangeY)
const pairID = []
/* loop with given idArray */
for (const _id of metaIdArray) {
const meta = await db.recording_data_metas.findOne({
where: {
id: _id
},
attributes: ['id', 'raw_data', 'name']
})
/* if channel has time */
if (channelX === 'Time' || channelY === 'Time') {
if (channelX === 'Time') {
/* if x is time, then get the y channel data */
for (const index in meta.raw_data[channelY]) {
/* if meta id is paired already then break */
if (pairID.findIndex((ele) => ele[0] === meta.id) !== -1) break
const rawID = meta.raw_data[channelY][index]
const rawData = await db[channelY + '_recording_data_raws'].findOne({
where: {
id: rawID
}
})
/* get time & data */
const data = rawData.data.replace(/"\*\*\*"/g, ' ').split(' ')
const time = data.filter((ele, index) => index % 2 === 0)
const value = data.filter((ele, index) => index % 2 === 1)
/* check with value & time range */
for (let index = 0; index < value.length; index++) {
if (value[index] <= rangeY[1] && value[index] >= rangeY[0]) {
if (time[index] <= rangeX[1] && time[index] >= rangeX[0]) {
pairID.push([meta.id, meta.name])
break
}
}
}
}
}
if (channelY === 'Time') {
for (const index in meta.raw_data[channelX]) {
if (pairID.findIndex((ele) => ele[0] === meta.id) !== -1) break
const rawID = meta.raw_data[channelX][index]
const rawData = await db[channelX + '_recording_data_raws'].findOne({
where: {
id: rawID
}
})
/* get time & data */
const data = rawData.data.replace(/"\*\*\*"/g, ' ').split(' ')
const time = data.filter((ele, index) => index % 2 === 0)
const value = data.filter((ele, index) => index % 2 === 1)
/* check with value & time range */
for (let index = 0; index < value.length; index++) {
if (value[index] <= rangeX[1] && value[index] >= rangeX[0]) {
if (time[index] <= rangeY[1] && time[index] >= rangeY[0]) {
pairID.push([meta.id, meta.name])
break
}
}
}
}
}
} else {
/* when two channels are not time */
/* loop with raw data id */
for (const index in meta.raw_data[channelX]) {
/* if meta id is paired already then break */
if (pairID.findIndex((ele) => ele[0] === meta.id) !== -1) break
/* get X channel data */
const rawIDX = meta.raw_data[channelX][index]
const rawDataX = await db[channelX + '_recording_data_raws'].findOne({
where: {
id: rawIDX
}
})
const valueX = rawDataX.data.replace(/"\*\*\*"/g, ' ').split(' ').filter((ele, index) => index % 2 === 1)
/* get Y channel data */
const rawIDY = meta.raw_data[channelY][index]
const rawDataY = await db[channelY + '_recording_data_raws'].findOne({
where: {
id: rawIDY
}
})
const valueY = rawDataY.data.replace(/"\*\*\*"/g, ' ').split(' ').filter((ele, index) => index % 2 === 1)
/* if x value in range then check y value in range */
for (let index = 0; index < valueX.length; index++) {
if (valueX[index] <= rangeX[1] && valueX[index] >= rangeX[0]) {
if (valueY[index] <= rangeY[1] && valueY[index] >= rangeY[0]) {
pairID.push([meta.id, meta.name])
break
}
}
}
}
}
console.log('pair', pairID)
}
return pairID
}
// async findWithIdRange (id, range) {
// const channel = String(range[0][0])
// const dataRange = range[0].slice(1, 3)
// const matchFile = []
// for (const _id of id) {
// console.log('id', _id)
// const meta = await db.recording_data_metas.findOne({
// where: {
// id: _id
// },
// attributes: ['id', 'raw_data', 'name']
// })
// if (await matchRange(channel, meta.raw_data[channel], dataRange) === true) {
// matchFile.push(meta.id)
// }
// }
// console.log('matchFile', matchFile)
// const channel1 = range[1][0]
// const range1 = range[1].slice(1, 3)
// const doubleMatchFile = []
// for (const _id of matchFile) {
// const meta = await db.recording_data_metas.findOne({
// where: {
// id: _id
// },
// attributes: ['id', 'raw_data', 'name']
// })
// console.log('meta', meta.id)
// if (await matchRange(channel1, meta.raw_data[channel1], range1) === true) {
// doubleMatchFile.push([meta.id, meta.name])
// }
// }
// console.log('doubleMatchFile', doubleMatchFile)
// return doubleMatchFile
// }
// }
// async function matchRange (channel, rawIdList, range) {
// console.log('matchRange', channel, rawIdList, range)
// for (const rawId of rawIdList) {
// const raw = await db[channel + '_recording_data_raws'].findOne({
// where: {
// id: rawId
// }
// })
// const value = raw.data.split('"***"')[0].split(' ').filter((ele, index) => index % 2 === 1)
// for (const val of value) {
// console.log('val', val)
// if (val < range[1] && val > range[0]) {
// return true
// }
// }
// }
// return false
}
export default RecordingDataMeta
+2 -13
View File
@@ -31,11 +31,11 @@ class RecordingDataMini {
return ret
}
async clearDeleted (index, where = { deleted: true }) {
async clearDeleted (index) {
const ret = await db[index + '_recording_data_minis'].destroy(
{
where: {
...where
deleted: true
}
}
)
@@ -69,17 +69,6 @@ class RecordingDataMini {
return ret
}
async getExistOrNotByID (id, index) {
const ret = await db[index + '_recording_data_minis'].findOne(
{
where: {
id: id
}
}
).then(token => !(token.data_mean === ''))
return ret
}
async getByIDs (id, index) {
const _id = JSON.parse('[' + id + ']')
const ret = await db[index + '_recording_data_minis'].findAllWithStream(
+18 -2
View File
@@ -37,11 +37,11 @@ class RecordingDataRaw {
return ret
}
async clearDeleted (index, where = { deleted: true }) {
async clearDeleted (index) {
const ret = await db[index + '_recording_data_raws'].destroy(
{
where: {
...where
deleted: true
}
}
)
@@ -103,6 +103,22 @@ class RecordingDataRaw {
return ret
}
async getSdDataByID (id, index) {
const ret = await db[index + '_recording_data_raws'].findAllWithStream(
{
batchSize: 1000,
where: {
id: id
},
attributes: [
'sd_data'
]
}
)
return ret
}
async getByAttrID (id, attr, index) {
const attrList = attr.split('-')
const ret = await db[index + '_recording_data_raws'].findAll(
+11 -13
View File
@@ -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('-')
-13
View File
@@ -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(
-97
View File
@@ -1,97 +0,0 @@
const db = require('../../db/database')
// const Op = db.Sequelize.Op
class ProjectModal {
async create (req) {
return db.projects.create(req)
}
async update (req, id) {
if (id != null) {
const ret = await db.projects.update(
req,
{
where: {
id: id
}
}
)
return ret
} else {
const ret = await db.projects.update(
req,
{
where: {}
}
)
return ret
}
}
async updateByAttr (req, attr, value) {
const whereObj = {}
const attrList = attr.split('-')
const valueList = value.split('-')
attrList.forEach((key, idx) => {
whereObj[key] = valueList[idx]
})
const ret = await db.projects.update(
req,
{
where: whereObj
}
)
return ret
}
async clearDeleted () {
const ret = await db.projects.destroy(
{
where: {
deleted: true
}
}
)
return ret
}
async getByID (id) {
const ret = await db.projects.findAll(
{
where: {
id: id
}
}
)
return ret
}
async getByAttr (attr, value) {
const attrList = attr.split('-')
const valueList = value.split('-')
const whereObj = {}
attrList.forEach((key, idx) => {
whereObj[key] = valueList[idx]
})
const ret = await db.projects.findAll(
{
where: whereObj
}
)
return ret
}
async getAll () {
const ret = await db.projects.findAll({
order: [
['created_at', 'ASC']
]
})
return ret
}
}
export default ProjectModal
-46
View File
@@ -1,46 +0,0 @@
const db = require('../../db/database')
class ProjectMeta {
async create (req) {
return db.project_metas.create(req)
}
async update (req, id) {
if (id != null) {
const ret = await db.project_metas.update(
req,
{
where: {
id: id
}
}
)
return ret
} else {
const ret = await db.project_metas.update(
req,
{
where: {}
}
)
return ret
}
}
async getByQueryWithAttrs (query, attrs, order) {
const attrList = attrs ? attrs.split('-') : undefined
const orderList = order ? order.split('-') : ['id', 'desc']
console.log('getByQueryWithAttrs', query, attrs, order)
const ret = await db.project_metas.findAndCountAll(
{
where: query,
attributes: attrList,
// group: group,
order: [orderList]
}
)
return ret
}
}
export default ProjectMeta
-46
View File
@@ -1,46 +0,0 @@
const db = require('../../db/database')
class ProjectReport {
async create (req) {
return db.project_reports.create(req)
}
async update (req, id) {
if (id != null) {
const ret = await db.project_reports.update(
req,
{
where: {
id: id
}
}
)
return ret
} else {
const ret = await db.project_reports.update(
req,
{
where: {}
}
)
return ret
}
}
async getByQueryWithAttrs (query, attrs, order) {
const attrList = attrs ? attrs.split('-') : undefined
const orderList = order ? order.split('-') : ['id', 'desc']
console.log('getByQueryWithAttrs', query, attrs, order)
const ret = await db.project_reports.findAndCountAll(
{
where: query,
attributes: attrList,
// group: group,
order: [orderList]
}
)
return ret
}
}
export default ProjectReport
+11
View File
@@ -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]
]
}
+17
View File
@@ -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]
]
}
+17
View File
@@ -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]
]
}
+20
View File
@@ -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]
]
}
+18
View File
@@ -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)
]
}
+22
View File
@@ -0,0 +1,22 @@
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]
]
}
+18
View File
@@ -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]
]
}
+21
View File
@@ -0,0 +1,21 @@
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_id/:channel/:id', controllers.recordingDataRaw.getSdDataByID],
['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]
]
}
+13
View File
@@ -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]
]
}
+12
View File
@@ -0,0 +1,12 @@
import controllers from '../../../controllers'
// '/api/file/trigger'
export default function (_prefix) {
const prefix = _prefix + '/trigger'
return [
['GET', prefix + '/get_meta_by_uuid/:uuid', controllers.trigger.getMetaByUUID],
['GET', prefix + '/get/all', controllers.trigger.getMetaAll],
['GET', prefix + '/get_raw_by_uuid/:parent_uuid', controllers.trigger.getTriggerRawByUUID],
]
}
+17
View File
@@ -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)
]
}
+8
View File
@@ -0,0 +1,8 @@
import task from './task'
export default function (_prefix) {
const prefix = _prefix + '/project'
return [
...task(prefix)
]
}
+15
View File
@@ -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 -136
View File
@@ -1,145 +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)
.get('/api/file/collection/get', controllers.collection.get)
// 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_attr_by_parent/:type/:parent/:attr', controllers.recordingDataMeta.getAttrByParent)
.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)
.get('/api/file/meta/find', controllers.recordingDataMeta.findWithIdRange)
.get('/api/file/meta/get', controllers.recordingDataMeta.get)
// 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_exist_or_not_by_id/:channel/:id', controllers.recordingDataMini.getExistOrNotByID)
.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/:id', controllers.device.update)
.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)
.get('/api/analysis/get/csv', controllers.analysis.getCSV)
// project
.post('/api/project/create', controllers.project.create)
.post('/api/project/update/:id', controllers.project.update)
.post('/api/project/update_by_attr/:attr/:value', controllers.project.updateByAttr)
.post('/api/project/update/all', controllers.project.update)
.get('/api/project/clear_deleted/:controller_id', controllers.project.clearDeleted)
.get('/api/project/get_by_id/:id', controllers.project.getByID)
.get('/api/project/get_by_attr/:attr/:value', controllers.project.getByAttr)
.get('/api/project/get/all', controllers.project.getAll)
// projectReport
.post('/api/project/report/create', controllers.projectReport.create)
.post('/api/project/report/update/:id', controllers.projectReport.update)
.get('/api/project/report/get', controllers.projectReport.get)
// projectMeta
.post('/api/project/meta/create', controllers.projectMeta.create)
.post('/api/project/meta/update/:id', controllers.projectMeta.update)
.get('/api/project/meta/get', controllers.projectMeta.get)
// configuration
.post('/api/configuration/create', controllers.chart.create)
.post('/api/configuration/update/:id', controllers.chart.update)
.get('/api/configuration/get', controllers.chart.get)
.get('/api/configuration/clear_deleted/', controllers.chart.clearDeleted)
export default router