Foreaider RESTful API
===
[TOC]
## Server
* Dashboard : http://iot.foreaider.xtaiwan.org
* Restful API : http://api.foreaider.xtaiwan.org
* MQTT Server : http://api.foreaider.xtaiwan.org
---
## 共用說明
### 驗證金鑰
所有 API 都需要傳入 `key` 參數進行身份驗證:
```
key: "3a9afa4abefbaa81e38c4f60ab641afce4d7ce4d3d5c3f87df6fa246038f1231"
```
### 帳號層級 (level)
| 層級 | 說明 |
|------|------|
| `admin` | 管理員 |
| `agent` | 代理商 |
| `user` | 一般使用者 (預設) |
### 通用錯誤回應
| status | 說明 |
|--------|------|
| `Error Key` | 驗證金鑰錯誤 |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
---
## Account API
### Create Account
建立新帳號
**POST** `/createAccount`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"email": "xxx@xxx.xxx",
"level": "user",
"vendor": "fa",
"devices": ["ForeAider01", "ForeAider02"],
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| account | Y | 帳號名稱 |
| password | Y | 密碼 |
| email | N | 電子郵件 |
| level | N | 權限層級,預設 `user` |
| vendor | N | 廠商識別 |
| devices | N | 設備陣列,預設空陣列 |
| key | Y | 驗證金鑰 |
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 建立成功 |
| `Duplicate` | 帳號已存在 |
| `Error Key` | 驗證金鑰錯誤 |
| `Create Account DB Error` | 資料庫錯誤 |
---
### Delete Account
刪除帳號
**POST** `/deleteAccount`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 刪除成功 |
| `Account Not Found` | 帳號不存在 |
| `Delete Account Error` | 密碼錯誤 |
| `Delete Account DB Error` | 資料庫錯誤 |
---
### Get Account Info
取得帳號資訊
**POST** `/getAccountInfo`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK",
"email": "xxx@xxx.xxx",
"level": "user",
"vendor": "fa",
"devices": ["deviceId1", "deviceId2"]
}
```
| status | 說明 |
|--------|------|
| `OK` | 查詢成功 |
| `Account Not Found` | 帳號不存在 |
| `Get Account Info Error` | 密碼錯誤 |
---
### Update Account Info
更新帳號資訊
**POST** `/updateAccountInfo`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"email": "new@email.com",
"devices": ["device1", "device2"],
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 更新成功 |
| `Account Not Found` | 帳號不存在 |
| `Update Account Error` | 密碼錯誤 |
| `Update Account DB Error` | 資料庫錯誤 |
---
### Forgot Password
忘記密碼,寄送重設連結至信箱
**POST** `/forgotPassword`
#### Request
```json
{
"account": "帳號名稱",
"email": "xxx@xxx.xxx",
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| account | N | 帳號名稱 (account 或 email 擇一) |
| email | Y | 電子郵件 |
| key | Y | 驗證金鑰 |
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 已寄送重設連結 |
| `Account Not Found` | 帳號或信箱不存在 |
| `Account or Email can not be empty` | 信箱為空 |
---
### Change Password (via Token)
透過 Token 變更密碼 (配合 forgotPassword 使用)
**POST** `/changePassword`
#### Request
```json
{
"token": "加密的重設 Token"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 變更成功 |
| `Invalid` | Token 無效或過期 |
| `Account Not Found` | 帳號不存在 |
---
### Change Password (Direct)
直接變更密碼 (需原密碼驗證)
**POST** `/change_password`
#### Request
```json
{
"account": "帳號名稱",
"password": "原密碼",
"newPassword": "新密碼",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 變更成功 |
| `Account not found` | 帳號不存在 |
| `account / password / newPassword can not be empty` | 參數不完整 |
---
## Device API
### Create Device
建立新設備並綁定到帳號
**POST** `/createDevice`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"vendor": "fa",
"device": "deviceId1",
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| account | Y | 帳號名稱 |
| password | Y | 密碼 |
| vendor | Y | 廠商識別 |
| device | Y | 設備 UUID |
| key | Y | 驗證金鑰 |
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 建立成功 |
| `Vendor Not Found` | 未提供廠商 |
| `Device Not Found` | 未提供設備 ID |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
| `Update Account DB Error` | 資料庫錯誤 |
**說明**: 新建設備預設類型為 `ESP`,會自動初始化 bedInfo 結構。
---
### Delete Device
刪除設備
**POST** `/deleteDevice`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"device": "deviceId1",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 刪除成功 |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
| `Device Not Found` | 設備不存在 |
| `Delete Device DB Error` | 資料庫錯誤 |
---
### Get Device List
取得所有設備列表
**POST** `/getDeviceList`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK",
"devices": [
{
"uuid": "deviceId1",
"vendor": "fa",
"deviceType": "ESP",
"account": ["user1", "user2"],
"bedInfo": {
"title": "床位名稱",
"info": "備註",
"alert": { ... }
}
}
]
}
```
| status | 說明 |
|--------|------|
| `OK` | 查詢成功 |
| `Account Not Found` | 帳號不存在 |
| `Invalid Password` | 密碼錯誤 |
| `No Devices Found` | 無設備資料 |
---
### Get Device Info
取得單一設備詳細資訊
**POST** `/getDeviceInfo`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"device": "deviceId1",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK",
"uuid": "deviceId1",
"vendor": "fa",
"deviceType": "ESP",
"account": ["user1"],
"bedInfo": {
"title": "床位名稱",
"info": "備註資訊",
"alert": {
"enabled": "false",
"start": "09:00",
"end": "18:00",
"heartStart": 40,
"heartEnd": 90,
"breathStart": 5,
"breathEnd": 15,
"delay": 3
}
}
}
```
---
### Update Device Info
更新設備資訊
**POST** `/updateDeviceInfo`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"device": "deviceId1",
"bedInfo": {
"title": "新床位名稱",
"info": "新備註",
"alert": {
"enabled": "true",
"start": "08:00",
"end": "20:00",
"heartStart": 50,
"heartEnd": 100,
"breathStart": 8,
"breathEnd": 20,
"delay": 5
}
},
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 更新成功 |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
| `Device Not Found` | 設備不存在 |
| `Update Device DB Error` | 資料庫錯誤 |
**注意**: `account` 和 `password` 欄位不會被更新到設備資料中。
---
### Add Account Device
將現有設備綁定到帳號
**POST** `/addAccountDevice`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"device": "deviceId1",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 綁定成功 |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
| `Account can not be empty` | 帳號為空 |
| `Device can not be empty` | 設備為空 |
| `Device doesn't exist` | 設備不存在 |
| `Device already in this account` | 設備已綁定此帳號 |
| `Update Account DB Error` | 資料庫錯誤 |
---
### Delete Account Device
從帳號解除設備綁定
**POST** `/deleteAccountDevice`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"device": "deviceId1",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 解除綁定成功 |
| `Account Not Found` | 帳號不存在或密碼錯誤 |
| `Device doesn't exist in this account` | 此帳號未綁定該設備 |
| `Update Account DB Error` | 資料庫錯誤 |
**注意**: 如果設備不再綁定任何帳號,設備資料會被自動刪除。
---
## Data API
### Get Current Data
取得設備即時資料
**POST** `/getCurrentData`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"devices": ["deviceId1", "deviceId2"],
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK",
"deviceId1": {
"vendor": "fa",
"status": "onbed",
"heart": 72,
"breath": 16,
"hg": 98,
"on": 1,
"wf": [],
"time": "1704067200000"
},
"deviceId2": "No Data"
}
```
#### 設備資料欄位說明
| 欄位 | 說明 |
|------|------|
| vendor | 廠商識別 |
| status | 狀態 (onbed/offbed/...) |
| heart | 心率 (次/分) |
| breath | 呼吸率 (次/分) |
| hg | 血紅素數值 |
| on | 開機狀態 (1/0) |
| wf | 波形數據 |
| time | 時間戳記 (毫秒) |
| status | 說明 |
|--------|------|
| `OK` | 查詢成功 |
| `Account Not Found` | 帳號不存在 |
| `No devices` | 未提供設備列表 |
| `Get Current Data Error` | 密碼錯誤或系統忙碌 |
---
### Get Historical Data
取得歷史資料
**POST** `/getHistoricalData`
#### Request
```json
{
"account": "帳號名稱",
"password": "密碼",
"devices": "deviceId1",
"from": "20220510000000",
"end": "20220510120000",
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| account | Y | 帳號名稱 |
| password | Y | 密碼 |
| devices | Y | 設備 UUID (單一字串) |
| from | Y | 起始時間,格式 `YYYYMMDDHHmmss`,`-1` 代表最早 |
| end | Y | 結束時間,格式 `YYYYMMDDHHmmss`,`-1` 代表現在 |
| key | Y | 驗證金鑰 |
#### Response
```json
{
"status": "OK",
"data": [
{
"vendor": "fa",
"status": "onbed",
"heart": 72,
"breath": 16,
"hg": 98,
"on": 1,
"wf": [],
"time": "1704067200000"
},
{
"vendor": "fa",
"status": "offbed",
"heart": 0,
"breath": 0,
"hg": 0,
"on": 1,
"wf": [],
"time": "1704067260000"
}
]
}
```
| status | 說明 |
|--------|------|
| `OK` | 查詢成功 |
| `Account Not Found` | 帳號不存在 |
| `No devices` | 未提供設備 |
| `Time format or time range error` | 時間格式錯誤 |
| `Get Historical Data Error` | 密碼錯誤 |
---
## Event API
### Insert Event
新增事件
**POST** `/insertEvent`
#### Request
```json
{
"id": "event001",
"type": "alert",
"message": "心率異常",
"deviceId": "deviceId1",
"timestamp": 1704067200000,
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| id | Y | 事件 ID (唯一) |
| key | Y | 驗證金鑰 |
| ... | N | 其他自訂欄位 |
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 新增成功 |
| `Need to define id` | 未提供 id |
| `ID Duplicated !` | ID 已存在 |
---
### Find Event
查詢事件
**POST** `/findEvent`
#### Request
```json
{
"keyword": "{type:'alert'}",
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| keyword | Y | 查詢條件 (MongoDB 格式字串) |
| key | Y | 驗證金鑰 |
#### keyword 範例
```javascript
// 查詢所有 alert 類型
"{type:'alert'}"
// 查詢特定設備
"{deviceId:'deviceId1'}"
// 查詢所有事件
"{}"
```
#### Response
```json
{
"status": "OK",
"data": [
{
"id": "event001",
"type": "alert",
"message": "心率異常",
"deviceId": "deviceId1",
"timestamp": 1704067200000
}
]
}
```
| status | 說明 |
|--------|------|
| `OK` | 查詢成功 |
| `Need to define keyword` | 未提供 keyword |
---
### Update Event
更新事件
**POST** `/updateEvent`
#### Request
```json
{
"id": "event001",
"message": "更新後的訊息",
"resolved": true,
"key": "KEY"
}
```
| 參數 | 必填 | 說明 |
|------|------|------|
| id | Y | 事件 ID |
| key | Y | 驗證金鑰 |
| ... | N | 要更新的欄位 |
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 更新成功 |
| `Need to fill id` | 未提供 id |
| `id not found !` | ID 不存在 |
---
### Delete Event
刪除事件
**POST** `/deleteEvent`
#### Request
```json
{
"id": "event001",
"key": "KEY"
}
```
#### Response
```json
{
"status": "OK"
}
```
| status | 說明 |
|--------|------|
| `OK` | 刪除成功 |
| `Need to fill id` | 未提供 id |
| `id not found` | ID 不存在 |
---
## 資料結構說明
### bedInfo 結構
```json
{
"title": "床位名稱",
"info": "備註資訊",
"alert": {
"enabled": "true/false",
"start": "09:00",
"end": "18:00",
"heartStart": 40,
"heartEnd": 90,
"breathStart": 5,
"breathEnd": 15,
"delay": 3
}
}
```
| 欄位 | 說明 |
|------|------|
| title | 床位顯示名稱 |
| info | 備註資訊 |
| alert.enabled | 是否啟用警報 |
| alert.start | 警報開始時間 |
| alert.end | 警報結束時間 |
| alert.heartStart | 心率下限 |
| alert.heartEnd | 心率上限 |
| alert.breathStart | 呼吸率下限 |
| alert.breathEnd | 呼吸率上限 |
| alert.delay | 警報延遲 (分鐘) |
---
## NodeJS Example
時間 GMT +8
```javascript
let kkey = '3a9afa4abefbaa81e38c4f60ab641afce4d7ce4d3d5c3f87df6fa246038f1231';
let client = primer.HttpClient({
host: 'api.foreaider.xtaiwan.org',
path: '/createAccount',
port: 80,
secure: false,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: {
account: 'Willman',
password: '123456',
key: kkey
},
}, (err, res, rbody) => {
if (err)
console.log(err.message);
try {
console.log(rbody.toString());
} catch (e) {}
});
```
---
## API 總覽
| 類別 | API | 方法 | 說明 |
|------|-----|------|------|
| Account | `/createAccount` | POST | 建立帳號 |
| Account | `/deleteAccount` | POST | 刪除帳號 |
| Account | `/getAccountInfo` | POST | 取得帳號資訊 |
| Account | `/updateAccountInfo` | POST | 更新帳號資訊 |
| Account | `/forgotPassword` | POST | 忘記密碼 |
| Account | `/changePassword` | POST | Token 變更密碼 |
| Account | `/change_password` | POST | 直接變更密碼 |
| Device | `/createDevice` | POST | 建立設備 |
| Device | `/deleteDevice` | POST | 刪除設備 |
| Device | `/getDeviceList` | POST | 取得設備列表 |
| Device | `/getDeviceInfo` | POST | 取得設備資訊 |
| Device | `/updateDeviceInfo` | POST | 更新設備資訊 |
| Device | `/addAccountDevice` | POST | 綁定設備到帳號 |
| Device | `/deleteAccountDevice` | POST | 解除設備綁定 |
| Data | `/getCurrentData` | POST | 取得即時資料 |
| Data | `/getHistoricalData` | POST | 取得歷史資料 |
| Event | `/insertEvent` | POST | 新增事件 |
| Event | `/findEvent` | POST | 查詢事件 |
| Event | `/updateEvent` | POST | 更新事件 |
| Event | `/deleteEvent` | POST | 刪除事件 |