u
This commit is contained in:
@@ -35,14 +35,15 @@ export class ACInfinityClient {
|
||||
|
||||
async login() {
|
||||
try {
|
||||
// AC Infinity API does not accept passwords greater than 25 characters
|
||||
const normalizedPassword = this.password.substring(0, 25);
|
||||
// AC Infinity API does not accept passwords greater than 25 characters - UPDATE: Reference impl uses full password?
|
||||
// const normalizedPassword = this.password.substring(0, 25);
|
||||
const normalizedPassword = this.password;
|
||||
|
||||
const response = await fetch(`${this.host}${API_URL_LOGIN}`, {
|
||||
method: 'POST',
|
||||
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',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
appEmail: this.email,
|
||||
@@ -63,6 +64,7 @@ export class ACInfinityClient {
|
||||
console.log('[AC] Successfully logged in to AC Infinity API');
|
||||
return this.userId;
|
||||
} catch (error) {
|
||||
console.error('[AC] Login error details:', error); // Added detailed logging
|
||||
if (error instanceof ACInfinityClientError) {
|
||||
throw error;
|
||||
}
|
||||
@@ -129,6 +131,9 @@ export class ACInfinityClient {
|
||||
for (const device of devices) {
|
||||
const devId = device.devId;
|
||||
const devName = device.devName || `device-${devId}`;
|
||||
// Use deviceInfo if available (newer API structure), otherwise fallback to root/devSettings
|
||||
const info = device.deviceInfo || device;
|
||||
const settings = device.devSettings || info;
|
||||
|
||||
// Normalize device name for use as identifier
|
||||
const deviceId = devName
|
||||
@@ -136,52 +141,65 @@ export class ACInfinityClient {
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-|-$/g, '');
|
||||
|
||||
// Extract sensor data from device settings or sensor fields
|
||||
// Temperature is stored as Celsius * 100
|
||||
if (device.devSettings?.temperature !== undefined) {
|
||||
// --- Device Level Sensors ---
|
||||
|
||||
// Temperature (Celsius * 100)
|
||||
if (info.temperature !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'temperature',
|
||||
value: device.devSettings.temperature / 100,
|
||||
value: info.temperature / 100,
|
||||
});
|
||||
} else if (device.temperature !== undefined) {
|
||||
} else if (settings.temperature !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'temperature',
|
||||
value: device.temperature / 100,
|
||||
value: settings.temperature / 100,
|
||||
});
|
||||
}
|
||||
|
||||
// Humidity is stored as % * 100
|
||||
if (device.devSettings?.humidity !== undefined) {
|
||||
// Humidity (% * 100)
|
||||
if (info.humidity !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'humidity',
|
||||
value: device.devSettings.humidity / 100,
|
||||
value: info.humidity / 100,
|
||||
});
|
||||
} else if (device.humidity !== undefined) {
|
||||
} else if (settings.humidity !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'humidity',
|
||||
value: device.humidity / 100,
|
||||
value: settings.humidity / 100,
|
||||
});
|
||||
}
|
||||
|
||||
// VPD if available
|
||||
if (device.devSettings?.vpdnums !== undefined) {
|
||||
// VPD
|
||||
if (info.vpdnums !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'vpd',
|
||||
value: device.devSettings.vpdnums / 100,
|
||||
value: info.vpdnums / 100,
|
||||
});
|
||||
} else if (settings.vpdnums !== undefined) {
|
||||
readings.push({
|
||||
device: deviceId,
|
||||
channel: 'vpd',
|
||||
value: settings.vpdnums / 100,
|
||||
});
|
||||
}
|
||||
|
||||
// Check for port-level sensors (some controllers have multiple ports)
|
||||
if (device.devPortList && Array.isArray(device.devPortList)) {
|
||||
for (const port of device.devPortList) {
|
||||
const portId = port.portId || port.port;
|
||||
const portDeviceId = `${deviceId}-port${portId}`;
|
||||
// --- Port Level Sensors/State ---
|
||||
const ports = info.ports || device.devPortList;
|
||||
if (ports && Array.isArray(ports)) {
|
||||
for (const port of ports) {
|
||||
const portId = port.port || port.portId;
|
||||
const portName = port.portName || `port${portId}`;
|
||||
// Create a descriptive suffix for the port device, e.g. "wall-fan" or "wall-port1"
|
||||
// If portName is generic "Port X", use number. If it's specific "Fan", use that.
|
||||
const suffix = portName.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
||||
const portDeviceId = `${deviceId}-${suffix}`;
|
||||
|
||||
// Port specific sensors (if any - sometimes temp usually on device)
|
||||
if (port.temperature !== undefined) {
|
||||
readings.push({
|
||||
device: portDeviceId,
|
||||
@@ -189,7 +207,6 @@ export class ACInfinityClient {
|
||||
value: port.temperature / 100,
|
||||
});
|
||||
}
|
||||
|
||||
if (port.humidity !== undefined) {
|
||||
readings.push({
|
||||
device: portDeviceId,
|
||||
@@ -197,6 +214,15 @@ export class ACInfinityClient {
|
||||
value: port.humidity / 100,
|
||||
});
|
||||
}
|
||||
|
||||
// Level / Speed (speak)
|
||||
if (port.speak !== undefined) {
|
||||
readings.push({
|
||||
device: portDeviceId,
|
||||
channel: 'level',
|
||||
value: port.speak,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user