@teslemetry/api 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +160 -24
- package/dist/index.d.cts +274 -170
- package/dist/index.d.mts +274 -170
- package/dist/index.mjs +160 -24
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3009,6 +3009,10 @@ var TeslemetryVehicleStream = class extends events.EventEmitter {
|
|
|
3009
3009
|
this.fields = event.config.fields;
|
|
3010
3010
|
});
|
|
3011
3011
|
}
|
|
3012
|
+
on(event, listener) {
|
|
3013
|
+
this.root.sse.sendCache(this.vin, event, listener);
|
|
3014
|
+
return super.on(event, listener);
|
|
3015
|
+
}
|
|
3012
3016
|
/** Get the current configuration for the vehicle */
|
|
3013
3017
|
async getConfig() {
|
|
3014
3018
|
const { data, response } = await getApiConfigByVin({ path: { vin: this.vin } });
|
|
@@ -3080,6 +3084,8 @@ var TeslemetryVehicleStream = class extends events.EventEmitter {
|
|
|
3080
3084
|
this.addField(field).catch((error) => {
|
|
3081
3085
|
this.logger.error(`Failed to add field ${field}:`, error);
|
|
3082
3086
|
});
|
|
3087
|
+
const data = this.root.sse.cache?.[this.vin]?.data?.[field];
|
|
3088
|
+
if (data !== void 0) callback(data);
|
|
3083
3089
|
this.data.on(field, callback);
|
|
3084
3090
|
return () => this.data.off(field, callback);
|
|
3085
3091
|
}
|
|
@@ -3096,16 +3102,69 @@ var TeslemetryStream = class extends events.EventEmitter {
|
|
|
3096
3102
|
active = false;
|
|
3097
3103
|
connected = false;
|
|
3098
3104
|
vin;
|
|
3099
|
-
cache;
|
|
3105
|
+
cache = {};
|
|
3106
|
+
cloudCache;
|
|
3107
|
+
localCache;
|
|
3100
3108
|
logger;
|
|
3101
3109
|
vehicles = /* @__PURE__ */ new Map();
|
|
3102
3110
|
constructor(root, options) {
|
|
3103
3111
|
super();
|
|
3104
3112
|
this.root = root;
|
|
3105
3113
|
this.vin = options?.vin;
|
|
3106
|
-
|
|
3114
|
+
if (typeof options?.cache === "boolean") {
|
|
3115
|
+
this.cloudCache = options.cache;
|
|
3116
|
+
this.localCache = options.cache;
|
|
3117
|
+
} else {
|
|
3118
|
+
this.cloudCache = options?.cache?.cloud;
|
|
3119
|
+
this.localCache = options?.cache?.local;
|
|
3120
|
+
}
|
|
3107
3121
|
this.logger = root.logger;
|
|
3108
3122
|
if (this.vin) this.getVehicle(this.vin);
|
|
3123
|
+
if (this.localCache) this.startLocalCache();
|
|
3124
|
+
}
|
|
3125
|
+
sendCache(vin, event, listener) {
|
|
3126
|
+
if (this.cache) {
|
|
3127
|
+
const vehicleCache = this.cache[vin];
|
|
3128
|
+
if (event === "connectivity" && vehicleCache.connectivity) for (const networkInterface in vehicleCache.connectivity) {
|
|
3129
|
+
const typedNetworkInterface = networkInterface;
|
|
3130
|
+
const status = vehicleCache.connectivity[typedNetworkInterface];
|
|
3131
|
+
if (status !== void 0) listener({
|
|
3132
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3133
|
+
vin,
|
|
3134
|
+
networkInterface: typedNetworkInterface,
|
|
3135
|
+
status,
|
|
3136
|
+
isCache: true
|
|
3137
|
+
});
|
|
3138
|
+
}
|
|
3139
|
+
else if (event === "state" && vehicleCache.state) listener({
|
|
3140
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3141
|
+
vin,
|
|
3142
|
+
state: vehicleCache.state,
|
|
3143
|
+
isCache: true
|
|
3144
|
+
});
|
|
3145
|
+
else if (event === "data" && vehicleCache.data) listener({
|
|
3146
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3147
|
+
vin,
|
|
3148
|
+
data: vehicleCache.data,
|
|
3149
|
+
isCache: true
|
|
3150
|
+
});
|
|
3151
|
+
else if (event === "errors" && vehicleCache.errors) listener({
|
|
3152
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3153
|
+
vin,
|
|
3154
|
+
errors: vehicleCache.errors,
|
|
3155
|
+
isCache: true
|
|
3156
|
+
});
|
|
3157
|
+
else if (event === "alerts" && vehicleCache.alerts) listener({
|
|
3158
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3159
|
+
vin,
|
|
3160
|
+
alerts: vehicleCache.alerts,
|
|
3161
|
+
isCache: true
|
|
3162
|
+
});
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
on(event, listener) {
|
|
3166
|
+
for (const vin in this.cache) this.sendCache(vin, event, listener);
|
|
3167
|
+
return super.on(event, listener);
|
|
3109
3168
|
}
|
|
3110
3169
|
getVehicle(vin) {
|
|
3111
3170
|
if (!this.vehicles.has(vin)) new TeslemetryVehicleStream(this.root, vin);
|
|
@@ -3122,7 +3181,7 @@ var TeslemetryStream = class extends events.EventEmitter {
|
|
|
3122
3181
|
const sse = await getSseByVin_({
|
|
3123
3182
|
client: this.root.client,
|
|
3124
3183
|
path: { vin: this.vin || "" },
|
|
3125
|
-
query: { cache: this.
|
|
3184
|
+
query: { cache: this.cloudCache }
|
|
3126
3185
|
});
|
|
3127
3186
|
this.logger.info(`Connected to stream`);
|
|
3128
3187
|
retries = 0;
|
|
@@ -3181,6 +3240,48 @@ var TeslemetryStream = class extends events.EventEmitter {
|
|
|
3181
3240
|
else if ("config" in event) vehicle.emit("config", event);
|
|
3182
3241
|
}
|
|
3183
3242
|
}
|
|
3243
|
+
cacheState(event) {
|
|
3244
|
+
this.cache[event.vin] ??= {};
|
|
3245
|
+
this.cache[event.vin].state = event.state;
|
|
3246
|
+
}
|
|
3247
|
+
cacheData(event) {
|
|
3248
|
+
this.cache[event.vin] ??= { data: {} };
|
|
3249
|
+
this.cache[event.vin].data = {
|
|
3250
|
+
...this.cache[event.vin].data,
|
|
3251
|
+
...event.data
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
3254
|
+
cacheErrors(event) {
|
|
3255
|
+
this.cache[event.vin] ??= {};
|
|
3256
|
+
this.cache[event.vin].errors = event.errors;
|
|
3257
|
+
}
|
|
3258
|
+
cacheAlerts(event) {
|
|
3259
|
+
this.cache[event.vin] ??= {};
|
|
3260
|
+
this.cache[event.vin].alerts = event.alerts;
|
|
3261
|
+
}
|
|
3262
|
+
cacheConnectivity(event) {
|
|
3263
|
+
this.cache[event.vin] ??= {};
|
|
3264
|
+
this.cache[event.vin].connectivity ??= {};
|
|
3265
|
+
this.cache[event.vin].connectivity[event.networkInterface] = event.status;
|
|
3266
|
+
}
|
|
3267
|
+
startLocalCache() {
|
|
3268
|
+
this.localCache = true;
|
|
3269
|
+
this.on("state", this.cacheState);
|
|
3270
|
+
this.on("data", this.cacheData);
|
|
3271
|
+
this.on("errors", this.cacheErrors);
|
|
3272
|
+
this.on("alerts", this.cacheAlerts);
|
|
3273
|
+
this.on("connectivity", this.cacheConnectivity);
|
|
3274
|
+
this.logger.info(`Started local cache`);
|
|
3275
|
+
}
|
|
3276
|
+
stopLocalCache() {
|
|
3277
|
+
this.localCache = false;
|
|
3278
|
+
this.off("state", this.cacheState);
|
|
3279
|
+
this.off("data", this.cacheData);
|
|
3280
|
+
this.off("errors", this.cacheErrors);
|
|
3281
|
+
this.off("alerts", this.cacheAlerts);
|
|
3282
|
+
this.off("connectivity", this.cacheConnectivity);
|
|
3283
|
+
this.logger.info(`Stopped local cache`);
|
|
3284
|
+
}
|
|
3184
3285
|
};
|
|
3185
3286
|
|
|
3186
3287
|
//#endregion
|
|
@@ -3245,6 +3346,15 @@ var TeslemetryChargingApi = class {
|
|
|
3245
3346
|
var TeslemetryEnergyApi = class extends events.EventEmitter {
|
|
3246
3347
|
root;
|
|
3247
3348
|
siteId;
|
|
3349
|
+
refreshDelay = 3e4;
|
|
3350
|
+
refreshInterval = {
|
|
3351
|
+
siteInfo: null,
|
|
3352
|
+
liveStatus: null
|
|
3353
|
+
};
|
|
3354
|
+
refreshClients = {
|
|
3355
|
+
siteInfo: /* @__PURE__ */ new Set(),
|
|
3356
|
+
liveStatus: /* @__PURE__ */ new Set()
|
|
3357
|
+
};
|
|
3248
3358
|
constructor(root, siteId) {
|
|
3249
3359
|
if (root.api.energySites.has(siteId)) throw new Error("Energy site already exists");
|
|
3250
3360
|
super();
|
|
@@ -3386,6 +3496,34 @@ var TeslemetryEnergyApi = class extends events.EventEmitter {
|
|
|
3386
3496
|
});
|
|
3387
3497
|
return data;
|
|
3388
3498
|
}
|
|
3499
|
+
requestPolling(endpoint) {
|
|
3500
|
+
if (!this.refreshInterval[endpoint]) switch (endpoint) {
|
|
3501
|
+
case "siteInfo":
|
|
3502
|
+
this.refreshInterval[endpoint] = setInterval(() => {
|
|
3503
|
+
this.getSiteInfo();
|
|
3504
|
+
}, this.refreshDelay);
|
|
3505
|
+
this.getSiteInfo();
|
|
3506
|
+
break;
|
|
3507
|
+
case "liveStatus":
|
|
3508
|
+
this.refreshInterval[endpoint] = setInterval(() => {
|
|
3509
|
+
this.getLiveStatus();
|
|
3510
|
+
}, this.refreshDelay);
|
|
3511
|
+
this.getLiveStatus();
|
|
3512
|
+
break;
|
|
3513
|
+
default: throw new Error(`Invalid endpoint: ${endpoint}`);
|
|
3514
|
+
}
|
|
3515
|
+
const symbol = Symbol("refreshClient");
|
|
3516
|
+
this.refreshClients[endpoint].add(symbol);
|
|
3517
|
+
return () => {
|
|
3518
|
+
this.refreshClients[endpoint].delete(symbol);
|
|
3519
|
+
if (this.refreshClients[endpoint].size === 0) {
|
|
3520
|
+
if (this.refreshInterval[endpoint]) {
|
|
3521
|
+
clearInterval(this.refreshInterval[endpoint]);
|
|
3522
|
+
this.refreshInterval[endpoint] = null;
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
};
|
|
3526
|
+
}
|
|
3389
3527
|
};
|
|
3390
3528
|
|
|
3391
3529
|
//#endregion
|
|
@@ -4907,7 +5045,7 @@ const consoleLogger = {
|
|
|
4907
5045
|
|
|
4908
5046
|
//#endregion
|
|
4909
5047
|
//#region package.json
|
|
4910
|
-
var version = "0.
|
|
5048
|
+
var version = "0.5.1";
|
|
4911
5049
|
|
|
4912
5050
|
//#endregion
|
|
4913
5051
|
//#region src/Teslemetry.ts
|
|
@@ -4968,27 +5106,25 @@ var Teslemetry = class {
|
|
|
4968
5106
|
* @returns A promise that resolves to an object containing vehicle and energy site names, API, and SSE instances.
|
|
4969
5107
|
*/
|
|
4970
5108
|
async createProducts() {
|
|
4971
|
-
const { data } = await
|
|
4972
|
-
|
|
4973
|
-
vehicles: {
|
|
4974
|
-
|
|
5109
|
+
const { data } = await getApiMetadata({ client: this.client });
|
|
5110
|
+
return {
|
|
5111
|
+
vehicles: Object.fromEntries(Object.entries(data.vehicles).map(([vin, metadata]) => [vin, {
|
|
5112
|
+
name: metadata.name ?? useTeslaModel(vin),
|
|
5113
|
+
vin,
|
|
5114
|
+
api: this.api.getVehicle(vin),
|
|
5115
|
+
sse: this.sse.getVehicle(vin),
|
|
5116
|
+
metadata
|
|
5117
|
+
}])),
|
|
5118
|
+
energySites: Object.fromEntries(Object.entries(data.energy_sites ?? {}).map(([id, metadata]) => {
|
|
5119
|
+
const siteId = Number(id);
|
|
5120
|
+
return [id, {
|
|
5121
|
+
name: metadata.name ?? "Unnamed",
|
|
5122
|
+
id: siteId,
|
|
5123
|
+
api: this.api.getEnergySite(siteId),
|
|
5124
|
+
metadata
|
|
5125
|
+
}];
|
|
5126
|
+
}))
|
|
4975
5127
|
};
|
|
4976
|
-
data.response?.forEach((product) => {
|
|
4977
|
-
if (product.device_type === "vehicle") result.vehicles[product.vin] = {
|
|
4978
|
-
name: product.display_name ?? useTeslaModel(product.vin),
|
|
4979
|
-
vin: product.vin,
|
|
4980
|
-
api: this.api.getVehicle(product.vin),
|
|
4981
|
-
sse: this.sse.getVehicle(product.vin),
|
|
4982
|
-
product
|
|
4983
|
-
};
|
|
4984
|
-
if (product.device_type === "energy") result.energySites[product.energy_site_id] = {
|
|
4985
|
-
name: product.site_name ?? "Unnamed",
|
|
4986
|
-
site: product.energy_site_id,
|
|
4987
|
-
api: this.api.getEnergySite(product.energy_site_id),
|
|
4988
|
-
product
|
|
4989
|
-
};
|
|
4990
|
-
});
|
|
4991
|
-
return result;
|
|
4992
5128
|
}
|
|
4993
5129
|
/**
|
|
4994
5130
|
* Get a vehicle API instance for the specified VIN.
|