Compare commits

...

93 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
Jordan Hsu 363d8aac11 [fix] delete bug 2021-10-18 17:47:56 +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 a7bea5288c [update] recover route device/update/:id 2021-09-23 18:31:08 +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
peterlu14 46b6918031 [update] babel src build copy python file to dist & port fix 2021-09-01 17:52:24 +08:00
peterlu14 df09a4c92b [update] add update sd card api 2021-08-30 18:47:53 +08:00
peterlu14 f4ac57c8f8 Merge branch 'release/0826_merge_spike' 2021-08-30 14:37:19 +08:00
peterlu14 64c6b20a8f [update] fix delete file error 2021-08-30 14:36:44 +08:00
peterlu14 8a65f20142 Merge remote-tracking branch 'origin/feature/spike_detect' 2021-08-27 17:46:59 +08:00
peterlu14 632d65c057 [update] new route update_by_id & update_by_mac and device calibration column type varchar(255) to TEXT and update_at update 2021-08-27 17:45:52 +08:00
TommyXin e013b9dd63 get collectiong if controller ID is null (for old version) 2021-08-24 00:29:31 +08:00
peterlu14 5605bcbe68 [update] remove wrong index 2021-08-20 19:59:32 +08:00
TommyXin 6a85c88fb7 controller id 2021-08-20 18:22:41 +08:00
TommyXin bc687cc2de collection add controller id 2021-08-20 18:15:19 +08:00
peterlu14 6bb37fd48d [update] fix sub_signal 2021-08-20 18:09:34 +08:00
TommyXin 4cbc3873f7 change controller api update path 2021-08-20 17:50:32 +08:00
peterlu14 64a6698611 [update] execute python file path 2021-08-20 16:55:03 +08:00
peterlu14 70a4f448e9 [update] change output data delimiter 2021-08-20 16:17:21 +08:00
peterlu14 ddd4524407 [update] fix start_index < 0 2021-08-20 16:06:42 +08:00
peterlu14 92a2fc8a26 [update] add spikeDetect all & partial 2021-08-20 13:27:37 +08:00
peterlu14 af999c8b33 [update] spikeDetect 2021-08-20 11:38:25 +08:00
TommyXin 5a1577db80 update mini batch 2021-08-09 23:32:05 +08:00
TommyXin f62c99c73a batch update raw&mini 2021-08-09 07:39:17 +08:00
TommyXin ac8c52b75b delete meta include subfile 2021-08-09 01:45:51 +08:00
TommyXin e240ff24b2 get meta by customer order 2021-08-07 20:29:12 +08:00
TommyXin 9fa0fd5322 meta get by attr 2021-08-07 19:51:33 +08:00
TommyXin 567855b7e5 [collection] update 2021-08-07 17:44:01 +08:00
TommyXin 8613369885 [meta] add get meta by attr&limit 2021-08-06 20:22:41 +08:00
peterlu14 88e5f0c155 [update] add route get meta all 2021-07-13 18:05:25 +08:00
TommyXin d7a3a06039 Merge branch 'task_config' 2021-07-01 21:49:31 +08:00
47 changed files with 1383 additions and 204 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",
+1
View File
@@ -14,6 +14,7 @@
"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: 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>'
}
+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='')
+116
View File
@@ -0,0 +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 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 dataType = request.data_type
const result = await recordingDataMeta.getByID(metaId)
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
const rawData = JSON.stringify(result[0].raw_data[channel])
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
])
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(`spike detect analysis process 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()
}
+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
}
})
})
}
+6 -3
View File
@@ -20,7 +20,8 @@ export const update = async (ctx, next) => {
}
export const clearDeleted = async (ctx, next) => {
const result = await collection.clearDeleted()
const controllerID = ctx.params.controller_id
const result = await collection.clearDeleted(controllerID)
ctx.body = result
next()
@@ -36,7 +37,8 @@ export const getByID = async (ctx, next) => {
export const getByName = async (ctx, next) => {
const name = ctx.params.name
const result = await collection.getByName(name)
const controllerID = ctx.params.controller_id
const result = await collection.getByName(name, controllerID)
ctx.body = result
next()
@@ -62,7 +64,8 @@ export const getByParentName = async (ctx, next) => {
}
export const getAll = async (ctx, next) => {
const result = await collection.getAll()
const controllerID = ctx.params.controller_id
const result = await collection.getAll(controllerID)
ctx.body = result
next()
@@ -6,6 +6,7 @@ const recordingDataMeta = new RecordingDataMeta()
export const create = async (ctx, next) => {
const data = ctx.request.body
console.log(auth.CheckAuth(ctx))
// console.log(data)
// console.log(ctx.request.header.authorization)
const result = await recordingDataMeta.create(data)
// console.log(result)
@@ -47,6 +48,40 @@ export const getByParent = async (ctx, next) => {
next()
}
export const getCountByParent = async (ctx, next) => {
const type = ctx.params.type
const parent = ctx.params.parent
const result = await recordingDataMeta.getCountByParent(type, parent)
ctx.body = result
next()
}
export const getByParentWithLimit = async (ctx, next) => {
const type = ctx.params.type
const parent = ctx.params.parent
const limit = ctx.params.limit
const offset = ctx.params.offset
const order = ctx.params.order
const result = await recordingDataMeta.getByParentWithLimit(type, parent, limit, offset, order)
ctx.body = result
next()
}
export const getByAttrsParentWithLimit = async (ctx, next) => {
const type = ctx.params.type
const parent = ctx.params.parent
const limit = ctx.params.limit
const offset = ctx.params.offset
const order = ctx.params.order
const attr = ctx.params.attr
const result = await recordingDataMeta.getByAttrsParentWithLimit(type, parent, limit, offset, order, attr)
ctx.body = result
next()
}
export const getByUUID = async (ctx, next) => {
const uuid = ctx.params.uuid
const result = await recordingDataMeta.getByUUID(uuid)
@@ -25,6 +25,16 @@ export const update = async (ctx, next) => {
next()
}
export const updateByIDs = async (ctx, next) => {
const index = ctx.params.channel
const data = ctx.request.body
const id = ctx.params.id
const result = await recordingDataMini.updateByIDs(data, id, index)
ctx.body = result
next()
}
// export const get = async (ctx, next) => {
// const index = ctx.params.channel
// const id = ctx.params.id
@@ -51,6 +61,15 @@ export const getByID = async (ctx, next) => {
next()
}
export const getByIDs = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
const result = await recordingDataMini.getByIDs(id, index)
ctx.body = result
next()
}
export const getMeanDataByID = async (ctx, next) => {
const index = ctx.params.channel
const id = ctx.params.id
@@ -25,6 +25,26 @@ export const update = async (ctx, next) => {
next()
}
export const updateSdData = async (ctx, next) => {
const index = ctx.params.channel
const data = ctx.request.body
const id = ctx.params.id
const result = await recordingDataRaw.updateSdData(data, id, index)
ctx.body = result
next()
}
export const updateByIDs = async (ctx, next) => {
const index = ctx.params.channel
const data = ctx.request.body
const id = ctx.params.id
const result = await recordingDataRaw.updateByIDs(data, id, index)
ctx.body = result
next()
}
export const clearDeleted = async (ctx, next) => {
const index = ctx.params.channel
const result = await recordingDataRaw.clearDeleted(index)
@@ -60,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()
// }
+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()
}
+7 -1
View File
@@ -8,6 +8,9 @@ import * as task from './controller/task'
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,
@@ -19,5 +22,8 @@ export default {
task,
recordingDataMeta,
recordingDataRaw,
recordingDataMini
recordingDataMini,
analysis,
sdCard,
trigger,
}
+17 -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 controller.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 controller.updateByID(data, id)
const result = await controller.update(data, id)
ctx.body = result
next()
@@ -44,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)
@@ -52,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
+5 -4
View File
@@ -12,16 +12,17 @@ export const create = async (ctx, next) => {
export const update = async (ctx, next) => {
const data = ctx.request.body
const result = await device.update(data)
const id = ctx.params.id
const result = await device.update(data, id)
ctx.body = result
next()
}
export const updateByID = async (ctx, next) => {
export const updateByMac = async (ctx, next) => {
const data = ctx.request.body
const id = ctx.params.id
const result = await device.updateByID(data, id)
const mac = ctx.params.mac
const result = await device.updateByMac(data, mac)
ctx.body = result
next()
+4 -2
View File
@@ -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,8 @@ 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.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
}
+4
View File
@@ -7,6 +7,10 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.JSONB,
defaultValue: {}
},
controller_id: {
type: Sequelize.INTEGER,
defaultValue: -1
},
size: {
type: Sequelize.INTEGER,
defaultValue: -1
+14 -9
View File
@@ -40,6 +40,10 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.STRING,
defaultValue: ''
},
root: {
type: Sequelize.INTEGER,
defaultValue: -1
},
// group/user: {
// admin: [id...],
// normal: [id...],
@@ -63,18 +67,15 @@ module.exports = (sequelize, Sequelize) => {
},
device: {
type: Sequelize.JSONB,
defaultValue: {
auto_join: [],
scanned: []
}
defaultValue: {}
},
device_scanned: {
type: Sequelize.JSONB,
defaultValue: {}
type: Sequelize.ARRAY(Sequelize.STRING),
defaultValue: []
},
device_auto_join: {
type: Sequelize.JSONB,
defaultValue: {}
device_connected: {
type: Sequelize.ARRAY(Sequelize.STRING),
defaultValue: []
},
// project/task: {
// running: [id...],
@@ -103,6 +104,10 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.STRING,
defaultValue: ''
},
sd_uploading: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
deleted: {
type: Sequelize.BOOLEAN,
defaultValue: false
+7 -3
View File
@@ -55,11 +55,15 @@ module.exports = (sequelize, Sequelize) => {
defaultValue: -1
},
parameter_set: {
type: Sequelize.INTEGER,
defaultValue: -1
type: Sequelize.JSONB,
defaultValue: {}
},
running: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
calibration: {
type: Sequelize.STRING,
type: Sequelize.TEXT,
defaultValue: ''
},
user_auth: {
@@ -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
@@ -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
+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
+52 -21
View File
@@ -4,11 +4,7 @@ const Op = db.Sequelize.Op
class CollectionModel {
async create (req) {
return db.collections.create({
name: req.name,
parent: req.parent,
size: req.size
})
return db.collections.create(req)
}
async update (req, id) {
@@ -23,14 +19,26 @@ class CollectionModel {
return ret
}
async clearDeleted () {
const ret = await db.collections.delete(
{
where: {
deleted: true
async clearDeleted (controllerID) {
let ret
if (controllerID == null) {
ret = await db.collections.destroy(
{
where: {
deleted: true
}
}
}
)
)
} else {
ret = await db.collections.destroy(
{
where: {
controller_id: controllerID,
deleted: true
}
}
)
}
return ret
}
@@ -45,14 +53,26 @@ class CollectionModel {
return ret
}
async getByName (name) {
const ret = await db.collections.findAll(
{
where: {
name: name
async getByName (name, controllerID) {
let ret
if (controllerID == null) {
ret = await db.collections.findAll(
{
where: {
name: name
}
}
}
)
)
} else {
ret = await db.collections.findAll(
{
where: {
controller_id: controllerID,
name: name
}
}
)
}
return ret
}
@@ -100,8 +120,19 @@ class CollectionModel {
return ret
}
async getAll () {
const ret = await db.collections.findAll()
async getAll (controllerID) {
let ret
if (controllerID == null) {
ret = await db.collections.findAll()
} else {
ret = await db.collections.findAll(
{
where: {
controller_id: controllerID
}
}
)
}
return ret
}
}
+95 -1
View File
@@ -1,4 +1,10 @@
import RecordingDataRaw from './recording_data_raw'
import RecordingDataMini from './recording_data_mini'
const db = require('../../db/database')
// const RecordingDataMini = require('./recording_data_mini')
const recordingDataRaw = new RecordingDataRaw()
const recordingDataMini = new RecordingDataMini()
const Op = db.Sequelize.Op
@@ -36,7 +42,34 @@ class RecordingDataMeta {
}
async clearDeleted () {
const ret = await db.recording_data_metas.destroy(
let ret = await db.recording_data_metas.findAll(
{
attributes: [
'id',
'raw_data',
'mini_data'
],
where: {
deleted: true
}
}
)
for (let i = 0; i < ret.length; i++) {
const meta = ret[i]
for (const channel in meta.raw_data) {
if (meta.raw_data[channel] != null) {
await recordingDataRaw.updateByIDs({ deleted: true }, meta.raw_data[channel], channel)
recordingDataRaw.clearDeleted(channel)
}
if (meta.mini_data[channel] != null) {
for (const miniID in meta.mini_data[channel]) {
await recordingDataMini.updateByIDs({ deleted: true }, meta.mini_data[channel][miniID], channel)
}
recordingDataMini.clearDeleted(channel)
}
}
}
ret = await db.recording_data_metas.destroy(
{
where: {
deleted: true
@@ -65,6 +98,67 @@ class RecordingDataMeta {
return ret
}
async getCountByParent (type, parent) {
const collectionType = type + '::jsonb'
const parentOp = {}
parentOp[collectionType] = {
[Op.contains]: '[' + parent + ']'
}
const ret = await db.recording_data_metas.count(
{
where: {
parent: parentOp
}
}
)
return ret
}
async getByParentWithLimit (type, parent, limit, offset, order) {
const collectionType = type + '::jsonb'
const parentOp = {}
parentOp[collectionType] = {
[Op.contains]: '[' + parent + ']'
}
const ret = await db.recording_data_metas.findAndCountAll(
{
where: {
parent: parentOp
},
order: [
['id', order]
],
limit: limit,
offset: offset
}
)
return ret
}
async getByAttrsParentWithLimit (type, parent, limit, offset, order, attr) {
const attrList = attr.split('-')
const orderList = order.split('-')
const collectionType = type + '::jsonb'
const parentOp = {}
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 getByID (id) {
const ret = await db.recording_data_metas.findAll(
{
+25
View File
@@ -19,6 +19,18 @@ class RecordingDataMini {
return ret
}
async updateByIDs (req, id, index) {
const ret = await db[index + '_recording_data_minis'].update(
req,
{
where: {
id: id
}
}
)
return ret
}
async clearDeleted (index) {
const ret = await db[index + '_recording_data_minis'].destroy(
{
@@ -57,6 +69,19 @@ class RecordingDataMini {
return ret
}
async getByIDs (id, index) {
const _id = JSON.parse('[' + id + ']')
const ret = await db[index + '_recording_data_minis'].findAllWithStream(
{
batchSize: 1000,
where: {
id: _id
}
}
)
return ret
}
async getMeanDataByID (id, index) {
const ret = await db[index + '_recording_data_minis'].findAllWithStream(
{
+33
View File
@@ -20,6 +20,23 @@ class RecordingDataRaw {
return ret
}
async updateSdData (req, id, index) {
const ret = await db.sequelize.query(`UPDATE "public"."${index}_recording_data_raws" SET sd_data = sd_data || '${req.data}' WHERE id = ${String(id)}`)
return ret
}
async updateByIDs (req, id, index) {
const ret = await db[index + '_recording_data_raws'].update(
req,
{
where: {
id: id
}
}
)
return ret
}
async clearDeleted (index) {
const ret = await db[index + '_recording_data_raws'].destroy(
{
@@ -86,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(
+32 -20
View File
@@ -8,26 +8,27 @@ class ControllerModel {
return db.controllers.create(req)
}
async update (req) {
const ret = await db.controllers.update(
req,
{
where: {}
}
)
return ret
}
async updateByID (req, id) {
const ret = await db.controllers.update(
req,
{
where: {
id: id
async update (req, id) {
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
if (id != null) {
const ret = await db.controllers.update(
req,
{
where: {
id: id
}
}
}
)
return ret
)
return ret
} else {
const ret = await db.controllers.update(
req,
{
where: {}
}
)
return ret
}
}
async updateByAttr (req, attr, value) {
@@ -37,7 +38,7 @@ class ControllerModel {
attrList.forEach((key, idx) => {
whereObj[key] = valueList[idx]
})
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
const ret = await db.controllers.update(
req,
{
@@ -91,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('-')
+24 -10
View File
@@ -12,22 +12,36 @@ class DeviceModel {
})
}
async update (req) {
const ret = await db.devices.update(
req,
{
where: {}
}
)
return ret
async update (req, id) {
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
if (id != null) {
const ret = await db.devices.update(
req,
{
where: {
id: id
}
}
)
return ret
} else {
const ret = await db.devices.update(
req,
{
where: {}
}
)
return ret
}
}
async updateByID (req, id) {
async updateByMac (req, mac) {
req.updated_at = db.Sequelize.literal('CURRENT_TIMESTAMP')
const ret = await db.devices.update(
req,
{
where: {
id: id
mac_address: mac
}
}
)
+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 -78
View File
@@ -1,87 +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/collection/create', controllers.collection.create)
.get('/api/collection/get_by_id/:id', controllers.collection.getByID)
.get('/api/collection/get_by_name/:name', controllers.collection.getByName)
.get('/api/collection/get_by_parent/:type/:parent', controllers.collection.getByParent)
.get('/api/collection/get_by_parent_name/:type/:parent/:name', controllers.collection.getByParentName)
.get('/api/collection/get/all', 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
}
}
// meta
.post('/api/file/meta/create', controllers.recordingDataMeta.create)
.post('/api/file/meta/update/:id', controllers.recordingDataMeta.update)
.get('/api/file/meta/clear_deleted/:id', 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_or_create_by_path/:path', controllers.recordingDataMeta.getOrCreateByPath)
// raw
.post('/api/file/raw/create/:channel', controllers.recordingDataRaw.create)
.post('/api/file/raw/update/:channel/:id', controllers.recordingDataRaw.update)
.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', controllers.device.update)
.post('/api/device/update_by_id/:id', controllers.device.updateByID)
.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)
// controller
.post('/api/controller/create', controllers.controller.create)
.post('/api/controller/update', controllers.controller.update)
.post('/api/controller/update_by_id/:id', controllers.controller.updateByID)
.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)
// task
.post('/api/task/create', controllers.task.create)
.post('/api/task/update', controllers.task.update)
.post('/api/task/update_by_id/:id', controllers.task.updateByID)
.post('/api/task/update_by_attr/:attr/:value', controllers.task.updateByAttr)
.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)
export default router
+3
View File
@@ -0,0 +1,3 @@
# Elite: 53
# Neulive: 101 or 95
ssh -NL 54321:localhost:5432 pi@192.168.2.1