# 透析机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. **查询设备数据** - 获取需要的设备数据 ### 测试连接 ```bash # 健康检查 - 验证服务可用性 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" # 获取映射格式数据(推荐) curl "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true" ``` **响应示例(映射格式)**: ```json { "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 示例 ```bash # 基础请求 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 示例 ```javascript // 使用 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 示例 ```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 示例 ```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 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")); }); } } } ``` --- ## 📊 响应格式 ### 成功响应 ```json { "code": 200, "message": "success", "data": { // 实际数据内容 } } ``` ### 错误响应 ```json { "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 端点 | ### 限流示例 ```bash # 第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**: 建议使用轮询+缓存的策略: ```javascript 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**: ```python 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,允许来自任何域的跨域请求。 ```javascript // 浏览器直接请求 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 **状态**: 生产就绪 ✅