东丽网口版透析机 socket- server 通讯
编辑 | blame | 历史 | 原始文档

透析机IoT数据服务 - HTTP API 第三方接入文档

版本: v1.1.0
更新日期: 2025-12-08
状态: 生产就绪 ✅

🌐 服务概览

服务地址

环境 地址 端口
开发环境 http://localhost 8080
生产环境 http://[IP地址] 8080

功能特性

实时数据查询 - 获取透析机设备的实时数据
属性映射 - 自动转换为可读的中文属性名
批量查询 - 一次获取所有设备数据
缓存管理 - 数据缓存和统计功能
限流保护 - 防止API滥用
CORS支持 - 跨域请求支持


🚀 接入指南

前置要求

  • 网络连接:能访问服务器IP地址和8080端口
  • HTTP客户端:支持标准HTTP/1.1
  • 字符编码:UTF-8

基本步骤

  1. 获取服务地址 - 咨询系统管理员获取实际服务地址
  2. 测试连接 - 调用健康检查接口验证连接
  3. 获取设备列表 - 查看可用的设备号
  4. 查询设备数据 - 获取需要的设备数据

测试连接

# 健康检查 - 验证服务可用性
curl -X GET "http://localhost:8080/api/health"

# 预期响应
{
  "code": 200,
  "message": "success",
  "data": {
    "status": "ok",
    "timestamp": "2025-12-08T10:30:45.123Z"
  }
}

📡 API端点

1. 获取单个设备数据

端点: GET /api/device/data

参数:
| 参数 | 类型 | 必需 | 说明 | 示例 |
|------|------|------|------|------|
| deviceNumber | string | ✅ | 设备号 | D001 |
| mapped | string | ❌ | 是否返回映射格式 | true/false |

请求示例:
```bash

获取原始格式数据

curl "http://localhost:8080/api/device/data?deviceNumber=D001"


**响应示例(映射格式)**:

{
"code": 200,
"message": "success",
"data": {
"deviceNumber": "D001",
"timestamp": "2025-12-08T10:30:45.123Z",
"properties": [
{
"identifier": "A",
"name": "脱水目标量",
"value": "50"
},
{
"identifier": "B",
"name": "脱水量",
"value": "25"
},
{
"identifier": "C",
"name": "脱水速率",
"value": "10"
},
{
"identifier": "R",
"name": "收缩压下限",
"value": "120"
},
{
"identifier": "mb",
"name": "脉搏-德朗",
"value": "72"
}
],
"format": "mapped"
}
}
```

限流规则: 同一设备5秒内最多请求1次


2. 获取所有设备数据

端点: GET /api/device/all

参数:
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| mapped | string | ❌ | 是否返回映射格式 |

请求示例:
bash # 获取所有设备映射数据 curl "http://localhost:8080/api/device/all?mapped=true"

响应示例:
json { "code": 200, "message": "success", "data": { "count": 2, "data": { "D001": { "timestamp": "2025-12-08T10:30:45.123Z", "properties": [ { "identifier": "A", "name": "脱水目标量", "value": "50" } ], "format": "mapped" }, "D002": { "timestamp": "2025-12-08T10:30:50.456Z", "properties": [ { "identifier": "A", "name": "脱水目标量", "value": "75" } ], "format": "mapped" } }, "format": "mapped" } }

限流规则: 全局1分钟内最多请求1次


3. 获取设备列表

端点: GET /api/device/list

参数: 无

请求示例:
bash curl "http://localhost:8080/api/device/list"

响应示例:
json { "code": 200, "message": "success", "data": { "count": 2, "devices": [ { "deviceNumber": "D001", "lastUpdate": "2025-12-08T10:30:45.123Z" }, { "deviceNumber": "D002", "lastUpdate": "2025-12-08T10:30:50.456Z" } ] } }


4. 获取缓存统计

端点: GET /api/cache/stats

参数: 无

请求示例:
bash curl "http://localhost:8080/api/cache/stats"

响应示例:
json { "code": 200, "message": "success", "data": { "timestamp": "2025-12-08T10:30:45.123Z", "totalDevices": 2, "cachedProperties": 156, "cacheSize": "45KB", "oldestData": "2025-12-08T10:20:30.000Z", "newestData": "2025-12-08T10:30:45.123Z" } }


5. 获取限流统计

端点: GET /api/ratelimit/stats

参数: 无

请求示例:
bash curl "http://localhost:8080/api/ratelimit/stats"

响应示例:
json { "code": 200, "message": "success", "data": { "enabled": true, "interval": 5000, "allDevicesInterval": 60000, "records": [ { "identifier": "D001", "lastRequest": "2025-12-08T10:30:45.123Z", "requestCount": 3 } ] } }


6. 清空缓存

端点: POST /api/cache/clear

参数: 无

请求示例:
bash curl -X POST "http://localhost:8080/api/cache/clear"

响应示例:
json { "code": 200, "message": "success", "data": { "message": "缓存已清空" } }


7. 健康检查

端点: GET /api/health

参数: 无

请求示例:
bash curl "http://localhost:8080/api/health"

响应示例:
json { "code": 200, "message": "success", "data": { "status": "ok", "timestamp": "2025-12-08T10:30:45.123Z" } }


📨 请求示例

cURL 示例

# 基础请求
curl -X GET "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"

# 添加自定义头
curl -X GET "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json"

# 带超时
curl --connect-timeout 5 --max-time 30 \
  "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"

JavaScript/Node.js 示例

// 使用 fetch API
async function getDeviceData(deviceNumber) {
  try {
    const response = await fetch(
      `http://localhost:8080/api/device/data?deviceNumber=${deviceNumber}&mapped=true`
    );
    const result = await response.json();
    
    if (result.code === 200) {
      console.log('设备数据:', result.data);
      result.data.properties.forEach(prop => {
        console.log(`${prop.name}: ${prop.value}`);
      });
    } else {
      console.error('获取失败:', result.message);
    }
  } catch (error) {
    console.error('请求错误:', error);
  }
}

getDeviceData('D001');

Python 示例

import requests
import json

# 获取单个设备数据
def get_device_data(device_number):
    url = f'http://localhost:8080/api/device/data?deviceNumber={device_number}&mapped=true'
    
    try:
        response = requests.get(url, timeout=5)
        result = response.json()
        
        if result['code'] == 200:
            print(f'设备: {device_number}')
            for prop in result['data']['properties']:
                print(f"  {prop['name']}: {prop['value']}")
        else:
            print(f'错误: {result["message"]}')
    except requests.RequestException as e:
        print(f'请求错误: {e}')

# 获取所有设备
def get_all_devices():
    url = 'http://localhost:8080/api/device/all?mapped=true'
    
    response = requests.get(url)
    data = response.json()
    
    if data['code'] == 200:
        for device_number, device_data in data['data']['data'].items():
            print(f"\n设备: {device_number}")
            for prop in device_data['properties']:
                print(f"  {prop['name']}: {prop['value']}")

if __name__ == '__main__':
    get_device_data('D001')
    get_all_devices()

Java 示例

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import org.json.JSONObject;

public class DeviceDataClient {
    private static final String BASE_URL = "http://localhost:8080";
    
    public static void getDeviceData(String deviceNumber) throws Exception {
        String url = BASE_URL + "/api/device/data?deviceNumber=" + deviceNumber + "&mapped=true";
        
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .GET()
            .build();
        
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        
        JSONObject json = new JSONObject(response.body());
        if (json.getInt("code") == 200) {
            JSONObject data = json.getJSONObject("data");
            System.out.println("设备号: " + data.getString("deviceNumber"));
            data.getJSONArray("properties").forEach(prop -> {
                JSONObject p = (JSONObject) prop;
                System.out.println("  " + p.getString("name") + ": " + p.getString("value"));
            });
        }
    }
}

📊 响应格式

成功响应

{
  "code": 200,
  "message": "success",
  "data": {
    // 实际数据内容
  }
}

错误响应

{
  "code": 400,
  "message": "缺少必要参数: deviceNumber"
}

状态码说明

状态码 含义 说明
200 OK 请求成功
400 Bad Request 请求参数错误或缺少必需参数
404 Not Found 资源不存在(如设备不存在)
429 Too Many Requests 请求过于频繁(触发限流)
500 Internal Server Error 服务器内部错误

⚠️ 错误处理

常见错误及解决方案

错误1: 设备不存在

错误响应:
json { "code": 404, "message": "设备 D001 未找到" }

解决方案:
1. 调用 /api/device/list 检查可用设备
2. 确认设备号是否正确
3. 检查设备是否已连接到系统

错误2: 请求过于频繁

错误响应:
json { "code": 429, "message": "请求过于频繁,请在 4500ms 后再试" }

解决方案:
1. 等待提示的时间后重试
2. 减少请求频率
3. 使用 /api/device/all 批量获取以减少请求次数

错误3: 缺少必需参数

错误响应:
json { "code": 400, "message": "缺少必要参数: deviceNumber" }

解决方案:
1. 检查是否提供了所有必需参数
2. 检查参数拼写是否正确
3. 参考API文档确认参数格式


🚦 限流规则

限流配置

限流对象 时间窗口 最大请求数 说明
单个设备 5秒 1次 /api/device/data 端点
全局设备 60秒 1次 /api/device/all 端点

限流示例

# 第1次请求成功
curl "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"
# 响应: 200 OK

# 第2次请求(间隔 < 5秒)失败
curl "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"
# 响应: 429 Too Many Requests
# "请求过于频繁,请在 4500ms 后再试"

# 等待5秒后再次请求成功
sleep 5
curl "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"
# 响应: 200 OK

避免限流的建议

  1. 批量查询: 使用 /api/device/all 一次获取所有设备
  2. 缓存数据: 本地存储数据,减少服务器查询
  3. 智能重试: 收到429时,按提示时间重试
  4. 分散请求: 查询不同设备而不是重复查询同一设备

❓ 常见问题

Q1: 映射格式和原始格式的区别是什么?

A:
- 原始格式: {"A": "50", "B": "25"}(需要查表才能理解)
- 映射格式: {"identifier": "A", "name": "脱水目标量", "value": "50"}(自解释)

推荐使用映射格式,便于理解和维护。

Q2: 如何定期获取最新数据?

A: 建议使用轮询+缓存的策略:

async function pollDeviceData(deviceNumber, interval = 10000) {
  setInterval(async () => {
    try {
      const response = await fetch(
        `http://localhost:8080/api/device/data?deviceNumber=${deviceNumber}&mapped=true`
      );
      const result = await response.json();
      
      if (result.code === 200) {
        console.log('最新数据:', result.data);
        // 在这里处理数据
      }
    } catch (error) {
      console.error('获取失败:', error);
    }
  }, interval);
}

// 每10秒获取一次数据
pollDeviceData('D001', 10000);

Q3: 如何处理网络连接失败?

A:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

def requests_retry_session(
    retries=3,
    backoff_factor=0.3,
    status_forcelist=(500, 502, 504),
    session=None,
):
    session = session or requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

# 使用
try:
    response = requests_retry_session().get('http://localhost:8080/api/health')
    print(response.json())
except requests.RequestException as e:
    print(f'连接失败: {e}')

Q4: 数据更新的实时性如何保证?

A:
- 设备数据通过Socket实时接收
- HTTP API返回的是缓存中的最新数据
- 数据延迟通常 < 1秒
- 可通过 timestamp 字段确认数据新鲜度

Q5: 支持CORS跨域请求吗?

A: 是的,系统默认支持CORS,允许来自任何域的跨域请求。

// 浏览器直接请求
fetch('http://localhost:8080/api/device/list')
  .then(r => r.json())
  .then(data => console.log(data));

Q6: API服务何时会不可用?

A:
- 服务故障(系统会自动记录日志)
- 网络问题
- 设备未连接

使用 /api/health 进行健康检查来判断服务状态。


📞 技术支持

如遇到任何问题,请提供以下信息联系技术支持:

  1. 错误信息截图
  2. 请求URL和参数
  3. 响应内容
  4. 系统日志文件
  5. 网络环境信息

📝 更新日志

v1.1.0 (2025-12-08)

  • ✅ 完整的属性映射支持(68个属性)
  • ✅ 单个和批量设备查询
  • ✅ 灵活的限流配置
  • ✅ CORS跨域支持
  • ✅ 详细的错误处理

v1.0.0 (2025-12-06)

  • 初始版本发布

最后更新: 2025-12-08
版本: v1.1.0
状态: 生产就绪 ✅