ecosystem-controlstation.js
// used to append interfaces to omnicore sdk so that created app and AppStudio can use
import API from './ecosystem-base.js';
import {Logger} from './../function/log-helper.js';
import {InfoType, WarningType} from '../information/informationCode.js';
import {ErrorCode} from '../exception/exceptionDesc.js';
import {ControlStation, Pending} from '../store/const.js';
import Store from '../store/store.js';
const factoryApiControlStation = function (es) {
let logModule = 'ecosystem-controlstation';
/**
* The API.CONTROLSTATIONMONITOR namespace provides a set of interfaces for easily and quickly adds control station monitoring and processing transactions.
* @alias API.CONTROLSTATIONMONITOR
* @ignore
* @namespace
*/
es.CONTROLSTATIONMONITOR = new (function () {
const subscribedResources = {};
/**
* Enum for monitor resources
*/
this.MonitorResources = {
'write-access-status': 'write-access-status',
'release-appeal-counter': 'release-appeal-counter',
'tpu-safety-protocol-connected': 'tpu-safety-protocol-connected',
'local-is-connected': 'local-is-connected',
};
const checkIfSpocSystem = async function () {
let bSpoc = await API.CONTROLSTATION.isSpocSystem();
if (!bSpoc) {
Logger.e(
logModule,
ErrorCode.UnsupportedSystem,
'ControlStation monitoring is only available on RobotWare 8 or later.',
);
throw new Error(ErrorCode.UnsupportedSystem);
}
};
const subscribeRes = async function (monitor, func) {
if (es.isSubscriptionBlocked) {
Logger.w(
WarningType.RWSSubscriptionBlocked,
'API.CONTROLSTATIONMONITOR: Subscription disabled when trying to monitor control station resource',
);
return;
}
monitor.addCallbackOnChanged(func);
await monitor.subscribe(true);
};
/**
* Monitors a control station resource.
* @alias monitorResource
* @memberof API.CONTROLSTATIONMONITOR
* @param {string} resourceType The type of resource to monitor (from MonitorResources enum).
* @param {function} [callback] The callback function that is called when the resource changes.
* @returns {Promise<void>}
* @example
* API.CONTROLSTATIONMONITOR.monitorResource(
* API.CONTROLSTATIONMONITOR.MonitorResources['write-access-status'],
* (status) => {
* console.log('Status:', status);
* }
* );
*/
this.monitorResource = async function (resourceType, callback = null) {
await checkIfSpocSystem();
const mappingKey = Store.generateMappingKey('ControlStation', [resourceType]);
// Validate if resourceType is a valid monitor resource
if (!Object.keys(this.MonitorResources).includes(resourceType)) {
Logger.w(WarningType.RWSSubscriptionBlocked, `API.CONTROLSTATIONMONITOR: Unknown ${mappingKey}`);
return;
}
if (es.isFetchControllerBlocked) {
Logger.w(
WarningType.RWSRequestBlocked,
`API.CONTROLSTATIONMONITOR: HttpRequest disabled when trying to monitor ${mappingKey}`,
);
return;
}
const storeValue = Store.getNamespace(ControlStation).getMapping(mappingKey);
if (storeValue === undefined) {
try {
Store.getNamespace(ControlStation).setMapping(mappingKey, Pending);
let initialValue;
switch (resourceType) {
case 'write-access-status':
initialValue = await RWS.ControlStation.getWriteAccessStatus();
break;
case 'release-appeal-counter':
initialValue = await RWS.ControlStation.getWriteAccessReleaseAppealChangeCounter();
break;
case 'tpu-safety-protocol-connected':
initialValue = await RWS.ControlStation.getTPUSafetyProtocolStatus();
break;
case 'local-is-connected':
initialValue = await RWS.ControlStation.isLocalConnected();
break;
default:
throw new Error(`Unknown resource type: ${resourceType}`);
}
Store.getNamespace(ControlStation).setMapping(mappingKey, initialValue);
typeof callback === 'function' && callback(initialValue);
es._events.trigger(mappingKey, initialValue);
} catch (e) {
return API.rejectWithStatus(
`Failed to subscribe to control station resource ${resourceType}`,
e,
ErrorCode.FailedToSubscribeControlStation,
);
}
} else if (storeValue === Pending) {
es._events.on(mappingKey, (value) => {
typeof callback === 'function' && callback(value);
});
} else {
typeof callback === 'function' && callback(storeValue);
}
if (es.isSubscriptionBlocked) {
Logger.w(
WarningType.RWSSubscriptionBlocked,
`API.CONTROLSTATION: Subscription disabled when trying to monitor control station resource ${mappingKey}`,
);
return;
}
// if the resource is not subscribed yet, subscribe to it
if (!subscribedResources[mappingKey]) {
try {
const monitor = RWS.ControlStation.getMonitor(resourceType);
const cbResource = function (data) {
Logger.i(logModule, `Control station resource changed: ${resourceType}`);
Store.getNamespace(ControlStation).setMapping(mappingKey, data);
es._events.trigger(mappingKey, data);
Logger.i(InfoType.RobotOperation, `Triggered control station resource: ${resourceType}`);
};
subscribeRes(monitor, cbResource.bind(this));
subscribedResources[mappingKey] = true;
Logger.i(InfoType.RobotOperation, `Control station resource subscribed:${mappingKey}`);
} catch (e) {
return API.rejectWithStatus(
`Failed to subscribe to control station resource ${resourceType}`,
e,
ErrorCode.FailedToSubscribeControlStation,
);
}
}
es._events.on(mappingKey, callback);
};
/**
* Monitors the write access status of control station.
* @alias monitorWriteAccessStatus
* @memberof API.CONTROLSTATIONMONITOR
* @param {function} [callback] The callback function that is called when write access status changes.
* @returns {Promise<void>}
* @example
* API.CONTROLSTATIONMONITOR.monitorWriteAccessStatus((status) => {
* console.log('Write access status:', status);
* if (status.status) {
* console.log('Write access held by:', status.name);
* }
* });
*/
this.monitorWriteAccessStatus = async function (callback = null) {
return this.monitorResource(this.MonitorResources['write-access-status'], callback);
};
/**
* Monitors the write access release appeal counter.
* @alias monitorReleaseAppealCounter
* @memberof API.CONTROLSTATIONMONITOR
* @param {function} [callback] The callback function that is called when counter changes.
* @returns {Promise<void>}
* @example
* API.CONTROLSTATIONMONITOR.monitorReleaseAppealCounter((counter) => {
* console.log('Release appeal counter:', counter);
* });
*/
this.monitorReleaseAppealCounter = async function (callback = null) {
return this.monitorResource(this.MonitorResources['release-appeal-counter'], callback);
};
/**
* Monitors the TPU safety protocol connection status.
* @alias monitorTPUSafetyProtocolConnected
* @memberof API.CONTROLSTATIONMONITOR
* @param {function} [callback] The callback function that is called when connection status changes.
* @returns {Promise<void>}
* @example
* API.CONTROLSTATIONMONITOR.monitorTPUSafetyProtocolConnected((isConnected) => {
* console.log('TPU safety protocol connected:', isConnected);
* });
*/
this.monitorTPUSafetyProtocolConnected = async function (callback = null) {
return this.monitorResource(this.MonitorResources['tpu-safety-protocol-connected'], callback);
};
/**
* Monitors the local control station connection status.
* @alias monitorLocalIsConnected
* @memberof API.CONTROLSTATIONMONITOR
* @param {function} [callback] The callback function that is called when connection status changes.
* @returns {Promise<void>}
* @example
* API.CONTROLSTATIONMONITOR.monitorLocalIsConnected((isConnected) => {
* console.log('Local control station connected:', isConnected);
* });
*/
this.monitorLocalIsConnected = async function (callback = null) {
return this.monitorResource(this.MonitorResources['local-is-connected'], callback);
};
})();
es.constructControlStation = true;
};
if (typeof API.constructControlStation === 'undefined') {
factoryApiControlStation(API);
}
export default API;
export {factoryApiControlStation};