From adc56860333b0cd32e09f537a6224e82779467cf Mon Sep 17 00:00:00 2001 From: peterlu14 Date: Thu, 18 Nov 2021 15:44:45 +0800 Subject: [PATCH 1/4] [update] change new path --- src/controllers/file/sd_card/index.js | 120 +++++++++++++++----------- 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/src/controllers/file/sd_card/index.js b/src/controllers/file/sd_card/index.js index 35dd3cd..2467904 100644 --- a/src/controllers/file/sd_card/index.js +++ b/src/controllers/file/sd_card/index.js @@ -2,10 +2,60 @@ 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 getUuidList = (uuidPathString) => { + return uuidPathString.split('\n').map(val => val.split(' ')[0]) +} + +const getUuidPathArray = (uuidPathString) => { + return uuidPathString.split('\n').map(val => val.split(' ')) +} + +const getPathByUuid = (uuid, uuidPathArray) => { + for (const uuidPath of uuidPathArray) { + if (uuidPath[0] === uuid) { + return uuidPath[1] + } + } +} + +const getPath = async (uuid) => { + return getPathByUuid(uuid, getUuidPathArray(await getUuidPathStringPromise())) +} + +const getUuidPathStringPromise = async () => { + return new Promise((resolve, reject) => { + const subprocess = childProcess.spawn(path.join(...sdGetPath)) + + subprocess.stdout.on('data', async (data) => { + resolve(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}`) + }) + }) +} + +const getParameter = async (metaID, parameterName) => { + const ret = await recordingDataMeta.getByID(metaID) + return ret[0].parameter_set[parameterName] +} + export const exist = async (ctx, next) => { const request = ctx.request.body // const controllerID = request.controllerID @@ -46,33 +96,31 @@ export const exist = async (ctx, next) => { export const deleted = async (ctx, next) => { const request = ctx.request.body - // const controllerID = request.controllerID - const mac = request.mac const uuid = request.uuid + const uuidPath = await getPath(uuid) + + // timeout defualt 120s to no-limit + ctx.req.setTimeout(0) function deletePromise () { return new Promise((resolve, reject) => { - const subprocess = childProcess.spawn('python3', [ - path.join(__dirname, '/sd_card_manipulate.py'), - 'delete', - mac, - uuid - ]) + const subprocess = childProcess.spawn( + path.join(...sdDeletePath), + [uuidPath]) subprocess.stdout.on('data', async (data) => { const dataString = data.toString() - if (dataString === 'True') { - resolve(dataString) - } + console.log(dataString) }) subprocess.stderr.on('data', (error) => { - reject(error) console.error(`Error ${error}`) + reject(error) }) subprocess.on('close', (code) => { console.log(`grep process exited with code ${code}`) + resolve(code) }) }) } @@ -88,8 +136,9 @@ export const upload = async (ctx, next) => { const request = ctx.request.body const controllerID = request.controllerID const metaID = request.metaID - const mac = request.mac 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) @@ -97,17 +146,13 @@ export const upload = async (ctx, next) => { function uploadPromise () { return new Promise((resolve, reject) => { const subprocess = childProcess.spawn('python3', [ - path.join(__dirname, '/sd_card_manipulate.py'), - 'upload', - mac, - uuid + path.join(...sdUploadPath), + uuidPath, + uuid, + ampGain ]) subprocess.stdout.on('data', async (data) => { - const dataString = data.toString() - if (dataString === 'True') { - resolve(dataString) - } }) subprocess.stderr.on('data', (error) => { @@ -117,16 +162,19 @@ export const upload = async (ctx, next) => { subprocess.on('close', (code) => { console.log(`sd card upload process exited with code ${code}`) + resolve(code) }) }) } + // controller column sd_uploading update await controller.update({ sd_uploading: true }, controllerID) const result = await uploadPromise() + // controller column sd_uploading close await controller.update({ sd_uploading: false }, controllerID) @@ -136,37 +184,13 @@ export const upload = async (ctx, next) => { }, metaID) ctx.body = result - next() } export const get = async (ctx, next) => { - function getPromise () { - return new Promise((resolve, reject) => { - const subprocess = childProcess.spawn('python3', [ - path.join(__dirname, '/sd_card_manipulate.py'), - 'get_uuid_list' - ]) - - subprocess.stdout.on('data', async (data) => { - const dataString = data.toString() - resolve(dataString) - }) - - subprocess.stderr.on('data', (error) => { - reject(error) - console.error(`Error ${error}`) - }) - - subprocess.on('close', (code) => { - console.log(`sdcard get process exited with code ${code}`) - }) - }) - } - - const result = await getPromise() - - ctx.body = result + const result = await getUuidPathStringPromise() + const uuidList = getUuidList(result) + ctx.body = uuidList next() } From d27946ed885d916e5a2acb30d3d9b02db077e5ed Mon Sep 17 00:00:00 2001 From: peterlu14 Date: Fri, 19 Nov 2021 11:43:18 +0800 Subject: [PATCH 2/4] [update] IIRFilter path --- src/controllers/analysis/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/analysis/index.js b/src/controllers/analysis/index.js index 852b780..eb60ebf 100644 --- a/src/controllers/analysis/index.js +++ b/src/controllers/analysis/index.js @@ -81,7 +81,7 @@ export const IIRFliter = async (ctx, next) => { function getPromise () { return new Promise((resolve, reject) => { const subprocess = childProcess.spawn('python3', [ - path.join(homedir(), '/IIRFilter.py'), + path.join(homedir(), 'bioproanalysis', 'filter', 'IIRFilter.py'), type, order, fs, From b1c92721be5db4272243a10d0045942c20614230 Mon Sep 17 00:00:00 2001 From: peterlu14 Date: Fri, 19 Nov 2021 18:06:44 +0800 Subject: [PATCH 3/4] [update] sd card api rebuild --- src/controllers/file/sd_card/index.js | 214 ++-- .../file/sd_card/sd_card_manipulate.py | 1000 ----------------- src/routes/api/file/sdcard.js | 6 +- 3 files changed, 113 insertions(+), 1107 deletions(-) delete mode 100644 src/controllers/file/sd_card/sd_card_manipulate.py diff --git a/src/controllers/file/sd_card/index.js b/src/controllers/file/sd_card/index.js index 2467904..661845f 100644 --- a/src/controllers/file/sd_card/index.js +++ b/src/controllers/file/sd_card/index.js @@ -12,12 +12,13 @@ const sdGetPath = [...sdPath, 'neuLiveSD_C', 'sd_list'] const sdDeletePath = [...sdPath, 'neuLiveSD_C', 'sd_remove'] const sdUploadPath = [...sdPath, 'sd_download.py'] -const getUuidList = (uuidPathString) => { - return uuidPathString.split('\n').map(val => val.split(' ')[0]) +const getParameter = async (metaID, parameterName) => { + const ret = await recordingDataMeta.getByID(metaID) + return ret[0].parameter_set[parameterName] } -const getUuidPathArray = (uuidPathString) => { - return uuidPathString.split('\n').map(val => val.split(' ')) +const getPath = async (uuid) => { + return getPathByUuid(uuid, getUuidPathArray(await getUuidPathStringPromise())) } const getPathByUuid = (uuid, uuidPathArray) => { @@ -28,16 +29,24 @@ const getPathByUuid = (uuid, uuidPathArray) => { } } -const getPath = async (uuid) => { - return getPathByUuid(uuid, getUuidPathArray(await getUuidPathStringPromise())) +// [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) => { - resolve(data.toString()) + dataString += data.toString() }) subprocess.stderr.on('data', (error) => { @@ -47,92 +56,76 @@ const getUuidPathStringPromise = async () => { subprocess.on('close', (code) => { console.log(`sdcard get process exited with code ${code}`) + resolve(dataString) }) }) } -const getParameter = async (metaID, parameterName) => { - const ret = await recordingDataMeta.getByID(metaID) - return ret[0].parameter_set[parameterName] +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 mac = request.mac const uuid = request.uuid - - function existPromise () { - return new Promise((resolve, reject) => { - const subprocess = childProcess.spawn('python3', [ - path.join(__dirname, '/sd_card_manipulate.py'), - 'exist', - mac, - uuid - ]) - - subprocess.stdout.on('data', async (data) => { - const dataString = data.toString() - resolve(dataString) - }) - - subprocess.stderr.on('data', (error) => { - reject(error) - console.error(`Error ${error}`) - }) - - subprocess.on('close', (code) => { - console.log(`grep process exited with code ${code}`) - }) - }) - } - - const result = await existPromise() + const path = await getPath(uuid) + let result + (path !== undefined) ? result = true : result = false ctx.body = result next() } -export const deleted = async (ctx, next) => { - const request = ctx.request.body - const uuid = request.uuid - const uuidPath = await getPath(uuid) - - // timeout defualt 120s to no-limit - ctx.req.setTimeout(0) - - function deletePromise () { - return new Promise((resolve, reject) => { - const subprocess = childProcess.spawn( - path.join(...sdDeletePath), - [uuidPath]) - - subprocess.stdout.on('data', async (data) => { - const dataString = data.toString() - console.log(dataString) - }) - - subprocess.stderr.on('data', (error) => { - console.error(`Error ${error}`) - reject(error) - }) - - subprocess.on('close', (code) => { - console.log(`grep process exited with code ${code}`) - resolve(code) - }) - }) - } - - const result = await deletePromise() - - ctx.body = result - - next() -} - -export const upload = async (ctx, next) => { +export const uploadThenDelete = async (ctx, next) => { const request = ctx.request.body const controllerID = request.controllerID const metaID = request.metaID @@ -143,54 +136,67 @@ export const upload = async (ctx, next) => { // timeout defualt 120s to no-limit ctx.req.setTimeout(0) - function uploadPromise () { - return new Promise((resolve, reject) => { - const subprocess = childProcess.spawn('python3', [ - path.join(...sdUploadPath), - uuidPath, - uuid, - ampGain - ]) - - subprocess.stdout.on('data', async (data) => { - }) - - 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(code) - }) - }) - } - // controller column sd_uploading update await controller.update({ sd_uploading: true }, controllerID) - const result = await uploadPromise() + const uploadResult = await uploadPromise(uuidPath, uuid, ampGain) + + if (uploadResult === 'false') { + // controller column sd_uploading close + await controller.update({ + sd_uploading: false + }, controllerID) + ctx.body = 'false' + next() + } + const deleteResult = await deletePromise(uuidPath) // controller column sd_uploading close await controller.update({ sd_uploading: false }, controllerID) + // meta sd_card_uploaded true await recordingDataMeta.update({ sd_data_uploaded: true }, metaID) - ctx.body = result + ctx.body = deleteResult next() } -export const get = async (ctx, 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() +// } diff --git a/src/controllers/file/sd_card/sd_card_manipulate.py b/src/controllers/file/sd_card/sd_card_manipulate.py deleted file mode 100644 index 3c7a44e..0000000 --- a/src/controllers/file/sd_card/sd_card_manipulate.py +++ /dev/null @@ -1,1000 +0,0 @@ -import serial -import sys -from typing import Union, Tuple, List, Optional, AnyStr, Iterable -import time -import glob -import psycopg2 -import json - -file_open_ins = [0xA0, 0x00] -file_close_ins = [0xA1, 0x00] -file_read_ins = [0xA3, 0x00] -file_dir_ins = [0xA4, 0x00] -file_set_meta_ins = [0xA5, 0x00] -get_version = [0x09, 0x80] -file_del_ins = [0xA6, 0x00] - -def setup_sd_manager(mac): - ports = glob.glob('/dev/ttyACM[0-9]*') - if mac is not None: - mac = mac[12:] - - for port in ports: - try: - ser = serial.Serial(port, 115200, timeout=0.5, inter_byte_timeout=0.5) - sd_manager = SDCardFileManager(device=0, usb_interface=ser) - if mac is None: - return sd_manager - device_mac = sd_manager.get_device_mac() - device_mac_str = ":".join('%02X' % b for b in device_mac) - # print(mac, device_mac_str) - - if device_mac_str == 'AB:CD' or device_mac_str == '4A:71': - return sd_manager - else: - if device_mac_str == mac: - return sd_manager - except BaseException as e: - print(e) - print('port' + str(port) + 'not match') - pass - return None - -def init_usb_serial(): - - argv_path = "/" - if len(sys.argv) > 1: - port = "/dev/ttyACM" + sys.argv[1] - if len(sys.argv) > 2: - argv_path += str(sys.argv[2]) - else: - port = "/dev/ttyACM0" - - ser = serial.Serial(port, 115200, timeout=0.5, inter_byte_timeout=0.5) - return ser - -def build_usb_ins(raw_ins: list, path:str = None, file_handle: int = 0, read_len: int = 0, meta=0 ) -> list: - command_prefix = 0x55AA - command_suffix = 0xAA55 - ctrl_prefix = 0x33CC - ctrl_suffix = 0xCC33 - - FA_READ = 0x01 - FA_WRITE = 0x02 - FA_OPEN_EXISTING = 0x00 - FA_CREATE_NEW = 0x04 - FA_CREATE_ALWAYS = 0x08 - FA_OPEN_ALWAYS = 0x10 - FA_OPEN_APPEND = 0x30 - - # print("path=", path) - if raw_ins == file_open_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += FA_READ.to_bytes(2, byteorder='little') - param += bytearray(path, 'utf8') - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == file_read_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += (file_handle).to_bytes(4, byteorder="little") # file handler - param += (read_len).to_bytes(4, byteorder="little") # max read size - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == file_close_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += (file_handle).to_bytes(4, byteorder="little") # file handler - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == get_version: - param = raw_ins[0].to_bytes(1, byteorder='little') - param += raw_ins[1].to_bytes(1, byteorder='little') - - ret = ctrl_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += ctrl_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == file_set_meta_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += (meta).to_bytes(4, byteorder="little") - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif path is not None: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += bytearray(path, 'utf8') - param += 0x00.to_bytes(2, byteorder='little') - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - else: - ins_len = len(raw_ins) - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += ins_len.to_bytes(2, byteorder='little') - ret += bytes(raw_ins) - ret += command_suffix.to_bytes(2, byteorder='little') - return ret - -class database(): - def __init__(self): - self._conn = self.setup_db_conn() - - def setup_db_conn(self): - conn = psycopg2.connect( - database="postgres", - user="biopro", - password="BioProControlBox", - host="127.0.0.1", - port="5432" - ) - return conn - - def get_meta_by_uuid(self, uuid): - cursor = self._conn.cursor() - sql_str = 'SELECT raw_data FROM "public"."recording_data_metas" WHERE uuid = \'' + uuid + '\'' - cursor.execute(sql_str) - ret = None - try: - ret = cursor.fetchall() - except BaseException as e: - print(e) - exit - cursor.close() - return ret - - def get_raw_by_channel_id(self, channel, id): - cursor = self._conn.cursor() - sql_str = 'SELECT end_time FROM "public"."{channel}_recording_data_raws" WHERE id = {id}'.format(channel = channel, id = id) - cursor.execute(sql_str) - ret = None - try: - ret = cursor.fetchall() - except BaseException as e: - print(e) - exit - cursor.close() - return ret - - def update_raw_sd_data(self, channel, id, data): - cursor = self._conn.cursor() - # sql_str = 'UPDATE "public"."{channel}_recording_data_raws" SET sd_data = sd_data || \'{data}\' WHERE id = {id}'.format(channel = channel, data = data, id = id) - sql_str = 'UPDATE "public"."{channel}_recording_data_raws" SET sd_data = CONCAT(sd_data, %s) WHERE id = %s'.format(channel = channel) - ret = None - sql_set = (data, str(id)) - # print('sql_set', sql_set) - # print('sql_str', sql_str) - try: - ret = cursor.execute(sql_str, sql_set) - self._conn.commit() - cursor.close() - except BaseException as e: - print(e) - exit - return ret - - def clear_raw_sd_data(self, channel, id): - cursor = self._conn.cursor() - # sql_str = 'UPDATE "public"."{channel}_recording_data_raws" SET sd_data = sd_data || \'{data}\' WHERE id = {id}'.format(channel = channel, data = data, id = id) - sql_str = 'UPDATE "public"."{channel}_recording_data_raws" SET sd_data = \'\' WHERE id = {id}'.format(channel = channel, id = id) - ret = None - sql_set = (str(id)) - # print('sql_set', sql_set) - # print('sql_str', sql_str) - try: - ret = cursor.execute(sql_str) - self._conn.commit() - cursor.close() - except BaseException as e: - print(e) - exit - return ret - -class NeuliveThreeOneDataDecoder(): - def __init__(self): - self._prev_time_stamp = None - self._prev_packet_delta_mean = None - self._prev_packet_delta_time = [] - self._start_new_packet = False - self._start_time_offset = 0 - self._start_time = [] - self._end_time = [] - - def start_time_set(self, time_list: list): - if isinstance(time_list, list): - self._start_time = time_list - - def end_time_set(self, time_list: list): - if isinstance(time_list, list): - self._end_time = time_list - - def decode_packet(self, data:list): - if data is None or len(data) < 9: - return None - - sample_number = data[6] - - # channel data & acc data number should be sample_number+2 - if (len(data)-9)/3 != sample_number+2: - return None - - axis_start_index = 9 + sample_number * 3 - axis_data_length = int((len(data) - axis_start_index) / 6) - - time_stamp = data[2] | data[3] << 8 | data[4] << 16 | data[5] << 24 # us - time_delta = data[7] | data[8] << 8 # us - - # print("time_stamp:", time_stamp) - # print("time_delta:", time_delta) - - stop = len(data) - - # discard old data - if self._start_new_packet is False: - if time_stamp < 0x00_01_00_00: - self._start_new_packet = True - self._start_time_offset = time_stamp - else: - return None - - # update previous time - if self._prev_time_stamp is None or self._prev_time_stamp == 0: - self._prev_time_stamp = time_stamp - - # is data lost? - data_packets_time_delta = time_stamp - self._prev_time_stamp - if data_packets_time_delta < 0: - return None - elif self._prev_packet_delta_mean is None or self._prev_packet_delta_mean == 0: - self._prev_packet_delta_time = [] - self._prev_packet_delta_time.append(data_packets_time_delta) - self._prev_packet_delta_mean = sum(self._prev_packet_delta_time) / len(self._prev_packet_delta_time) - elif data_packets_time_delta > 3 * self._prev_packet_delta_mean: - # print("[warning] data lost time = ", time_stamp/1e6) - self._prev_packet_delta_mean = 0 - self._prev_packet_delta_time = [] - else: - # update packet delta standard - MAX_PREV_PACKET = 10 - if len(self._prev_packet_delta_time) >= MAX_PREV_PACKET: - self._prev_packet_delta_time.pop(0) - self._prev_packet_delta_time.append(data_packets_time_delta) - self._prev_packet_delta_mean = sum(self._prev_packet_delta_time) / len(self._prev_packet_delta_time) - - # init ret object - ret = [] - time_step = time_delta/(sample_number) - active_ch = [] - ret_dict = {} - - # decode recording data - NUMBER_OF_CALI_CH = 16 - for i in range(sample_number): - ret_time_stamp = int(time_stamp + i*time_step - self._start_time_offset) - - # avoid index out of range - offset = 9 + 3 * i - if offset + 1 < stop: - ch = data[offset] - d1 = data[offset + 1] - d2 = data[offset + 2] - - channel = ch - value = d1 << 8 | d2 - - # if channel < NUMBER_OF_CALI_CH and self.cali_coeff is not None: - # gain, offset = self.cali_coeff[NUMBER_OF_CALI_CH * amp_gain + channel] - - # if gain == 0: - # cali_value = value - 2048 - # elif gain == 1 and offset == 0: - # cali_value = value - 2048 - # else: - # cali_value = int(1000 * ((value - 2048 - offset) / gain)) - # else: - # cali_value = value - 2048 - cali_value = value - 2048 - - # append ret dict - _ch_dict = str(channel) - if _ch_dict in active_ch: - pass - # ret_dict{_ch_dict} - else: - active_ch.append(_ch_dict) - ret_dict[_ch_dict] = [] - ret_dict[_ch_dict].append(ret_time_stamp) - ret_dict[_ch_dict].append(cali_value) - - sub_ret = [ret_time_stamp, channel, value] - ret.append(sub_ret) - return ret_dict - -class dat_file(): - def __init__(self, usb_interface, name: str = "", path: str = "", size: int = 0): - self._usb_interface = usb_interface - if name.startswith('.meta'): - self._name = name - self._path = path + name - else: - self._name = name - self._path = path + "/" + name - self._size = size - - def get_name(self) -> str: - return self._name - - def print_name(self): - print(self._name) - - def _file_open(self) -> int: - file_open = build_usb_ins(file_open_ins, self._path) - self._usb_interface.write(file_open) - - file_handle = 0 - prefix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if prefix == 0x55AA: - total = int.from_bytes(self._usb_interface.read(2), byteorder='little') - file_handle_bytes = self._usb_interface.read(total) - file_handle = int.from_bytes(file_handle_bytes, byteorder='little') - - suffix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if suffix != 0xAA55: - print("suffix error") - return 0 - return file_handle - - def _file_close(self, file_handle: int): - file_close = build_usb_ins(file_close_ins, file_handle=file_handle) - self._usb_interface.write(file_close) - - prefix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if prefix == 0x55AA: - total = int.from_bytes(self._usb_interface.read(2), byteorder='little') - read = self._usb_interface.read(total) - suffix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if suffix != 0xAA55: - print("suffix error") - - def _file_read(self, file_handle: int) -> list: - file_read = build_usb_ins(file_read_ins, file_handle=file_handle, read_len=1024) - - total = 1 - ret = [] - while total > 0: - self._usb_interface.write(file_read) - - prefix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if prefix == 0x55AA: - total = int.from_bytes(self._usb_interface.read(2), byteorder='little') - # print("total read len:", total) - - read = self._usb_interface.read(total) - - # data = list(read) - # print("data len:", len(data)) - # print("read data:", data) - suffix = int.from_bytes(self._usb_interface.read(2), byteorder='little') - if suffix != 0xAA55: - print("suffix error") - else: - ret.extend(read) - return ret - -class rec_file(): - def __init__(self, usb_interface, name: str = "", path: str = "", dat_files: list = []): - self._usb_interface = usb_interface - self._name = name - self._path = path - self._dat_files = dat_files - self._meta_uuid = '' - - def update_meta_uuid(self) -> list: - META_UUID_LENGTH = 36 - self._meta_uuid = '' - for meta_file in self._dat_files: - dfile_name = meta_file.get_name() - # print("dfile_name = ", dfile_name) - if dfile_name.startswith('.meta'): - # meta_file_handle = meta_file._file_open() - # uuid = meta_file._file_read(meta_file_handle) - # meta_file._file_close(meta_file_handle) - if len(dfile_name) >= META_UUID_LENGTH+5: - for idx in range(META_UUID_LENGTH): - self._meta_uuid += dfile_name[idx+5] - # print("self._meta_uuid = ", self._meta_uuid) - break - - def get_meta_uuid(self) -> str: - return self._meta_uuid - - def get_dat_data(self): - for dat_file in self._dat_files: - if dat_file.get_name() != ".meta": - dat_file_handle = dat_file._file_open() - data = dat_file._file_read(dat_file_handle) - dat_file._file_close(dat_file_handle) - return data - return None - - def list_dat_name(self): - for dat_file in self._dat_files: - if dat_file.get_name() != ".meta": - print(dat_file.get_name()) - - def get_name(self): - return self._name - - def get_path(self): - return self._path - -class directory(): - def __init__(self, - name: str = "/", - path: str = "/" , - folder: list = [], - file:list = []): - self.name = name - self.path = path - self.folder = folder - self.file = file - - def get_path(self) -> str: - return self.path - - def get_name(self) -> str: - return self.name - - def print_name(self) -> str: - print(self.name) - - def list_folder(self): - for folder in self.folder: - yield folder - - def print_folder(self): - print("parent folder name:", self.name) - for folder in self.folder: - folder.print_name() - print("end of child folder\n") - - def list_file(self): - for file in self.file: - yield file - - def print_file(self): - print("parent folder name:", self.name) - for file in self.file: - print(file) - print("end of files list\n") - - def add_folder(self, child_folder): - if isinstance(child_folder, Iterable): - for folder in child_folder: - self.folder.append(folder) - else: - self.folder.append(child_folder) - - def add_file(self, files): - if isinstance(files, Iterable): - for file in files: - self.file.append(file) - else: - self.file.append(files) - -class SDCardFileManager(database): - def __init__(self, device: int, usb_interface): - super().__init__() - self._device = device - self._usb_interface = usb_interface - self._root_dir = directory() - self._rec_files = [] - # self._conn = setup_db_conn() - # self._cursor = self._conn.cursor() - # self._db_api = ApiRequests() - - def close_serial_port(self): - if self._usb_interface is not None: - self._usb_interface.close() - - - def update_sd_file(self): - first_layer_folder = self._get_dir() - - for folder in first_layer_folder: - folder_path = self._root_dir.get_name() + folder - new_folder = directory(name=folder, path=folder_path, folder=[], file=[]) - self._root_dir.add_folder(new_folder) - # self._root_dir.print_folder() - - for folder in self._root_dir.folder: - folder_name = folder.get_name() - second_layter_folder = self._get_dir(folder.path) - - for second_folder in second_layter_folder: - folder_path = folder.path + "/" + second_folder - new_folder = directory(name=second_folder, path=folder_path, folder=[], file=[]) - folder.add_folder(new_folder) - # folder.print_folder() - - for second_folder in folder.folder: - dat_file_list = [] - for dat_file_name in self._get_file(second_folder.path): - dfile = dat_file(usb_interface=self._usb_interface, - name=dat_file_name, - path=second_folder.path) - dat_file_list.append(dfile) - - rfile = rec_file(usb_interface=self._usb_interface, - name=second_folder.get_path(), - path=second_folder.get_path(), - dat_files=dat_file_list) - rfile.update_meta_uuid() - if rfile._meta_uuid != '': - self._rec_files.append(rfile) - - def get_file_list(self) -> list: - return self._rec_files - - def get_file_meta_uuid(self, file_path: str): - for rfile in self._rec_files: - if rfile.get_path() == file_path: - return rfile.get_meta_uuid() - return [None] - - def _build_usb_ins(self, raw_ins: list, path:str = None, file_handle: int = 0, read_len: int = 0) -> list: - command_prefix = 0x55AA - command_suffix = 0xAA55 - ctrl_prefix = 0x33CC - ctrl_suffix = 0xCC33 - - FA_READ = 0x01 - FA_WRITE = 0x02 - FA_OPEN_EXISTING = 0x00 - FA_CREATE_NEW = 0x04 - FA_CREATE_ALWAYS = 0x08 - FA_OPEN_ALWAYS = 0x10 - FA_OPEN_APPEND = 0x30 - - if raw_ins == file_open_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += FA_READ.to_bytes(2, byteorder='little') - param += bytearray(path, 'utf8') - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == file_read_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += (file_handle).to_bytes(4, byteorder="little") # file handler - param += (read_len).to_bytes(4, byteorder="little") # max read size - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == file_close_ins: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += (file_handle).to_bytes(4, byteorder="little") # file handler - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - elif raw_ins == get_version: - param = raw_ins[0].to_bytes(1, byteorder='little') - param += raw_ins[1].to_bytes(1, byteorder='little') - - ret = ctrl_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += ctrl_suffix.to_bytes(2, byteorder='little') - - elif path is not None: - param = raw_ins[0].to_bytes(2, byteorder='little') - param += bytearray(path, 'utf8') - param += 0x00.to_bytes(2, byteorder='little') - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += len(param).to_bytes(2, byteorder='little') - ret += param - ret += command_suffix.to_bytes(2, byteorder='little') - - else: - ins_len = len(raw_ins) - - ret = command_prefix.to_bytes(2, byteorder='little') - ret += ins_len.to_bytes(2, byteorder='little') - ret += bytes(raw_ins) - ret += command_suffix.to_bytes(2, byteorder='little') - return ret - - def _get_file(self, path: str = "/") -> list: - ''' read directory in SD card - - :parma path: target directory path - :return: dir list - ''' - - ROOT_LAYER = 1 - YEAR_MONTH_LAYER = 2 - HOUR_MINUTE_LAYER = 3 - - directory_layer = path.count("/") + 1 - if directory_layer != HOUR_MINUTE_LAYER: - return [] - - ins_file_dir = self._build_usb_ins(file_dir_ins, path) - - self._usb_interface.write(ins_file_dir) - file_list_raw = str(self._usb_interface.read(2048)) - - file_list = [] - - index=0 - while True: - index = file_list_raw.find("Bytes") - - if index > 0: - if file_list_raw[index+7:index+12] == '.meta': - file_list.append(file_list_raw[index+7:index+48]) - file_list_raw = file_list_raw[:index] + file_list_raw[index+50:] - # print("file_list_raw[index+7:index+46] = ", file_list_raw[index+7:index+46]) - else: - file_list.append(file_list_raw[index+7:index+16]) - file_list_raw = file_list_raw[:index] + file_list_raw[index+18:] - # print("file_list_raw[index+7:index+16] = ", file_list_raw[index+7:index+16]) - else: - break - return file_list - - def _get_dir(self, path: str = "/") -> list: - ''' read directory in SD card - - :parma path: target directory path - :return: dir list - ''' - - ROOT_LAYER = 1 - YEAR_MONTH_LAYER = 2 - HOUR_MINUTE_LAYER = 3 - - if path == "/": - directory_layer = ROOT_LAYER - else: - directory_layer = path.count("/") + 1 - - ins_file_dir = self._build_usb_ins(file_dir_ins, path) - - self._usb_interface.write(ins_file_dir) - file_dir_raw = str(self._usb_interface.read(1024)) - # print("file_dir_raw", file_dir_raw) - - dir_list = [] - - index=0 - - while True: - index = file_dir_raw.find("") - - if index > 0: - if directory_layer == ROOT_LAYER: - dir_list.append(file_dir_raw[index+7:index+15]) - file_dir_raw = file_dir_raw[:index] + file_dir_raw[index+17:] - elif directory_layer == YEAR_MONTH_LAYER: - dir_list.append(file_dir_raw[index+7:index+13]) - file_dir_raw = file_dir_raw[:index] + file_dir_raw[index+15:] - else: - return [] - else: - break - return dir_list - - def get_device_mac(self) -> list: - get_version_ins = self._build_usb_ins(get_version) - # print("get_version_ins = ", list(get_version_ins)) - - self._usb_interface.write(get_version_ins) - device_version = list(self._usb_interface.read(20)) - return device_version[9:11] - - def del_rfile(self, rfile_name: str='', uuid: str=''): - del_file_path = '' - if rfile_name == '': - if uuid != '': - if self._rec_files == []: - print("there is no file in SD manager, please init and update the manager") - return - - for rfile in self._rec_files: - if rfile._meta_uuid == uuid: - del_file_path = rfile._path - break - - if del_file_path == '': - print("the uuid is not exist") - return - else: - print("please enter correct file path or uuid!") - return - else: - del_file_path = rfile_name - - del_ins = self._build_usb_ins(raw_ins=file_del_ins, path = del_file_path) - self._usb_interface.write(del_ins) - - # def is_meta_file_exist_db(self, meta_uuid) -> bool: - # # meta = self._db_api.getMetaByUUID(meta_uuid) - # meta = MetaAPI.getByUUID(meta_uuid) - - # if isinstance(meta_uuid, str): - # if meta is None: - # return False - # else: - # return True - # else: - # print("incorrect meta uuid format, expect str") - # return False - - def is_meta_file_exist_sd(self, meta_uuid) -> bool: - for rfile in self._rec_files: - if meta_uuid == rfile._meta_uuid: - return True - return False - - def _get_rec_file(self, meta_uuid) -> Optional[rec_file]: - for rfile in self._rec_files: - if meta_uuid == rfile.get_meta_uuid(): - return rfile - return None - - def download_rec_file(self, meta_uuid): - # if self.is_meta_file_exist_db(meta_uuid) is False: - # print("uuid is not exist in database") - # return None - - # if self.is_meta_file_exist_sd(meta_uuid) is False: - # print("uuid is not exist in sd card") - # return None - - # init time_threshold for each channel - # time_threshold = {'channel_a': ['ta1', 'ta2', 'ta3', ...], 'channel_b': ['tb1', 'tb2', 'tb3', ...], ...} - time_threshold = {} - raw_id_list = {} - rawID_timeThreshold_idx = {} - # raw_list = self._db_api.getMetaByUUID(meta_uuid)[0]['raw_data'] - - exe_start_time = time.time() - - # print("loading database parameter...") - raw_list = self.get_meta_by_uuid(meta_uuid)[0][0] # column raw_data index 14 - for ch in raw_list.keys(): - time_threshold[ch] = [] - raw_id_list[ch] = [] - rawID_timeThreshold_idx[ch] = 0 - for raw_id in raw_list[ch]: - time_threshold[ch].append(self.get_raw_by_channel_id(ch, raw_id)[0][0]) - raw_id_list[ch].append(raw_id) - - # clear sd_data - # print('clear sd data', ch, raw_id) - self.clear_raw_sd_data(ch, raw_id) - - # print("time_threshold:", time_threshold) - # print("raw_id_list:", raw_id_list) - # print("load database parameter done.\n") - - # init neulive3.x deocoder - neu3x_decoder = NeuliveThreeOneDataDecoder() - - # get rec file - rfile = self._get_rec_file(meta_uuid) - - number_of_dat = len(rfile._dat_files) - - for current_dat_file_idx in range(1, number_of_dat): - dat_file_done_time = time.time() - # print("loading sd card data...") - dfile = rfile._dat_files[current_dat_file_idx] - dat_file_handle = dfile._file_open() - dfile_data = dfile._file_read(dat_file_handle) - dfile._file_close(dat_file_handle) - if len(dfile_data) == 0: - continue - - # init decode message - current_data_idx = 0 - write_raw_file_flag = False - chip_id = dfile_data[0] - mcu_id = dfile_data[1] - sample_per_packet = dfile_data[6] - - # assume there are 300 channels - # ch 1~64 is recording channel - # ch 256, 257, 258, 259 is acc channel - str_data_buf = ['' for _ in range(300)] - - # sample_per_packet+2 because acc data can be view as two ch data - # +9 because header length = 9, which is chip_id, mcu_id, timestamp(4B), sampleNumber, deltaTime(2B) - packet_len = (sample_per_packet+2) * 3 + 9 - - # print_counter = 0 - while current_data_idx + packet_len < len(dfile_data): - q_buf = dfile_data[current_data_idx:current_data_idx + packet_len] - current_data_idx += packet_len - - # decode raw sd card data - raw_data_dict = neu3x_decoder.decode_packet(q_buf) - for ch in raw_data_dict.keys(): - try: - last_timeStamp = raw_data_dict[ch][-2] - except KeyError: - continue - except BaseException as e: - print(e) - - # get time threshold - try: - time_threshold_list = time_threshold[ch] - time_threshold_temp = int(time_threshold_list[rawID_timeThreshold_idx[ch]]) - except KeyError: - continue - except BaseException as e: - print(e) - - # update time_stamp threshold - # comment this block if split sd data by size (instead of endtime) - if last_timeStamp > time_threshold_temp: - if rawID_timeThreshold_idx[ch] >= len(time_threshold_list)-1: - rawID_timeThreshold_idx[ch] = len(time_threshold_list) - 1 - else: - write_raw_file_flag = True - - # write raw file if reach time_stamp threshold - # comment this block if split sd data by size (instead of endtime) - if write_raw_file_flag: - write_raw_file_flag = False - raw_id = raw_id_list[ch][rawID_timeThreshold_idx[ch]] - self.update_raw_sd_data(ch, raw_id , str_data_buf[int(ch)]) - rawID_timeThreshold_idx[ch] += 1 - str_data_buf[int(ch)] = '' - # print("loading byte: %d (total %d bytes); file:%d/%d; ch=%d, switch to raw_idx=%d" - # %(current_data_idx, len(dfile_data), current_dat_file_idx, number_of_dat-1, int(ch), rawID_timeThreshold_idx[ch])) - - # append str_data in buffer - str_data = ' '.join(str(data) for data in raw_data_dict[ch]) - str_data_buf[int(ch)] = str_data_buf[int(ch)] + str_data + '"***"' - - # write raw file if str_data_buf reach a certain size - # if len(str_data_buf[int(ch)]) > 1e5: - # raw_id = raw_id_list[ch][rawID_timeThreshold_idx[ch]] - # RawAPI.updateSdData(ch, raw_id , {'data': str_data_buf[int(ch)]}) - # str_data_buf[int(ch)] = '' - - # uncomment this block if split sd data by size (instead of endtime) - # if rawID_timeThreshold_idx[ch] + 1 >= len(raw_id_list[ch]): - # rawID_timeThreshold_idx[ch] = len(raw_id_list[ch]) - 1 - # else: - # rawID_timeThreshold_idx[ch] += 1 - # print("loading byte: %d (total %d bytes); file:%d/%d; ch=%d, raw_idx=%d" - # %(current_data_idx, len(dfile_data), current_dat_file_idx, number_of_dat-1, int(ch), rawID_timeThreshold_idx[ch])) - - # write last sd_data before switch to next dat file - for ch in raw_list.keys(): - if str_data_buf[int(ch)] != '': - raw_id = raw_id_list[ch][rawID_timeThreshold_idx[ch]] - self.update_raw_sd_data(ch, raw_id , str_data_buf[int(ch)]) - str_data_buf[int(ch)] = '' - - # uncomment this block if split sd data by size (instead of endtime) - # rawID_timeThreshold_idx[ch] += 1 - # if rawID_timeThreshold_idx[ch] >= len(raw_id_list[ch]): - # rawID_timeThreshold_idx[ch] = len(raw_id_list[ch]) - 1 - # print("raw_id=%d, loading sd_data tail, file:%d/%d" %(raw_id, current_dat_file_idx, number_of_dat-1)) - # print("load file %d done, time cost: %ds" %(current_dat_file_idx, time.time()-dat_file_done_time)) - # print("") - - # update rec_raw start/end time - # for ch in raw_list.keys(): - # checkEndTime[ch] = [] - # for raw_id in raw_list[ch]: - # raw_time_data = self._db_api.getRawByID(channel=ch, id=raw_id)[0]['sd_data'].split() - # start_time = raw_time_data[0] - # end_time = raw_time_data[-2] - # self._db_api.updateRawByAttr(channel=ch, id=raw_id, attrs= {'sd_start_time': start_time}) - # self._db_api.updateRawByAttr(channel=ch, id=raw_id, attrs= {'sd_end_time': end_time}) - - exe_end_time = time.time() - - # checkEndTime = {} - # for ch in raw_list.keys(): - # checkEndTime[ch] = [] - # for raw_id in raw_list[ch]: - # raw_time_data = self._db_api.getRawByID(channel=ch, id=raw_id)[0]['sd_data'].split() - # end_time = raw_time_data[-2] - # checkEndTime[ch].append(end_time) - # print("checkEndTime:", checkEndTime) - - execute_time = int(exe_end_time-exe_start_time) - execute_time_m = int(execute_time/60) - execute_time_s = execute_time - execute_time_m*60 - # print("execute time = %dm %ds" %(execute_time_m, execute_time_s)) - -def main(): - method = sys.argv[1] - mac = None - uuid = None - if len(sys.argv) > 3: - mac = sys.argv[2] - uuid = sys.argv[3] - - # create serial & sd_manager - sd_manager = setup_sd_manager(mac) - - # print('sd_manager', sd_manager) - - if sd_manager != None: - # update sd file list - sd_manager.update_sd_file() - - if method == 'exist': - result = sd_manager.is_meta_file_exist_sd(uuid) - print(result, end='') - elif method == 'delete': - sd_manager.del_rfile(uuid) - # sys.stdout.flush() - print(True, end='') - elif method == 'upload': - sd_manager.download_rec_file(uuid) - print(True, end='') - elif method == 'get_uuid_list': - rec_list = [] # rec_tuple = [(name, uuid), (name, uuid)] - file_list = sd_manager.get_file_list() - for rfile in file_list: - rec_list.append(rfile.get_meta_uuid()) - print(' '.join(rec_list), end='') - - # rec_tuple = [] # rec_tuple = [(name, uuid), (name, uuid)] - # file_list = sd_manager.get_file_list() - # for rfile in file_list: - # rec_tuple.append((rfile.get_name(), rfile.get_meta_uuid())) - - # show all recording file - # file_number = 0 - # print("sd card recording file list:") - # for rfile in rec_tuple: - # print("file number:", file_number,"name:", rfile[0], "uuid", rfile[1]) - # file_number += 1 - # print("") - - # print("choose a file to load: ", end="") - # file_number = int(input()) - - sd_manager.close_serial_port() - - exit() - -if __name__ == '__main__': - main() diff --git a/src/routes/api/file/sdcard.js b/src/routes/api/file/sdcard.js index f75b048..465344b 100644 --- a/src/routes/api/file/sdcard.js +++ b/src/routes/api/file/sdcard.js @@ -5,9 +5,9 @@ import controllers from '../../../controllers' export default function (_prefix) { const prefix = _prefix + '/sdcard' return [ - ['GET', prefix + '/get', controllers.sdCard.get], + ['GET', prefix + '/get', controllers.sdCard.getFileList], ['POST', prefix + '/exist', controllers.sdCard.exist], - ['POST', prefix + '/upload', controllers.sdCard.upload], - ['POST', prefix + '/delete', controllers.sdCard.deleted] + ['POST', prefix + '/upload', controllers.sdCard.uploadThenDelete], + // ['POST', prefix + '/delete', controllers.sdCard.deleted] ] } From e4816e9447170142af7082b0af42ae22af5a8cb7 Mon Sep 17 00:00:00 2001 From: peterlu14 Date: Tue, 23 Nov 2021 12:43:15 +0800 Subject: [PATCH 4/4] [update] sd card error handling --- src/controllers/file/sd_card/index.js | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/controllers/file/sd_card/index.js b/src/controllers/file/sd_card/index.js index 661845f..9bea69e 100644 --- a/src/controllers/file/sd_card/index.js +++ b/src/controllers/file/sd_card/index.js @@ -143,27 +143,20 @@ export const uploadThenDelete = async (ctx, next) => { const uploadResult = await uploadPromise(uuidPath, uuid, ampGain) - if (uploadResult === 'false') { - // controller column sd_uploading close - await controller.update({ - sd_uploading: false - }, controllerID) - ctx.body = 'false' - next() + if (uploadResult === 'true') { + // meta sd_card_uploaded true + await recordingDataMeta.update({ + sd_data_uploaded: true + }, metaID) + await deletePromise(uuidPath) } - const deleteResult = await deletePromise(uuidPath) // controller column sd_uploading close await controller.update({ sd_uploading: false }, controllerID) - // meta sd_card_uploaded true - await recordingDataMeta.update({ - sd_data_uploaded: true - }, metaID) - - ctx.body = deleteResult + ctx.body = uploadResult next() }