11 KiB
AC Infinity API Reference
This document provides technical details about the AC Infinity API integration used by this Homebridge plugin. It covers the API endpoints, payload formats, and controller-specific approaches discovered through reverse engineering.
API Base URL
http://www.acinfinityserver.com
Authentication
The API uses simple token-based authentication:
- Login with email/password to get a user token
- Include token in subsequent requests via the
tokenheader
Login Request
POST /api/user/appUserLogin
Content-Type: application/x-www-form-urlencoded
appEmail=user@example.com&appPasswordl=password123
Note: The API parameter is appPasswordl (with 'l') - this is intentional and matches the official API.
Password Limitation: API only accepts first 25 characters of password.
Login Response
{
"msg": "success.",
"code": 200,
"data": {
"appId": "1234567890123456789",
"nickName": "user@example.com",
"appEmail": "user@example.com"
}
}
The appId is used as the authentication token for subsequent requests.
Core Endpoints
Get Device List
POST /api/user/devInfoListAll
Content-Type: application/x-www-form-urlencoded
userId=1234567890123456789
Headers:
token: 1234567890123456789
phoneType: 1
appVersion: 1.9.7
Get Device Mode Settings
POST /api/dev/getdevModeSettingList
Content-Type: application/x-www-form-urlencoded
devId=1234567890123456789&port=2
Headers:
token: 1234567890123456789
phoneType: 1
appVersion: 1.9.7
minversion: 3.5
Set Device Mode (Fan Control)
POST /api/dev/addDevMode
Content-Type: application/x-www-form-urlencoded
[See Controller-Specific Payloads below]
Device Types
AC Infinity manufactures different types of devices:
Supported: Controller-Based Devices
These devices have a central controller with USB-C ports for connecting fans and sensors:
UIS 89 AI+ (Type 20)
- Device Type: 20
- newFrameworkDevice: true
- API Approach: Hardcoded static payload
- User-Agent:
ACController/1.9.7 (com.acinfinity.humiture; build:533; iOS 18.5.0) Alamofire/5.10.2
UIS 69 PRO (Type 11)
- Device Type: 11
- newFrameworkDevice: false
- API Approach: Static payload with real device settings
- User-Agent:
ACController/1.9.7 (com.acinfinity.humiture; build:533; iOS 18.5.0) Alamofire/5.10.2
UIS 69 PRO+ (Type 18)
- Device Type: 18
- newFrameworkDevice: false
- API Approach: Static payload with real device settings
- User-Agent:
ACController/1.9.7 (com.acinfinity.humiture; build:533; iOS 18.5.0) Alamofire/5.10.2
Unsupported: Standalone Devices
Airtap T4/T6 Register Booster Fans - These standalone Wi-Fi devices don't have a controller or ports structure. The API likely returns device data without the deviceInfo.ports array.
Status: Not yet supported. Need device data from actual Airtap users to implement support.
Workaround: Use ESP32 module replacement for ESPHome/Home Assistant integration.
Controller-Specific Payloads
UIS 89 AI+ (Hardcoded Static Payload)
For newer controllers, use a static payload with hardcoded values:
POST /api/dev/addDevMode
Content-Type: application/x-www-form-urlencoded
acitveTimerOff=0&acitveTimerOn=0&activeCycleOff=0&activeCycleOn=0&activeHh=0&activeHt=0&activeHtVpd=0&activeHtVpdNums=0&activeLh=0&activeLt=0&activeLtVpd=0&activeLtVpdNums=0&atType=2&co2FanHighSwitch=0&co2FanHighValue=0&co2LowSwitch=0&co2LowValue=0&devHh=0&devHt=0&devHtf=32&devId=1234567890123456789&devLh=0&devLt=0&devLtf=32&devMacAddr=&ecOrTds=0&ecTdsLowSwitchEc=0&ecTdsLowSwitchTds=0&ecTdsLowValueEcMs=1&ecTdsLowValueEcUs=0&ecTdsLowValueTdsPpm=0&ecTdsLowValueTdsPpt=1&ecUnit=0&externalPort=1&hTrend=0&humidity=0&isOpenAutomation=0&masterPort=0&modeType=2&moistureLowSwitch=0&moistureLowValue=0&offSpead=0&onSelfSpead=7&onSpead=7&onlyUpdateSpeed=0&phHighSwitch=0&phHighValue=0&phLowSwitch=0&phLowValue=0&schedEndtTime=65535&schedStartTime=65535&settingMode=0&speak=0&surplus=0&tTrend=0&targetHumi=0&targetHumiSwitch=0&targetTSwitch=0&targetTemp=0&targetTempF=32&targetVpd=0&targetVpdSwitch=0&tdsUnit=0&temperature=0&temperatureF=0&trend=0&unit=0&vpdSettingMode=0&waterLevelLowSwitch=0&waterTempHighSwitch=0&waterTempHighValue=0&waterTempHighValueF=32&waterTempLowSwitch=0&waterTempLowValue=0&waterTempLowValueF=32
Key Parameters:
onSpead=7: Target fan speed (0-10)modeType=2: Set to ON mode (use0to turn off)externalPort=1: Port number
Headers:
token: 1234567890123456789
phoneType: 1
appVersion: 1.9.7
minversion: 3.5
UIS 69 PRO (Static Payload with Real Settings)
For older controllers, first fetch current settings, then send them in static payload format:
-
Fetch Current Settings (as shown above)
-
Send Static Payload with real values:
POST /api/dev/addDevMode
Content-Type: application/x-www-form-urlencoded
acitveTimerOff=[REAL_VALUE]&acitveTimerOn=[REAL_VALUE]&activeCycleOff=[REAL_VALUE]&...&onSpead=7&...
Headers:
token: 1234567890123456789
phoneType: 1
appVersion: 1.9.7
Critical Differences:
- Populate payload with actual device settings (not zeros)
- Omit the
modeSetidfield (this causes 403 errors) - Set
modeType=2whenonSpead > 0to activate the fan (ormodeType=0to turn off) - Only change the
onSpeadandmodeTypeparameters - Keep all other values as retrieved from current settings
Key API Fields
Fan Speed Control
- onSpead: Target fan speed (0-10)
- speak: Current fan power level (0-10, read-only)
- onSelfSpead: Self-regulating speed setting
Device Information
- devId: Device identifier
- externalPort: Port number (1-8 depending on controller)
- devType: Controller type (11=UIS 69 PRO, 20=UIS 89 AI+, 18=UIS 69 PRO+)
- newFrameworkDevice: Boolean indicating API approach needed
Environmental Data
- temperature: Temperature (×100, e.g., 2366 = 23.66°C)
- humidity: Humidity (×100, e.g., 5118 = 51.18%)
- vpdnums: VPD value (×100, e.g., 143 = 1.43 kPa)
Mode Detection
- curMode: Current operating mode (read-only status)
1= OFF2= ON (Manual)3= AUTO8= VPD
- modeType: Mode to set when changing settings
0= OFF2= ON (Manual)- Important: Must set
modeType=2when changing speed to activate the fan
Port Status
- online: Port connection status (0/1)
- loadState: Load detection (0/1)
- portResistance: Port resistance reading
Error Codes
- 200: Success
- 403: "Data saving failed" (rate limiting or invalid payload)
- 404: Endpoint not found
- 500: Invalid credentials
- 10001: Authentication failed
- 100001: Generic request error
- 999999: Operation failed (usually unsupported controller)
Common Issues
Speed Changes Not Persisting
Symptom: API returns 200 success, but controller doesn't change speed. Speed reverts to 0 after a few seconds.
Root Cause: Controller is in OFF mode (curMode: 1). The API accepts speed changes but the controller ignores them when not activated.
Solution: Always set modeType=2 (ON) when setting onSpead > 0. Set modeType=0 when turning off.
Example:
// Wrong - speed won't persist if controller is OFF
onSpead=5&modeType=0
// Correct - activates controller and sets speed
onSpead=5&modeType=2
// Correct - turns off controller
onSpead=0&modeType=0
"Data saving failed" (403)
Symptom: 403 error when trying to set fan speed on UIS 69 PRO.
Root Cause: Including modeSetid field or using wrong payload format.
Solution:
- For UIS 69 PRO: Use static payload with real device settings (NO
modeSetid) - For UIS 89 AI+: Use hardcoded static payload
Rate Limiting
The API implements connection-based rate limiting:
- Multiple requests from different connections are treated as different clients
- Use persistent HTTP connections (keepalive) to avoid rate limits
- Implement request queuing with reasonable delays (500ms between requests)
Network Analysis
This API documentation was created through:
- Charles Proxy Analysis: Captured official AC Infinity iPhone app network traffic
- Home Assistant Integration: Analyzed working Home Assistant plugin implementation
- Live Testing: Tested with actual UIS 69 PRO and UIS 89 AI+ hardware
- Reverse Engineering: Discovered controller-specific approaches through trial and error
Security Notes
⚠️ Important Security Considerations:
- API credentials (email/password) are transmitted in plain text
- Authentication tokens have no visible expiration
- All API communication happens over HTTP (not HTTPS)
- This API is intended for local network use with AC Infinity controllers
- Never expose API credentials in public repositories or logs
Implementation Notes
HTTP Client Configuration
const axios = axios.create({
baseURL: 'http://www.acinfinityserver.com',
timeout: 15000,
headers: {
'User-Agent': 'ACController/1.9.7 (com.acinfinity.humiture; build:533; iOS 18.5.0) Alamofire/5.10.2',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
},
httpAgent: new Agent({ keepAlive: true, maxSockets: 1 }),
httpsAgent: new HttpsAgent({ keepAlive: true, maxSockets: 1 }),
maxRedirects: 3,
validateStatus: (status) => status < 500,
});
Controller Detection
function isNewFrameworkDevice(deviceType, deviceData) {
// AI+ controllers use hardcoded static payload
if (deviceType === 20) return true;
// Check explicit framework flag
if (deviceData?.newFrameworkDevice === true) return true;
if (deviceData?.newFrameworkDevice === false) return false;
// Default: older controllers use real settings approach
return false;
}
Error Handling
if (response.data.code === 403) {
// Rate limited or invalid payload
// For UIS 69 PRO: try iPhone app approach
// For UIS 89 AI+: verify static payload format
}
if (response.data.code === 999999) {
// Unsupported controller or wrong API approach
// Switch between hardcoded vs real settings method
}
Testing
A comprehensive test CLI application is included (test-api.js) that:
- Auto-detects controller types
- Uses appropriate API approach for each controller
- Includes fallback logic for unknown devices
- Provides detailed logging for debugging
Usage:
node test-api.js http://www.acinfinityserver.com email@example.com password123 devices
node test-api.js http://www.acinfinityserver.com email@example.com password123 speed DEVICE_ID PORT_ID SPEED
This documentation reflects the current understanding of the AC Infinity API as of December 2025. The API may change without notice as it's not officially documented by AC Infinity.