/**
* BeNomad BeMap JavaScript API - ChargingTime service (v1.5)
*
* Promise-based wrapper around `POST service/chargingTime/1.0` — estimates
* how long it takes to charge an EV from one battery level to another at
* a given charger.
*
* Auth: `ROLE_CHARGINGTIME`.
*
* Note: the BeMap server does NOT expose a per-vehicle "curve" endpoint.
* Customers who need a charging curve to plot call `estimate()` repeatedly
* with different `remainingBatteryLevel` values (e.g. 10, 20, 30, …, 90)
* and derive instantaneous power from the differences.
*
* Typical usage:
*
* var ct = new bemap.ChargingTime(ctx);
* var req = new bemap.ChargingTimeRequest({
* vehicle: 'a204c816-...',
* chargingPointPower: 50,
* chargingCurrentType: bemap.ChargingCurrentType.DC,
* remainingBatteryLevel: 20,
* chargingBatteryLevel: 80
* });
* ct.estimate(req).then(function(resp) {
* console.log('charging time:', resp.getChargingTime(), 's');
* console.log('knee at:', resp.getOptimumBatteryChargeLevel(), '%');
* }).catch(function(err) {
* if (err.getCode() === bemap.Error.CHARGING_TIME_FAILED) ...;
* });
*
* @since 1.5.0
* @public
* @constructor
* @extends {bemap.ServiceV2}
* @param {bemap.Context} context
* @param {Object} [options]
*/
bemap.ChargingTime = function(context, options) {
bemap.ServiceV2.call(this, context, options);
};
bemap.inherits(bemap.ChargingTime, bemap.ServiceV2);
/**
* Estimate a charging duration.
*
* @public
* @param {bemap.ChargingTimeRequest} request
* @param {Object} [options]
* @param {AbortSignal} [options.signal]
* @return {Promise<bemap.ChargingTimeResponse>}
*/
bemap.ChargingTime.prototype.estimate = function(request, options) {
if (!(request instanceof bemap.ChargingTimeRequest)) {
return Promise.reject(new bemap.Error({
code: bemap.Error.INVALID_ARGUMENT,
message: 'ChargingTime.estimate requires a bemap.ChargingTimeRequest'
}));
}
// Client-side validation — fail before the network call.
if (!request.vehicle) {
return Promise.reject(new bemap.Error({
code: bemap.Error.INVALID_ARGUMENT,
message: 'ChargingTime.estimate: request.vehicle (UUID key) is required'
}));
}
if (request.chargingPointPower === null || request.chargingPointPower <= 0) {
return Promise.reject(new bemap.Error({
code: bemap.Error.INVALID_ARGUMENT,
message: 'ChargingTime.estimate: request.chargingPointPower must be > 0 (kW)'
}));
}
if (!request.chargingCurrentType) {
return Promise.reject(new bemap.Error({
code: bemap.Error.INVALID_ARGUMENT,
message: 'ChargingTime.estimate: request.chargingCurrentType is required (bemap.ChargingCurrentType.*)'
}));
}
if (request.chargingBatteryLevel <= request.remainingBatteryLevel) {
return Promise.reject(new bemap.Error({
code: bemap.Error.INVALID_ARGUMENT,
message: 'ChargingTime.estimate: chargingBatteryLevel must be > remainingBatteryLevel'
}));
}
var opts = options || {};
var body = request.toJson();
if (!body.geoserver) body.geoserver = this.ctx.getGeoserver();
return this._post('service/chargingTime/1.0', body, { signal: opts.signal })
.then(function(json) {
var resp = bemap.ChargingTimeResponse.fromJson(json);
if (resp.isError()) {
throw new bemap.Error({
code: bemap.Error.CHARGING_TIME_FAILED,
message: 'The server could not compute a charging time ' +
'(zero battery capacity, zero connector power, or zero max charge power)',
context: json
});
}
return resp;
});
};