├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── vulnerability-report.md └── PULL_REQUEST_TEMPLATE.md ├── CONTRIBUTING.md ├── hash_password.js ├── api_docs └── portal.ubianet.com │ └── api │ ├── user │ ├── get_subscription_ios_device.json │ ├── event_calendar.json │ ├── families.json │ ├── get_cloud_video_url.json │ ├── cloud_list.json │ └── qry │ │ └── device │ │ └── device_services.json │ ├── v2 │ └── user │ │ ├── card4g-info.json │ │ └── device_list.json │ └── v3 │ └── login.json ├── package.json ├── LICENSE ├── login.js ├── README.md └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | api_docs/convert_headers.py 3 | user.json 4 | .env 5 | node_modules -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[Bug]" 5 | labels: bug 6 | assignees: JEMcats 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Enhancement]" 5 | labels: enhancement 6 | assignees: JEMcats 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/vulnerability-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Vulnerability report 3 | about: Report a vulnerability with our software here. 4 | title: "[Vulnerability]" 5 | labels: vulnerability 6 | assignees: JEMcats 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | To start make a fork of the dev branch. 4 | 5 | In your fork make the changes you would like make. 6 | 7 | Fill out the infromation for the pull request. 8 | 9 | When you are ready open your pull request. 10 | -------------------------------------------------------------------------------- /hash_password.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | var sha1 = require('js-sha1'); 3 | // HMAC SHA-1 with Base64 Encoding 4 | var hash = sha1.hmac.array('', process.env.password); 5 | var base_hash = Buffer.from(hash).toString('base64'); 6 | // Replace the last character with a comma 7 | const modifiedSignature = base_hash.replace(/.$/, ','); 8 | 9 | console.log('Hashed Password:', modifiedSignature); 10 | -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/get_subscription_ios_device.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/get_subscription_ios_device", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": {}, 12 | "response": { 13 | "code": 0, 14 | "data": { 15 | "subscription_ios_devices": [] 16 | }, 17 | "msg": "success" 18 | } 19 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ubox-camera-api", 3 | "version": "1.0.0", 4 | "description": "An API for connecting to uBox cameras.", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/JEMcats/ubox_camera_api.git" 12 | }, 13 | "keywords": [ 14 | "camera" 15 | ], 16 | "author": "JEMcats.Software", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/JEMcats/ubox_camera_api/issues" 20 | }, 21 | "homepage": "https://github.com/JEMcats/ubox_camera_api#readme", 22 | "dependencies": { 23 | "axios": "^1.7.7", 24 | "crypto": "^1.0.1", 25 | "dotenv": "^16.4.5", 26 | "fs": "^0.0.1-security", 27 | "http": "^0.0.1-security", 28 | "js-sha1": "^0.7.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/event_calendar.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/event_calendar", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "date": "2024-10", 13 | "time_diff": -18000, 14 | "summer_time": 1, 15 | "token": "Token Found In User Authentication", 16 | "device_uid": "Device Identifyer" 17 | }, 18 | "response": { 19 | "code": 0, 20 | "data": { 21 | "date": "2024-10", 22 | "time_diff": -18000, 23 | "days": [ 24 | 1, 25 | 5, 26 | 6, 27 | 7, 28 | 8, 29 | 9, 30 | 10 31 | ] 32 | }, 33 | "msg": "success" 34 | } 35 | } -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/families.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/families", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "token": "Token Found In User Authentication" 13 | }, 14 | "response": { 15 | "code": 0, 16 | "data": [ 17 | { 18 | "id": "Home Id", 19 | "name": "My home", 20 | "zone_id": 1, 21 | "country_code": "E2", 22 | "province": "New York", 23 | "city": "", 24 | "addr_1": "", 25 | "addr_2": "", 26 | "zip_code": "", 27 | "geo_info": {}, 28 | "lbs_code": "LBS code" 29 | } 30 | ], 31 | "msg": "success" 32 | } 33 | } -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/get_cloud_video_url.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/get_cloud_video_url", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "uid": "From Cloud List", 13 | "bucket_name": "From Cloud List", 14 | "cloud_provider": "From Cloud List", 15 | "image": "From Cloud List", 16 | "cloud_provider_int": "From Cloud List", 17 | "endpoint": "From Cloud List", 18 | "guid": "uuid in cloud list" 19 | }, 20 | "response": { 21 | "code": 0, 22 | "data": { 23 | "guid": "I am not sure where to find this", 24 | "video_url": "Url To The Video", 25 | "expired_second": 3600, 26 | "cloud_provider": "1_amazon" 27 | }, 28 | "msg": "success" 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 JEMcats.Software 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/v2/user/card4g-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/v2/user/card4g-info", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "token": "Token Found In User Authentication", 13 | "icc_id": "Sim Card ICC Id Of Your Device" 14 | }, 15 | "response": { 16 | "code": 0, 17 | "data": { 18 | "icc_id": "Sim Card ICC Id", 19 | "supplier": 6, 20 | "operator": "international", 21 | "data_total": 61439, 22 | "data_used": 7511, 23 | "data_left": 53928, 24 | "activated_at": "2023-11-23", 25 | "effective_at": "", 26 | "expired_at": "2024-12-29", 27 | "expired_at_utc": 1729339041, 28 | "state": 0, 29 | "batch": "A-230726", 30 | "status": "ACTIVATED_NAME", 31 | "flow_unlimit": false, 32 | "card_suit_id": "16", 33 | "only_free": false, 34 | "card_pkg_flow_status": "normal", 35 | "card_pkg_expire_status": "normal", 36 | "is_live_control": false, 37 | "live_keep_seconds": 0 38 | }, 39 | "msg": "success" 40 | } 41 | } -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Breaking Change 8 | 12 | 13 | ## Proposed Change 14 | 17 | 18 | ## Type of Change 19 | 24 | 25 | - [ ] Bugfix (non-breaking change that resolves an issue) 26 | - [ ] New Feature (which introduces functionality to an existing game or user interface) 27 | - [ ] Breaking Change (fix or feature that disrupts existing functionality) 28 | 29 | ## Additional Information 30 | 34 | 35 | - This PR addresses or resolves issue: 36 | - This PR is related to issue: 37 | 38 | ## Checklist 39 | 42 | 43 | - [ ] All code is thoroughly tested and functions locally. 44 | - [ ] There is minimal to no commented-out code in this PR. -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/cloud_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/cloud_list", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "summer_time": 1, 13 | "time_revised": true, 14 | "device_uid": [ 15 | "UID of the device" 16 | ], 17 | "token": "Token Found In User Authentication", 18 | "time_diff": -18000, 19 | "page": 1, 20 | "timestamp": [ 21 | 1728619200, 22 | 1728705664 23 | ] 24 | }, 25 | "response": { 26 | "code": 0, 27 | "data": { 28 | "cloud": 1, 29 | "count": { 30 | "total": 1, 31 | "pages": 1, 32 | "page": 1, 33 | "page_num": 20 34 | }, 35 | "list": [ 36 | { 37 | "battery": 100, 38 | "bucket_name": "ubiabox-us", 39 | "cloud": 1, 40 | "cp": 1, 41 | "device_uid": "UID of the device", 42 | "end_point": "AWS endpoint", 43 | "event_time": 1728596236, 44 | "id": "Cloud Recording Identifyer", 45 | "img": "Path to recording image", 46 | "realname": "", 47 | "status": 2, 48 | "type": 1, 49 | "uuid": "recording guid", 50 | "zone_id": "1", 51 | "cloud_image_url": "URL to cloud image", 52 | "event_type_message": "", 53 | "ai_flag": 0, 54 | "ai_result": {}, 55 | "user_tag": {} 56 | } 57 | ], 58 | "service": true, 59 | "time_diff": -18000 60 | }, 61 | "msg": "success" 62 | } 63 | } -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/v2/user/device_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/v2/user/device_list", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found When Signing In" 10 | }, 11 | "request": {}, 12 | "response": { 13 | "code": 0, 14 | "data": { 15 | "noti": [], 16 | "is_reach_limit": false, 17 | "firmware_ver": [ 18 | { 19 | "model_num": "879", 20 | "version": "879.0.13.36" 21 | }, 22 | { 23 | "model_num": "30", 24 | "version": "30.30.2.123" 25 | } 26 | ], 27 | "items": [ 28 | { 29 | "add_utc": 1697758855, 30 | "device_uid": "Device Uid", 31 | "device_name": "Device Name", 32 | "is_owner": true, 33 | "ps_name": "us", 34 | "zone_id": 1, 35 | "address_id": "2229460", 36 | "alexa_status": 0, 37 | "geo_info": {}, 38 | "ordering": { 39 | "index": 1 40 | } 41 | } 42 | ], 43 | "infos": [ 44 | { 45 | "dynamic_info": { 46 | "device_uid": "Device Uid", 47 | "online_state": "2", 48 | "battery": 100, 49 | "is_battery_charging": true, 50 | "signal": 1, 51 | "latest_active_utc": 1728657094 52 | }, 53 | "card_info": { 54 | "is_flag_import": true, 55 | "is_ubia_card": true, 56 | "is_lock": false, 57 | "icc_id": "Sim Card ICC Id", 58 | "icc_id_1": "Sim Card 1 ICC Id", 59 | "icc_id_2": "", 60 | "card_pkg_flow_status": "normal", 61 | "card_pkg_expire_status": "normal", 62 | "policy_suggest_sync_traffic": true 63 | }, 64 | "device_uid": "Device Uid", 65 | "device_name": "Device Name", 66 | "add_utc": 1697758855, 67 | "zone_id": 1, 68 | "address_id": "Address Id", 69 | "alexa_status": 0, 70 | "alexa_id": "", 71 | "is_ap_device": false, 72 | "device_user": "admin", 73 | "device_pwd": "device password", 74 | "has_cloud_storage": true, 75 | "is_cloud_storage_opened": true, 76 | "dev_func": 1063461, 77 | "is_dst_enabled": true, 78 | "location": "", 79 | "model_num": "879", 80 | "is_notice_enabled": true, 81 | "is_owner": true, 82 | "permissions": "", 83 | "product_id": "Product Identifyer", 84 | "ps_name": "us", 85 | "has_ticket_service": true, 86 | "time_diff": -18000, 87 | "cur_work_mode": 0, 88 | "want_work_mode": 0, 89 | "device_type": 0, 90 | "is_panoramic_device": false, 91 | "json_app_info": "{}", 92 | "geo_info": {}, 93 | "capabilities": [] 94 | } 95 | ] 96 | }, 97 | "msg": "success" 98 | } 99 | } -------------------------------------------------------------------------------- /login.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const axios = require('axios'); 3 | const https = require('https'); 4 | require('dotenv').config(); 5 | var sha1 = require('js-sha1'); 6 | // HMAC SHA-1 with Base64 Encoding 7 | function hmacSha1Base64(data) { 8 | if (process.env.debug_mode == 'false') { 9 | var hash = sha1.hmac.array('', data); 10 | var base_hash = Buffer.from(hash).toString('base64'); 11 | // Replace the last character with a comma 12 | const modifiedSignature = base_hash.replace(/.$/, ','); 13 | 14 | return modifiedSignature; 15 | } else { 16 | return data 17 | } 18 | } 19 | // Function to generate a random string for the device token 20 | function generateRandomString(length) { 21 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 22 | let result = ''; 23 | for (let i = 0; i < length; i++) { 24 | result += characters.charAt(Math.floor(Math.random() * characters.length)); 25 | } 26 | return result; 27 | } 28 | 29 | // Load email and password from environment variables 30 | const email = process.env.email; 31 | const password = hmacSha1Base64(process.env.password); 32 | if (process.env.debug_mode == 'true') { 33 | console.log('email',process.env.email) 34 | console.log('password',process.env.password) 35 | console.log(password) 36 | } 37 | // Check if email and password are defined 38 | if (!email || !password) { 39 | console.error("Error: Email or password not found in environment variables."); 40 | process.exit(1); 41 | } 42 | 43 | // Define the request headers 44 | const headers = { 45 | "method": "POST", 46 | "scheme": "https", 47 | "path": "/api/v3/login", 48 | "authority": "portal.ubianet.com", 49 | "accept": "*/*", 50 | "content-type": "application/json" 51 | }; 52 | 53 | // Define the request body 54 | const body = { 55 | "account": email, 56 | "password": password, 57 | "lang": "en", 58 | "app": "ubox", 59 | "device_token": generateRandomString(30), // Generate random 30-character string 60 | "app_version": "1.1.115", 61 | "brand": "iPhone15,2(18.1)", 62 | "device_type": 2 63 | }; 64 | 65 | 66 | // Create an axios instance that ignores SSL errors (only if necessary) 67 | const axiosInstance = axios.create({ 68 | httpsAgent: new https.Agent({ 69 | rejectUnauthorized: false // Allow SSL certificate bypass (use with caution) 70 | }) 71 | }); 72 | 73 | // Make the POST request 74 | axiosInstance.post('https://portal.ubianet.com/api/v3/login', body, { headers }) 75 | .then(response => { 76 | console.log("Response received:", response.data); // Log the full response 77 | 78 | const data = response.data; 79 | 80 | if (data.code === 0) { 81 | // Extract required information from the response 82 | const tokenInfo = { 83 | token: data.data.Token, 84 | token_secret: data.data.Token_secret, 85 | AWS_key: data.data.app_config.aws_cloud.key, 86 | AWS_secret: data.data.app_config.aws_cloud.secret, 87 | device_token: data.data.device_token 88 | }; 89 | 90 | // Save the extracted information to 'user.json' 91 | fs.writeFileSync('user.json', JSON.stringify(tokenInfo, null, 4)); 92 | console.log("Token information saved to user.json"); 93 | } else { 94 | console.error("Login failed:", data.msg); // Log error message from API 95 | } 96 | }) 97 | .catch(error => { 98 | // Handle and log errors during the API request 99 | if (error.response) { 100 | console.error("Error response data:", error.response.data); 101 | console.error("Status code:", error.response.status); 102 | } else if (error.request) { 103 | console.error("No response received:", error.request); 104 | } else { 105 | console.error("Request error:", error.message); 106 | } 107 | }); -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/user/qry/device/device_services.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/user/qry/device/device_services", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json", 9 | "x-ubia-auth-usertoken": "Token Found In User Authentication" 10 | }, 11 | "request": { 12 | "token": "Token Found In User Authentication", 13 | "uids": [ 14 | "Uids for the cameras" 15 | ] 16 | }, 17 | "response": { 18 | "code": 0, 19 | "data": { 20 | "is_reach_limit": false, 21 | "items": [ 22 | { 23 | "uid": "Camera's Uid", 24 | "has_trial": false, 25 | "services": { 26 | "Alexa": { 27 | "auto_subscribe": [], 28 | "is_auto_subscribe": false, 29 | "note": "", 30 | "service_end": "", 31 | "service_ident": "", 32 | "service_package": "", 33 | "service_start": "", 34 | "status": 0, 35 | "exist": false, 36 | "is_lifetime_free_bird": false, 37 | "has_trial": false, 38 | "is_prepaid": false 39 | }, 40 | "FaceID": {}, 41 | "Ucloud": { 42 | "auto_subscribe": [ 43 | { 44 | "channel": "Method to pay with", 45 | "product_id": "merchant.cn.ubia.ubox.30rwcloud360", 46 | "service_ident": "Unknown", 47 | "state": "Unknown", 48 | "is_owner": false, 49 | "cycle_month": 12, 50 | "original_transaction_id": "Transaction id " 51 | } 52 | ], 53 | "is_auto_subscribe": true, 54 | "note": "", 55 | "service_end": "End of subscription", 56 | "service_ident": "Unknown", 57 | "service_package": "", 58 | "service_start": "Start of subscription", 59 | "status": 1, 60 | "exist": true, 61 | "is_lifetime_free_bird": false, 62 | "has_trial": false, 63 | "is_prepaid": false 64 | }, 65 | "BirdDetection": { 66 | "auto_subscribe": [], 67 | "is_auto_subscribe": false, 68 | "note": "", 69 | "service_end": "", 70 | "service_ident": "", 71 | "service_package": "", 72 | "service_start": "", 73 | "status": 0, 74 | "exist": false, 75 | "is_lifetime_free_bird": false, 76 | "has_trial": false, 77 | "is_prepaid": false 78 | }, 79 | "AnimalDetection": { 80 | "auto_subscribe": [], 81 | "is_auto_subscribe": false, 82 | "note": "", 83 | "service_end": "", 84 | "service_ident": "", 85 | "service_package": "", 86 | "service_start": "", 87 | "status": 0, 88 | "exist": false, 89 | "is_lifetime_free_bird": false, 90 | "has_trial": false, 91 | "is_prepaid": false 92 | } 93 | } 94 | } 95 | ] 96 | }, 97 | "msg": "success" 98 | } 99 | } -------------------------------------------------------------------------------- /api_docs/portal.ubianet.com/api/v3/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": { 3 | "method": "POST", 4 | "scheme": "https", 5 | "path": "/api/v3/login", 6 | "authority": "portal.ubianet.com", 7 | "accept": "*/*", 8 | "content-type": "application/json" 9 | }, 10 | "request": { 11 | "account": "Your Email", 12 | "password": "Your Hashed Password", 13 | "lang": "en", 14 | "app": "ubox", 15 | "device_token": "A Random Identifyer", 16 | "app_version": "1.1.115", 17 | "brand": "iPhone15,2(18.1)", 18 | "device_type": 2 19 | }, 20 | "response": { 21 | "code": 0, 22 | "data": { 23 | "account": "Your Email", 24 | "app_id": 1, 25 | "app_version": "1.1.115", 26 | "device_token": "A Random Identifyer", 27 | "device_type": 2, 28 | "email_auth": 1, 29 | "extra": { 30 | "default_clarity": 0, 31 | "display_name": "", 32 | "live_slient": 1, 33 | "notice_ring": 1, 34 | "notice_shock": 1, 35 | "play_back_slient": 0 36 | }, 37 | "kuid": "a uid", 38 | "lang": "en", 39 | "lbs_code": "2D", 40 | "login_node": "us", 41 | "mobile_brand": "iPhone15,2(18.1)", 42 | "notice_type": 2, 43 | "union_id": "", 44 | "uuid": "Your account uuid", 45 | "wechat_bind": false, 46 | "avatar_url": "A url to your account image", 47 | "open_auth_binding": {}, 48 | "notices": [], 49 | "Token": "A token for accessing endpoints in the API", 50 | "Token_secret": "A token secret for accessing endpoints in the API", 51 | "app_config": { 52 | "ai": { 53 | "key": "no_more_use", 54 | "secret": "no_more_use" 55 | }, 56 | "android_private_config": { 57 | "ucon": { 58 | "API Keys":"API Keys" 59 | }, 60 | "ybox": { 61 | "API Keys":"API Keys" 62 | } 63 | }, 64 | "aws_cloud": { 65 | "key": "The AWS key for ubox", 66 | "secret": "The AWS secret for ubox" 67 | }, 68 | "bird_wiki_url": "https://{{lang}}wikipedia.org/wiki/{{bird_name}}", 69 | "cloud": { 70 | "key": "The key for ubox", 71 | "secret": "The key for ubox" 72 | }, 73 | "cnpay": [ 74 | "wechat", 75 | "alipay" 76 | ], 77 | "facebook_binding_cmd": "sub", 78 | "facebook_icamplus_profile_id": "A profile id for facebook", 79 | "feature_show_tip_4g_charge": true, 80 | "feature_show_tip_4g_charge_list": [ 81 | "icamplus", 82 | "ubox", 83 | "soliomplus", 84 | "ybox", 85 | "xega" 86 | ], 87 | "firmware_ver_check": { 88 | "query_period_sec": 86400, 89 | "version_range": [ 90 | "Some Values I Don't Understand" 91 | ] 92 | }, 93 | "freq_pir_battery": { 94 | "info": 50, 95 | "warn": 30 96 | }, 97 | "ios_private_config": { 98 | "ucon": { 99 | "API Keys":"API Keys" 100 | }, 101 | "ybox": { 102 | "API Keys":"API Keys" 103 | } 104 | }, 105 | "min_req_body_compress_bytes": 1500, 106 | "mixed_purchase_limit_days": 3, 107 | "not_appraisal_alert": false, 108 | "setting_online_time_over_new_tip_sec": 300, 109 | "tencent_cloud": { 110 | "API Keys":"API Keys" 111 | } 112 | }, 113 | "hw_token": "", 114 | "regid_jg": "", 115 | "regid_vivo": "", 116 | "regid_xm": "", 117 | "linked_users": [ 118 | { 119 | "nick_name": "Linked Username", 120 | "source": "ubia" 121 | } 122 | ], 123 | "svcloc": { 124 | "api_dn": "https://portal.ubianet.com", 125 | "evt_dn": "https://log.ubianet.com", 126 | "pay": "https://portal-us.ubianet.com/py_biz/us_channel_po.html", 127 | "pay_sub": "" 128 | } 129 | }, 130 | "msg": "success" 131 | } 132 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | uBox Camera API is made to take your existing uBox cameras and get infromation from them. 4 | 5 | There is no official uBox Camera API documentation so this is an unofficial API. 6 | 7 | We are NOT affiliated, associated, authorized, endorsed by, or in any way officially connected with UBIA TECHNOLOGIES CO. The official Ubia website can be found at [ubianet.com](https://www.ubianet.com). 8 | 9 | # Features 10 | 11 | | Features | Status | 12 | | -------- | ------- | 13 | | List Of Devices | Available | 14 | | Sim Card Info | Available | 15 | | Cloud Recording List | Available | 16 | | Events Calendar | Available | 17 | | Get Cloud Video Url | Available | 18 | | Get Subscribed iOS Devices | Available | 19 | | uBox Camera Stream To RTSP | Upcoming | 20 | | Web Interface | Upcoming | 21 | | Portal.ubianet.com API Documentation | Upcoming | 22 | 23 | # Install 24 | 25 | Choose the correct install for your system 26 | 27 | ## MacOS 28 | Install Homebrew 29 | ``` 30 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 31 | ``` 32 | 33 | Install NPM and Git 34 | ``` 35 | $ brew install npm git 36 | ``` 37 | 38 | Clone Repo 39 | ``` 40 | $ git clone https://github.com/JEMcats/ubox_camera_api.git 41 | ``` 42 | 43 | Navigate To The Cloned Repo 44 | ``` 45 | $ cd ubox_camera_api 46 | ``` 47 | 48 | Install The Required Dependiences 49 | ``` 50 | $ npm install 51 | ``` 52 | The API is now setup and ready to be used. 53 | 54 | ## Linux 55 | 56 | Choose the install for your Linux Distribution 57 | 58 | ### Ubuntu 59 | 60 | Install NPM And Git 61 | ``` 62 | $ sudo apt update 63 | sudo apt install npm git 64 | ``` 65 | 66 | Clone The Repo 67 | ``` 68 | $ git clone https://github.com/JEMcats/ubox_camera_api.git 69 | ``` 70 | 71 | Navigate To The Cloned Repo 72 | ``` 73 | $ cd ubox_camera_api 74 | ``` 75 | 76 | Install The Required Dependiences 77 | ``` 78 | $ npm install 79 | ``` 80 | The API is now setup and ready to be used. 81 | 82 | ### Other Distributions 83 | 84 | If there is another Linux distibution you would like added feel free to open a pull request. 85 | 86 | ## Windows 87 | 88 | As of now we do not have an install guide for Windows, if you would you would like this added feel free to open a pull request. 89 | 90 | # Usage 91 | 92 | Navigate to the directory you have cloned from this repo. If you have not cloned the repository yet please follow the installation directions. 93 | 94 | ## Login 95 | 96 | To login to the API create a .env file and write the following 97 | ``` 98 | email=your_email 99 | password=your_password 100 | debug_mode=false 101 | server_port=8020 102 | ``` 103 | Once you have completed that run the following command 104 | ``` 105 | $ node login.js 106 | ``` 107 | This will generate a users.json file which will contain your token and other infromation. 108 | 109 | If the uBox Camera API ever stops working it is most likely that your login has expired, please run ``` login.js ``` again. 110 | 111 | ## Hosting API 112 | 113 | Onece you have run ``` login.js ```, to use the ubox-camera-api run the following command 114 | ``` 115 | $ node server.js 116 | ``` 117 | if you get an error this is probably because you have not run ``` login.js ``` try running ``` login.js ``` again. 118 | 119 | Once your server has started you will see 120 | ``` 121 | Server running on port 8020 122 | ``` 123 | in your console. 124 | 125 | If you would like to change the port, modify the ```server_port``` varible in the env file 126 | 127 | ## API usage 128 | 129 | The following endpoints can be accessed at ```localhost:8020```, if you change your port the API will be at ```localhost:YOUR_PORT```. 130 | 131 | | Endpoint | Method | 132 | | -------- | ------- | 133 | | /api/v2/user/device_list | GET | 134 | | /api/user/families | GET| 135 | | /api/user/get_subscription_ios_device | GET | 136 | | /api/v2/user/card4g-info | POST | 137 | | /api/user/cloud_list | POST | 138 | | /api/user/event_calendar | POST | 139 | | /api/user/get_cloud_video_url | POST | 140 | | /api/user/qry/device/device_services | POST | 141 | 142 | # Using The Password Hashing Tool 143 | 144 | To hash you password to for using the raw login endpoint [```portal.ubianet.com/api/v3/login```](https://github.com/JEMcats/ubox_camera_api/tree/main/api_docs/portal.ubianet.com/api/v3/login.json), you will need to hash your password with ```hash_password.js```. 145 | 146 | To start make sure that the ```password=YOUR_PASSWORD``` value is set in your ```.env``` file. 147 | 148 | Run this on the command line: 149 | ``` 150 | $ node hash_password.js 151 | ``` 152 | 153 | Wait for the console to say 154 | ``` 155 | Hashed Password: HASHEDPASSWORD, 156 | ``` 157 | 158 | Copy the hashed password and use it as your password in the POST Request JSON Body. 159 | # Contributing 160 | 161 | To start make a fork of the dev branch. 162 | 163 | In your fork make the changes you would like make. 164 | 165 | Fill out the infromation for the pull request. 166 | 167 | When you are ready open your pull request. 168 | 169 | # Troubleshooting 170 | Here are some troubleshooting steps to take before making a Github issue. 171 | 172 | ## ```login.js``` 173 | Here is some troubleshooting for ```login.js``` 174 | ### Reset Your Password Without Special Charectors 175 | In the uBox app reset your password and try login in with ```login.js``` again. 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const fs = require('fs'); 3 | const axios = require('axios'); 4 | require('dotenv').config(); 5 | 6 | let port = process.env.server_port; 7 | 8 | const userdata = JSON.parse(fs.readFileSync('user.json')); 9 | 10 | async function makeUbiaRequest(body, url) { 11 | // Define the request headers 12 | const headers = { 13 | "method": "POST", 14 | "scheme": "https", 15 | "path": url, 16 | "authority": "portal.ubianet.com", 17 | "accept": "*/*", 18 | "content-type": "application/json", 19 | "x-ubia-auth-usertoken": userdata.token 20 | }; 21 | 22 | try { 23 | const response = await axios.post(`https://portal.ubianet.com${url}`, body, { headers }); 24 | const data = response.data; 25 | 26 | if (data.code === 0) { 27 | return { "code": response.status, "msg": data.msg, "data": data }; 28 | } else { 29 | console.error("Request Failed", data.msg); // Log error message from API 30 | return { "code": response.status, "msg": data.msg }; 31 | } 32 | } catch (error) { 33 | // Handle and log errors during the API request 34 | if (error.response) { 35 | console.error("Error response data:", error.response.data); 36 | console.error("Status code:", error.response.status); 37 | return { "code": error.response.status, "msg": error.response.data }; 38 | } else if (error.request) { 39 | console.error("No response received:", error.request); 40 | return { "code": 500, "msg": 'Unknown Error' }; 41 | } else { 42 | console.error("Request error:", error.message); 43 | return { "code": 500, "msg": error.message }; 44 | } 45 | } 46 | } 47 | 48 | async function GETrequest(req, res) { 49 | switch (req.url) { 50 | case '/api/v2/user/device_list': 51 | const ubia_response_device_list = await makeUbiaRequest({}, req.url); 52 | res.writeHead(ubia_response_device_list.code, { 'Content-Type': 'application/json' }); 53 | res.write(JSON.stringify(ubia_response_device_list.data)); // Ensure JSON data is stringified 54 | res.end(); 55 | break; 56 | case '/api/user/families': 57 | const ubia_response_families = await makeUbiaRequest({"token":userdata.token}, req.url); 58 | res.writeHead(ubia_response_families.code, { 'Content-Type': 'application/json' }); 59 | res.write(JSON.stringify(ubia_response_families.data)); // Ensure JSON data is stringified 60 | res.end(); 61 | break; 62 | case '/api/user/get_subscription_ios_device': 63 | const ubia_response_get_subscription_ios_device = await makeUbiaRequest({}, req.url); 64 | res.writeHead(ubia_response_get_subscription_ios_device.code, { 'Content-Type': 'application/json' }); 65 | res.write(JSON.stringify(ubia_response_get_subscription_ios_device.data)); // Ensure JSON data is stringified 66 | res.end(); 67 | break; 68 | default: 69 | res.writeHead(404, { 'Content-Type': 'text/html' }); 70 | res.write('Not Found'); 71 | res.end(); 72 | break; 73 | } 74 | } 75 | 76 | async function POSTrequest(req, res) { 77 | let body = ''; 78 | 79 | // Accumulate data chunks in the body string 80 | req.on('data', chunk => { 81 | body += chunk.toString(); // Convert Buffer to string 82 | }); 83 | 84 | // When the body is fully received, proceed 85 | req.on('end', async () => { 86 | // Try to parse the JSON body 87 | try { 88 | const parsedBody = JSON.parse(body); 89 | parsedBody.token = userdata.token; // Attach the token 90 | 91 | // Handle different POST routes 92 | switch (req.url) { 93 | case '/api/user/qry/device/device_services': 94 | const ubia_response_device_services = await makeUbiaRequest(parsedBody, req.url); 95 | res.writeHead(ubia_response_device_services.code, { 'Content-Type': 'application/json' }); 96 | res.write(JSON.stringify(ubia_response_device_services.data)); 97 | res.end(); 98 | break; 99 | 100 | case '/api/user/cloud_list': 101 | const ubia_response_cloud_list = await makeUbiaRequest(parsedBody, req.url); 102 | res.writeHead(ubia_response_cloud_list.code, { 'Content-Type': 'application/json' }); 103 | res.write(JSON.stringify(ubia_response_cloud_list.data)); 104 | res.end(); 105 | break; 106 | 107 | case '/api/user/event_calendar': 108 | const ubia_response_event_calendar = await makeUbiaRequest(parsedBody, req.url); 109 | res.writeHead(ubia_response_event_calendar.code, { 'Content-Type': 'application/json' }); 110 | res.write(JSON.stringify(ubia_response_event_calendar.data)); 111 | res.end(); 112 | break; 113 | 114 | case '/api/user/get_cloud_video_url': 115 | const ubia_response_get_cloud_video_url = await makeUbiaRequest(parsedBody, req.url); 116 | res.writeHead(ubia_response_get_cloud_video_url.code, { 'Content-Type': 'application/json' }); 117 | res.write(JSON.stringify(ubia_response_get_cloud_video_url.data)); 118 | res.end(); 119 | break; 120 | 121 | case '/api/v2/user/card4g-info': 122 | const ubia_response_card4g_info = await makeUbiaRequest(parsedBody, req.url); 123 | res.writeHead(ubia_response_card4g_info.code, { 'Content-Type': 'application/json' }); 124 | res.write(JSON.stringify(ubia_response_card4g_info.data)); 125 | res.end(); 126 | break; 127 | 128 | default: 129 | res.writeHead(404, { 'Content-Type': 'text/html' }); 130 | res.write('Not Found'); 131 | res.end(); 132 | break; 133 | } 134 | 135 | } catch (error) { 136 | res.writeHead(400, { 'Content-Type': 'application/json' }); 137 | res.write(JSON.stringify({ error: 'Invalid JSON' })); 138 | res.end(); 139 | } 140 | }); 141 | } 142 | 143 | // Create a server object: 144 | http.createServer(function (req, res) { 145 | switch (req.method) { 146 | case 'GET': 147 | GETrequest(req, res); 148 | break; 149 | case 'POST': 150 | console.log(req.body) 151 | POSTrequest(req, res); 152 | break; 153 | default: 154 | break; 155 | } 156 | }).listen(port); // The server object listens on port 8020 157 | console.log(`Server running on port ${port}`); --------------------------------------------------------------------------------