跳转至

HRV指标计算

最后更新:2023年08月31日

接口能力

本接口可分析心电数据中的常用HRV指标,包括SDNN、RMSSD、SDSD、PNN50、TP、HF、LF、VLF、LF/HF等。

请求方法

HTTP方法: POST
请求URL:http://api.amsu-new.com/amsu-analysis/v2/hrv/common/results/
数据提交方式:multipart/form-data

Header参数:

字段 类型 描述
Authorization Bearer Token 构造方式为Bearer+(空格)+(Access Token)

Body参数:

字段 类型 必传 范围 描述
height Integer 90 - 240 身高,单位:cm
weight Float 30.0 - 200.9 体重,单位:kg
age Integer 18 - 120 年龄
gender Integer 0 - 1 性别,男10
ecg_file File *.ecg 二进制心电文件,以.ecg作后缀名,尺寸限制 100M 以内(约55小时离线数据)。数据将按照 小端序 2字节short型被解析,可使用 心电图查看工具 观察您的文件是否能正确解析
model String online、offline 心电记录模式,通过蓝牙采集的心电数据为online,在AMSU设备中存储的心电数据为offline
device String V6、S1 心电设备类型,对应蓝牙协议中「Device Information」-「Model Number」里包含的开发代号,心电衣(带)主机对应代号为V6,心电贴对应代号为S1

提示

若 model 为 online ,请在构造心电文件时用您自定义的信息(或任意值)填充前256个字节作为头部,若不构造头部,则文件中前1~2秒的心电数据不会参与分析。

返回参数

字段 类型 描述
id Integer 本次分析的标识
hr Integer 平均心率
max_hr Integer 最高心率
min_hr Integer 最低心率
sdnn Interger HRV 时域指标,正常窦性⼼心搏间期(NN)的标准差,单位:ms
rmssd Integer HRV 时域指标,相邻NN间期之差的均⽅根值,单位:ms
sdsd Integer HRV 时域指标,相邻NN间期之差的标准差,单位:ms
pnn50 Float HRV 时域指标,相邻NN间期差值大于50ms间隔以上的心搏数占总心搏数的比例(乘以100),单位:%
tp Interger HRV 频域指标,总功率(频段≤0.4Hz),单位:ms2
hf Interger HRV 频域指标,高频功率(频段0.15~0.4Hz),单位:ms2
lf Integer HRV 频域指标,低频功率(频段0.04~0.15Hz),单位:ms2
vlf Integer HRV 频域指标,极底频功率(频段0.0033~0.04Hz),单位:ms2
lf_hf_ratio Float 低频与高频功率之比

正确返回示例:

HTTP状态码:200

{
    "id": 334,
    "hr": 87,
    "max_hr": 96,
    "min_hr": 81,
    "sdnn": 29,
    "rmssd": 19,
    "sdsd": 19,
    "pnn50": 1.4,
    "tp": 559,
    "hf": 149,
    "lf": 286,
    "vlf": 123,
    "lf_hf_ratio": 1.9
}

错误返回示例:

HTTP状态码不为200

{
    "error": {
        "code": "COMMON.INVALID_FILE_TYPE",
        "msg": "Unsupported file type for field 'ecg_file'."
    }
}

错误码

HTTP状态码 错误码 说明
422 ECG.INVALID_DATA 无法从心电数据中有效识别出R波,此错误的可能原因有:1. 心电文件格式出错;2.心电数据未正常采集;3.心电数据质量过差

另请参见 公共错误码

示例代码

OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
  .addFormDataPart("height","188")
  .addFormDataPart("weight","88.8")
  .addFormDataPart("gender","0")
  .addFormDataPart("age","18")
  .addFormDataPart("ecg_file","example_online.ecg",
    RequestBody.create(MediaType.parse("application/octet-stream"),
    new File("/datas/example_online.ecg")))
  .addFormDataPart("model","online")
  .addFormDataPart("device","V6")
  .build();
Request request = new Request.Builder()
  .url("http://api.amsu-new.com/amsu-analysis/v2/hrv/common/results/")
  .method("POST", body)
  .addHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcHBfa2V5OjkzZWUyMGNiNTliOTY0OWY3YzIwIiwiZXhwIjoxNjQ4Njk5MjA2fQ.WljGB-66JR9CFNYzaXjR81i0ySNmXfVAsqVW_lfLT7g")
  .build();
Response response = client.newCall(request).execute();
#import <Foundation/Foundation.h>

dispatch_semaphore_t sema = dispatch_semaphore_create(0);

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://api.amsu-new.com/amsu-analysis/v2/hrv/common/results/"]
  cachePolicy:NSURLRequestUseProtocolCachePolicy
  timeoutInterval:10.0];
NSDictionary *headers = @{
  @"Authorization": @"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcHBfa2V5OjkzZWUyMGNiNTliOTY0OWY3YzIwIiwiZXhwIjoxNjQ4Njk5MjA2fQ.WljGB-66JR9CFNYzaXjR81i0ySNmXfVAsqVW_lfLT7g"
};

[request setAllHTTPHeaderFields:headers];
NSArray *parameters = @[
  @{ @"name": @"height", @"value": @"188" }, 
  @{ @"name": @"weight", @"value": @"88.8" }, 
  @{ @"name": @"gender", @"value": @"0" }, 
  @{ @"name": @"age", @"value": @"18" }, 
  @{ @"name": @"ecg_file", @"fileName": @"/datas/example_online.ecg" }, 
  @{ @"name": @"model", @"value": @"online" }, 
  @{ @"name": @"device", @"value": @"V6" } 
];

NSString *boundary = @"----WebKitFormBoundary7MA4YWxkTrZu0gW";
NSError *error;
NSMutableString *body = [NSMutableString string];

for (NSDictionary *param in parameters) {
  [body appendFormat:@"--%@\r\n", boundary];
  if (param[@"fileName"]) {
    [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"; filename=\"%@\"\r\n", param[@"name"], param[@"fileName"]];
    [body appendFormat:@"Content-Type: %@\r\n\r\n", param[@"contentType"]];
    [body appendFormat:@"%@", [NSString stringWithContentsOfFile:param[@"fileName"] encoding:NSUTF8StringEncoding error:&error]];
    if (error) {
      NSLog(@"%@", error);
    }
  } else {
    [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"\r\n\r\n", param[@"name"]];
    [body appendFormat:@"%@", param[@"value"]];
  }
}
[body appendFormat:@"\r\n--%@--\r\n", boundary];
NSData *postData = [body dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postData];

[request setHTTPMethod:@"POST"];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  if (error) {
    NSLog(@"%@", error);
    dispatch_semaphore_signal(sema);
  } else {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
    NSError *parseError = nil;
    NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
    NSLog(@"%@",responseDictionary);
    dispatch_semaphore_signal(sema);
  }
}];
[dataTask resume];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcHBfa2V5OjkzZWUyMGNiNTliOTY0OWY3YzIwIiwiZXhwIjoxNjQ4Njk5MjA2fQ.WljGB-66JR9CFNYzaXjR81i0ySNmXfVAsqVW_lfLT7g");

var formdata = new FormData();
formdata.append("height", "188");
formdata.append("weight", "88.8");
formdata.append("gender", "0");
formdata.append("age", "18");
formdata.append("ecg_file", fileInput.files[0], "example_online.ecg");
formdata.append("model", "online");
formdata.append("device", "V6");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: formdata,
  redirect: 'follow'
};

fetch("http://api.amsu-new.com/amsu-analysis/v2/hrv/common/results/", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));
import requests

url = "http://api.amsu-new.com/amsu-analysis/v2/hrv/common/results/"

payload={'height': '188',
'weight': '88.8',
'gender': '0',
'age': '18',
'model': 'online',
'device': 'V6'}

files=[
  ('ecg_file',('example_online.ecg',open('/datas/example_online.ecg','rb'),'application/octet-stream'))
]
headers = {
  'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhcHBfa2V5OjkzZWUyMGNiNTliOTY0OWY3YzIwIiwiZXhwIjoxNjQ4Njk5MjA2fQ.WljGB-66JR9CFNYzaXjR81i0ySNmXfVAsqVW_lfLT7g'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)