@iotize/tap
Version:
IoTize Device client for Javascript
269 lines • 16.4 kB
JavaScript
import { bufferToHexString } from '@iotize/common/byte-converter';
import { Subject, throwError } from 'rxjs';
import { map } from 'rxjs/operators';
import { TAP_REQUEST_FRAME_CONVERTER, TAP_RESPONSE_FRAME_CONVERTER, } from './converters';
import { debug } from './debug';
import { InterceptorChain } from './interceptors/interceptor-chain';
import { TapClientError } from './tap-client-error';
import { TapRequestHelper } from './request/tap-request-helper';
const TAG = 'Client';
export class TapClient {
constructor(requestEncoder, responseDecoder) {
this._onProtocolChange = new Subject();
this._commandEncoder = requestEncoder;
this._responseDecoder = responseDecoder;
this.protocols = {};
this._interceptorChain = new InterceptorChain((context) => {
try {
const command = context.request;
// const bodyDecoder = context.bodyDecoder;
return this._command(command);
}
catch (err) {
return throwError(err);
}
});
}
static create(protocol) {
const client = new TapClient(TAP_REQUEST_FRAME_CONVERTER, TAP_RESPONSE_FRAME_CONVERTER);
if (protocol) {
client.addComProtocol(protocol);
}
return client;
}
// public isEncryptionEnabled(): boolean {
// return this._options.encryption;
// }
// public get cryptedFrameConverter() {
// return this._cryptedFrameConverter;
// }
get interceptorChain() {
return this._interceptorChain;
}
addInterceptor(interceptor) {
this.interceptorChain.addInterceptor(interceptor);
return this;
}
// /**
// * Enable/Disable encrytion when communicating with a device
// * @param value true if requests must be encrypted
// * @param algo optional if you have already provided the algo with @{link setEncryptionAlgo(algo)} method
// */
// public enableEncryption(value: boolean, algo?: EncryptionAlgo): Promise<any> {
// if (value) {
// algo = algo || this._encryptionAlgo;
// if (!algo) {
// return Promise.reject(
// TapClientError.illegalArgument(
// 'Illegal argument, encryption algo must be set'
// )
// );
// }
// return this._startEncryption(algo);
// }
// else {
// return this._stopEncryption();
// }
// }
isConnected() {
return (this.hasProtocol(this.currentProtocolId) &&
this.getCurrentProtocol().isConnected());
}
/**
* see {@link getCurrentProtocol}
*/
get protocol() {
return this.getCurrentProtocol();
}
get commandEncoder() {
return this._commandEncoder;
}
get responseDecoder() {
return this._responseDecoder;
}
/**
* Get current protocol or throw an error if no protocol
*/
getCurrentProtocol() {
if (!this.currentProtocolId) {
throw TapClientError.illegalStateError('Tap client protocol is required');
}
if (!this.hasProtocol(this.currentProtocolId)) {
throw TapClientError.illegalArgument('Protocol ' + this.currentProtocolId + ' does not exist');
}
return this.protocols[this.currentProtocolId];
}
/**
* Register/replace a communication protocol with given id
* If no communication protocol is selected yet, it will select it.
* @param newProtocol
* @param id
*/
addComProtocol(newProtocol, id = 'default') {
this.protocols[id] = newProtocol;
if (!this.currentProtocolId) {
this.currentProtocolId = id;
}
return this;
}
/**
* Switch to given communication protocol identifier
* @throws if protocol identifier does not exist
* @param name
*/
switchProtocol(name) {
if (!this.hasProtocol(name)) {
throw TapClientError.illegalArgument('Unkonwn protocol: ' + name);
}
const oldProtocol = this.getCurrentProtocol();
this.currentProtocolId = name;
debug(TAG, `Changing protocol to: ${name}`);
this._onProtocolChange.next({
newProtocol: this.getCurrentProtocol(),
oldProtocol,
});
return this;
}
/**
* Change communication protocol
* @throws if protocol identifier does not exist
* @param protocol can either be the communication protocol instance or a string identifier
*/
useComProtocol(protocol) {
let protocolId;
if (typeof protocol == 'string') {
protocolId = protocol;
}
else {
protocolId = protocol.constructor.name;
this.addComProtocol(protocol, protocolId);
}
this.switchProtocol(protocolId);
return this;
}
/**
* Return true if protocol identifier is registered
* @param id
*/
hasProtocol(id) {
return id in this.protocols;
}
connect() {
try {
return this.getCurrentProtocol().connect();
}
catch (err) {
return throwError(err);
}
}
disconnect() {
try {
return this.getCurrentProtocol().disconnect();
}
catch (err) {
return throwError(err);
}
}
/**
* Send request
* @param request
* @param bodyDecoder
*/
request(request) {
return this._interceptorChain.execute({
// bodyDecoder,
request,
client: this,
});
}
/**
* Send raw request
* No interceptors/No encryption will be triggered
* @param dataIn request bytes
* @param bodyDecoder optional body decoder to use
*/
send(dataIn) {
try {
return this.getCurrentProtocol()
.send(dataIn)
.pipe(map((result) => {
// debug(
// TAG,
// 'Received result: ',
// bufferToHexString(result),
// 'DECODER: ',
// bodyDecoder ? bodyDecoder.constructor.name : 'NO'
// );
try {
return this._responseDecoder.decode(result);
}
catch (err) {
throw TapClientError.decodeResponseError(err, dataIn);
}
}));
}
catch (err) {
return throwError(err);
}
}
/**
* Listen to connection state change event
* We have to resubscribe when protocol change..
*/
onConnectionStateChange() {
try {
return this.getCurrentProtocol().onConnectionStateChange();
}
catch (err) {
return throwError(err);
}
}
onProtocolChange() {
try {
return this._onProtocolChange.asObservable();
}
catch (err) {
return throwError(err);
}
}
_command(command) {
try {
if (!this.isConnected()) {
return throwError(TapClientError.notConnectedError());
}
let dataIn;
try {
dataIn = this._commandEncoder.encode(command);
}
catch (e) {
return throwError(TapClientError.encodeRequestError(command, e));
}
debug(TAG, `Sending ${TapRequestHelper.toString(command)} (${dataIn.length} bytes 0x${bufferToHexString(dataIn)})`);
return this.getCurrentProtocol()
.send(dataIn)
.pipe(map((result) => {
// debug(
// TAG,
// 'Received result: ',
// bufferToHexString(result),
// 'DECODER: ',
// bodyDecoder ? bodyDecoder.constructor.name : 'NO'
// );
try {
const response = this._responseDecoder.decode(result);
// if (bodyDecoder) {
// response.setBodyDecoder(bodyDecoder);
// }
return response;
}
catch (err) {
throw TapClientError.decodeResponseError(err, command);
}
}));
}
catch (err) {
return throwError(err);
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFwLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL2NsaWVudC9pbXBsL3NyYy9saWIvdGFwLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQWNsRSxPQUFPLEVBQWMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckMsT0FBTyxFQUNMLDJCQUEyQixFQUMzQiw0QkFBNEIsR0FDN0IsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNwRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFaEUsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDO0FBRXJCLE1BQU0sT0FBTyxTQUFTO0lBbUJwQixZQUNFLGNBQW9ELEVBQ3BELGVBQXNEO1FBbEJoRCxzQkFBaUIsR0FBRyxJQUFJLE9BQU8sRUFBdUIsQ0FBQztRQW9CN0QsSUFBSSxDQUFDLGVBQWUsR0FBRyxjQUFjLENBQUM7UUFDdEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLGVBQWUsQ0FBQztRQUN4QyxJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxnQkFBZ0IsQ0FDM0MsQ0FBQyxPQUF5QixFQUFFLEVBQUU7WUFDNUIsSUFBSTtnQkFDRixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO2dCQUNoQywyQ0FBMkM7Z0JBQzNDLE9BQU8sSUFBSSxDQUFD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