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 | 刪除事件 |