UNPKG

@iotize/tap

Version:

IoTize Device client for Javascript

818 lines (802 loc) 31 kB
import { TapRequestFrame, ResultCode, ApduResponse } from '@iotize/tap/client/api'; import { TapRequestHelper, tapResponseStatusToString, TapResponseFrameBuilder, TapRequestFrameBuilder, TapClient, NumberConverter, TapStreamReader, TapStreamWriter } from '@iotize/tap/client/impl'; import { defer, Observable, Subject } from 'rxjs'; import { createLazyDebugger, createDebugger } from '@iotize/common/debug'; import { chunkArray } from '@iotize/common/array'; import { bufferToHexString } from '@iotize/common/byte-converter'; import { first } from 'rxjs/operators'; import { CodeError } from '@iotize/common/error'; class PathParameter { static fillParam(path, key, value) { var map = {}; map[key] = value; return PathParameter.fillParams(path, map); } /** * Same as fillParams but will throw an error if some parameters has not been replaced */ static fillAllParams(path, pathParameters) { path = PathParameter.fillParams(path, pathParameters); const remainingArgs = PathParameter.extractParams(path); if (remainingArgs.length > 0) { throw new Error(`Missing path parameter ${remainingArgs.join(', ')} (path: ${path})`); } return path; } static fillParams(path, mapping) { for (var key in mapping) { var match = '{' + key + '}'; if (path.indexOf(match) >= 0) { path = path.replace(match, mapping[key].toString()); } else { throw new Error('Parameter ' + key + ' does not exist in path: ' + path); } } return path; } /** * * @param path * @returns names of path parameters */ static extractParams(path) { var found = [], rxp = PathParameter.PARAMETER_REGEX, curMatch; while ((curMatch = rxp.exec(path))) { found.push(curMatch[1]); } return found; } static hasParams(path) { return PathParameter.extractParams(path).length > 0; } } (function (PathParameter) { PathParameter.PARAMETER_REGEX = /{([^}]+)}/g; })(PathParameter || (PathParameter = {})); const prefix = '@iotize/tap'; const lazyDebug = createLazyDebugger(prefix); const debug = createDebugger(prefix); class TapError extends CodeError { constructor(code, message, cause) { super(message, code); this.cause = cause; } static cannotStartScram(err) { return new TapError(TapError.Code.CannotStartScram, `Cannot start encrypted session, initialization failed. Cause: ${err.message}`, err); } static notImplementedYet(msg) { throw new TapError(TapError.Code.NotImplemented, msg); } static initializationVectorNotSupported(err) { return new TapError(TapError.Code.InitializationVectorNotSupported, `Initialization vector for SCRAM is not implemented with your current firmware version. You cannot use this feature.`, err); } static executeRequestError(request, err) { return new TapError(TapError.Code.ExecuteRequestError, `Tap request ${TapRequestFrame.MethodType[request.method]} ${request.pathAlias || request.path} failed. ${err.message}`, err); } static reponseStatusError(response, call) { return new TapResponseStatusError(response, call); } static invalidServiceCallConfiguration(msg) { return new TapError(TapError.Code.InvalidServiceCallConfiguration, msg); } static appendChunkError(cause, chunk, progress) { return new AppendChunkError(cause, chunk, progress); } static nfcPairingError(msg, cause) { return new TapError(TapError.Code.NfcPairingError, `NFC pairing failed. ${msg}`, cause); } } (function (TapError) { let Code; (function (Code) { Code["CannotStartScram"] = "TapErrorCannotStartScram"; Code["NotImplemented"] = "TapErrorNotImplemented"; Code["InitializationVectorNotSupported"] = "TapErrorInitializationVectorNotSupported"; Code["AppendChunkError"] = "AppendChunkError"; Code["ResponseStatusError"] = "TapErrorTapResponseStatusError"; Code["InvalidServiceCallConfiguration"] = "TapErrorInvalidServiceCallConfiguration"; Code["ExecuteRequestError"] = "TapErrorTapExecuteRequestError"; Code["NfcPairingError"] = "TapErrorNfcPairingError"; Code["ScramNotStartedYet"] = "TapErrorScramNotStartedYet"; Code["InvalidScramKey"] = "TapErrorInvalidScramKey"; })(Code = TapError.Code || (TapError.Code = {})); })(TapError || (TapError = {})); class TapResponseStatusError extends TapError { constructor(response, call) { super(TapError.Code.ResponseStatusError, `Tap request ${call ? `${serviceCallToString(call)} ` : response.request ? TapRequestHelper.toString(response.request) + ' ' : ''}failed. ${tapResponseStatusToString(response.status)} (status code 0x${response.status.toString(16)})`); this.response = response; } } class AppendChunkError extends TapError { constructor(cause, chunk, progress) { super(TapError.Code.AppendChunkError, `Appending data chunk n°${progress.loaded}/${progress.total} failed with error: ${cause.message}`, cause); this.chunk = chunk; this.progress = progress; } } class TapResponse { constructor(_tapResponse, request, bodyDecoder) { this._tapResponse = _tapResponse; this.request = request; this.bodyDecoder = bodyDecoder; } static SUCCESS(data) { return TapResponse.create(ResultCode.OK, data); } static ERROR(errorCode) { errorCode = errorCode || ResultCode.BAD_REQUEST; return TapResponse.create(errorCode); } static create(codeRet, data) { return new TapResponse(TapResponseFrameBuilder.create(codeRet, data)); } get data() { return this._tapResponse.data; } body(decoder) { this.successful(); if (decoder) { return decoder.decode(this.rawBody()); } else if (this._bodyCache === undefined) { if (this.bodyDecoder) { this._bodyCache = this.bodyDecoder.decode(this.rawBody()); } else { this._bodyCache = this.rawBody(); } } // In this case we now that T = DataType return this._bodyCache; } rawBody() { if (this.data) { return this.data; } else { return new Uint8Array(0); } } setBodyDecoder(decoder) { this.bodyDecoder = decoder; return this; } hasBody() { return this.rawBody() != null; } codeRet() { return this.status; } get status() { return this._tapResponse.status; } toString() { return `ResponseMessage[codeRet="${this.status}";data="${this.hasBody() ? bufferToHexString(this.rawBody()) : 'NO DATA'}";decoder=${this.bodyDecoder ? this.bodyDecoder.constructor.name : 'NONE'}]`; } toBytes() { return this.data; } setBody(body) { this._bodyCache = body; } isSuccessful() { return (this.status & 0x80) === 0; } setError(err) { return (this.error = err); } successful() { if (!this.isSuccessful()) { if (this.error) { throw this.error; } else { throw TapError.reponseStatusError(this); } } } setRequest(request) { this.request = request; } } var __awaiter$2 = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; function serviceCallToString(call, options) { function printObject(obj) { if (obj instanceof Uint8Array) { return '0x' + bufferToHexString(obj); } else if (typeof obj === 'object') { return ('{' + Object.keys(obj) .map((key) => `"${key}":${printObject(obj[key])}`) .join(',') + '}'); } else { return JSON.stringify(obj); } } const lwm2mPath = ServiceCallRunner.resolvePathParameters(call); const pathAlias = call.pathAlias ? PathParameter.fillAllParams(call.pathAlias, call.pathParameters || {}) : undefined; let result = `${TapRequestFrame.MethodType[call.method]} ${pathAlias || lwm2mPath}`; if (call.pathAlias) { result += ` (${lwm2mPath})`; } if (!(options === null || options === void 0 ? void 0 : options.skipBody) && call.body !== undefined) { result += ' ' + printObject(call.body); } return result; } class ServiceCallRunner { constructor(client, options = { chunkSize: 220, }) { this.client = client; this.options = options; } get(path, body) { return this.execute({ method: TapRequestFrame.MethodType.GET, path, body, }); } put(path, body) { return this.execute({ method: TapRequestFrame.MethodType.PUT, path, body, }); } post(path, body) { return this.execute({ method: TapRequestFrame.MethodType.POST, path, body, }); } prepare(call) { return defer(() => __awaiter$2(this, void 0, void 0, function* () { const tapRequestFrame = ServiceCallRunner.toTapRequest(call); // const debugArgs: string[] = [`CALL: ${call.method} ${call.path} body=`]; // debugArgs.push( // call.body instanceof Uint8Array // ? bufferToHexString(call.body) // : call.body // ); // debugArgs.push(`(${args[0].toString()})`); try { const tapResponseFrame = yield this.client .request(tapRequestFrame) .toPromise(); if (!tapResponseFrame) { throw new Error(`No Tap response`); } const response = new TapResponse(tapResponseFrame, tapRequestFrame); const responseBodyDecoder = ServiceCallRunner.resolveResponseBodyDecoder(call); if (responseBodyDecoder) { response.setBodyDecoder({ decode: responseBodyDecoder, }); } if (!response.isSuccessful()) { response.setError(TapError.reponseStatusError(response, call)); } return response; } catch (err) { if (!(err instanceof TapError)) { throw TapError.executeRequestError(call, err); } throw err; } })); // return response$.pipe( // tap( // response => { // debug(this.constructor.name, ...debugArgs, '=>', response.toString()); // }, // err => { // debug(this.constructor.name, ...debugArgs, ` => ${err.message}`); // } // ) // ); } execute(call) { return this.prepare(call).pipe(first()).toPromise(); } createAppendCalls(call, chunkSize = this.options.chunkSize) { const chunks = chunkArray(Array.from(call.body || new Uint8Array()), chunkSize).map((chunk, index) => { return Object.assign(Object.assign({}, call), { body: Uint8Array.from(chunk) }); }); return chunks; } prepareAppendCall(call, chunkSize = this.options.chunkSize) { return new Observable((emitter) => { let isCancelled = false; (() => __awaiter$2(this, void 0, void 0, function* () { try { const calls = this.createAppendCalls(call, chunkSize); let index = 0; let byteOffset = 0; for (const call of calls) { if (isCancelled) { return; } const chunk = call.body; const progress = { total: chunk.length, loaded: index + 1, byteOffset, }; emitter.next(progress); const response = yield this.execute({ method: call.method || TapRequestFrame.MethodType.PUT, path: call.path, body: chunk, }); try { response.successful(); } catch (err) { throw TapError.appendChunkError(err, chunk, progress); } byteOffset += chunk.length; index++; } emitter.complete(); } catch (err) { emitter.error(err); return; } }))(); return () => { // TODO throw error on cancel isCancelled = true; }; }); } static toTapRequest(call) { const path = ServiceCallRunner.resolvePathParameters(call); const body = ServiceCallRunner.encodeBody(call); return TapRequestFrameBuilder.create(call.method, path, body); } static resolveResponseBodyDecoder(call) { if (call.responseBodyDecoder) { return toDecoderFunction(call.responseBodyDecoder); } return undefined; } static resolvePathParameters(info) { return PathParameter.fillAllParams(info.path, info.pathParameters || {}); } /** * Encode body according to options and configuration */ static encodeBody(options) { if (options.body === undefined) { return undefined; } const encoded = options.bodyEncoder ? toEncoderFunction(options.bodyEncoder)(options.body) : options.body; if (encoded !== undefined && !(encoded instanceof Uint8Array)) { throw TapError.invalidServiceCallConfiguration(`Request body encoder is required for call to ${serviceCallToString(options)}`); } return encoded; } } function toEncoderFunction(classOrFunction) { return typeof classOrFunction === 'function' ? classOrFunction : classOrFunction.encode.bind(classOrFunction); } function toDecoderFunction(classOrFunction) { return typeof classOrFunction === 'function' ? classOrFunction : classOrFunction.decode.bind(classOrFunction); } class AbstractService { constructor(serviceCallRunner) { this.serviceCallRunner = serviceCallRunner; } } /** * This class will be augmented when importing specific service * For example: * ```typescript * const container: ServiceContainer; * expect(container.interface).to.be.undefined; * import '@iotize/tap/service/interface'; * expect(container.interface).to.be.not.undefined; * * ``` */ class ServiceContainer { constructor(serviceCallRunner) { this.serviceCallRunner = serviceCallRunner; } /** * List loaded services */ services() { return Object.values(this.servicesMap()); } servicesMap() { const services = {}; for (const key in this) { const hasDescriptor = Object.getOwnPropertyDescriptor(ServiceContainer.prototype, key); const value = this[key]; if (hasDescriptor === null || hasDescriptor === void 0 ? void 0 : hasDescriptor.enumerable) { if (value instanceof AbstractService) { services[key] = value; } } } return services; } /** * List all loaded resources */ resources() { return this.services().reduce((prev, service) => { prev.push(...Object.values(service.resources)); return prev; }, []); } } function extendServiceContainer(attrName, serviceConstructor) { const hiddenAttrName = `__${attrName}__`; Object.defineProperty(ServiceContainer.prototype, hiddenAttrName, { enumerable: false, configurable: true, writable: true, value: undefined, }); return Object.defineProperty(ServiceContainer.prototype, attrName, { get() { const that = this; if (!that[hiddenAttrName]) { that[hiddenAttrName] = new serviceConstructor(this.serviceCallRunner); } return that[hiddenAttrName]; }, enumerable: true, configurable: true, }); } const NFC_PAIRING_COMMAND = Uint8Array.from([ 0x00, 0xa4, 0x04, 0x00, 0x07, // DATA 0xf0, 0x02, 0x4c, 0x77, 0x4d, 0x32, 0x4d, // -- 0x90, 0x00, // SW2 ]); const DEFAULT_TAP_MAX_FRAME_SIZE = 256 - 6; // Lc = u8 legnth - 5 header bytes - 1 byte "Le" var __awaiter$1 = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; const TAG = 'Device'; /** * */ class Tap { constructor(client) { this._events = new Subject(); this._client = client; this._lwm2m = new ServiceCallRunner(this.client); this.service = new ServiceContainer(this._lwm2m); // 'service', (context) => new ServiceContainer(context.tap.lwm2m) // this._scramInterceptor = new ScramInterceptor( // this._services.scram, // this.apiConfig // ); // this._client.addInterceptor(this._scramInterceptor); // this._initCache(); // this._converterProvider = new ConverterProvider(PathToTypeMap, DefaultConverterMap); } get events() { return this._events.asObservable(); } get client() { return this._client; } get lwm2m() { return this._lwm2m; } set client(client) { this._client = client; this._lwm2m.client = client; // this._services.client = client; } notifyEvent(event) { this._events.next(event); } static create() { return new Tap(TapClient.create()); } static fromProtocol(protocol) { const client = TapClient.create(); client.addComProtocol(protocol); return new Tap(client); } get protocol() { return this.client.getCurrentProtocol(); } /** * Connect with the given communication protocol * TODO what if there is already a connected communication protocol * @param protocol */ connect(protocol) { debug(TAG, 'connecting...'); // this._clearCache(); if (protocol) { this.client.addComProtocol(protocol, 'default'); } return this._client.connect().toPromise(); } /** * Disconnect device */ disconnect() { debug(TAG, 'disconnecting...'); // if (options.clearCache) { // this.clearCache(); // } // if (options.clearSession) { // this.clearSession(); // } return this._client.disconnect().toPromise(); } isConnected() { if (!this._client) { return false; } return this._client.isConnected(); } /** * Configure current tap instance thanks to a TapConfigurator * @param configurator */ configure(configurator) { return configurator.configure(this).toPromise(); } /** * * @param protocol */ useComProtocol(protocol) { this.client.useComProtocol(protocol); return this; } /** * Send an NFC pairing request */ nfcPairing() { return __awaiter$1(this, void 0, void 0, function* () { const comProtocol = yield this.client.getCurrentProtocol(); const response = yield comProtocol.send(NFC_PAIRING_COMMAND).toPromise(); if (!response || response.length !== 2) { throw TapError.nfcPairingError(`Tap responded with a frame size of ${(response === null || response === void 0 ? void 0 : response.length) || 0} byte(s) but expecting 2 bytes.`); } const statusCode = NumberConverter.uint16().decode(response); if (statusCode !== ApduResponse.Status.OK) { throw TapError.nfcPairingError(`Tap responded with an invalid APDU response status 0x${statusCode.toString(16)}.`); } return response; }); } } Tap.TAG = 'Tap'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /** * If response status code is NOT_IMPLEMENTED or NOT_FOUND it will returns the default value * @param responsePromise * @param defaultValue */ function defaultValueIfTapRequetNotImplemented(responsePromise, defaultValue) { return __awaiter(this, void 0, void 0, function* () { const response = yield responsePromise; if (!response.isSuccessful()) { if (response.status === ResultCode.NOT_IMPLEMENTED || response.status === ResultCode.NOT_FOUND) { return defaultValue; } } return response.body(); }); } /** * Utility function add a new getter to the Tap prototype */ function defineTapPropertyExtension(propName, factory) { Object.defineProperty(Tap.prototype, propName, { get() { const that = this; const hiddentPropName = `__${propName}__`; if (!that[hiddentPropName]) { that[hiddentPropName] = factory({ tap: this, }); } return that[hiddentPropName]; }, enumerable: false, configurable: true, }); } /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var HostProtocol; (function (HostProtocol) { HostProtocol[HostProtocol["NFC"] = 1] = "NFC"; HostProtocol[HostProtocol["BLUETOOTH"] = 2] = "BLUETOOTH"; HostProtocol[HostProtocol["GSM"] = 4] = "GSM"; HostProtocol[HostProtocol["USB_RLINK"] = 8] = "USB_RLINK"; HostProtocol[HostProtocol["USB_CMISIS_DAP"] = 16] = "USB_CMISIS_DAP"; HostProtocol[HostProtocol["WIFI"] = 32] = "WIFI"; HostProtocol[HostProtocol["BLE"] = 64] = "BLE"; HostProtocol[HostProtocol["LORA"] = 128] = "LORA"; HostProtocol[HostProtocol["UART"] = 256] = "UART"; HostProtocol[HostProtocol["MQTT"] = 512] = "MQTT"; HostProtocol[HostProtocol["WEBSOCKET"] = 1024] = "WEBSOCKET"; HostProtocol[HostProtocol["SLAVE_SERVER"] = 2048] = "SLAVE_SERVER"; })(HostProtocol || (HostProtocol = {})); /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var TargetProtocol; (function (TargetProtocol) { TargetProtocol[TargetProtocol["SWD"] = 0] = "SWD"; TargetProtocol[TargetProtocol["S3P"] = 1] = "S3P"; TargetProtocol[TargetProtocol["JTAG"] = 2] = "JTAG"; TargetProtocol[TargetProtocol["MODBUS"] = 3] = "MODBUS"; TargetProtocol[TargetProtocol["DIRECT_IO"] = 4] = "DIRECT_IO"; TargetProtocol[TargetProtocol["SERIAL"] = 6] = "SERIAL"; TargetProtocol[TargetProtocol["CUSTOM"] = 7] = "CUSTOM"; TargetProtocol[TargetProtocol["CAN"] = 8] = "CAN"; TargetProtocol[TargetProtocol["MODBUS_TCP"] = 9] = "MODBUS_TCP"; TargetProtocol[TargetProtocol["NONE"] = 255] = "NONE"; })(TargetProtocol || (TargetProtocol = {})); /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var VariableFormat; (function (VariableFormat) { VariableFormat[VariableFormat["_1_BIT"] = 0] = "_1_BIT"; VariableFormat[VariableFormat["_8_BITS"] = 1] = "_8_BITS"; VariableFormat[VariableFormat["_16_BITS"] = 2] = "_16_BITS"; VariableFormat[VariableFormat["_32_BITS"] = 3] = "_32_BITS"; })(VariableFormat || (VariableFormat = {})); /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var AppPathType; (function (AppPathType) { AppPathType["PRIMER_CLOUD_WEB_APP_URL"] = "$1/"; AppPathType["URL"] = "$2/"; AppPathType["ANDROID_APP_ID"] = "$4/"; AppPathType["PRIMER_CLOUD_CONFIG_URL"] = "$5/"; AppPathType["AAR_2"] = "$6/"; })(AppPathType || (AppPathType = {})); /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var SpecialFeature; (function (SpecialFeature) { SpecialFeature[SpecialFeature["SWD_DIRECT_ACCESS"] = 100] = "SWD_DIRECT_ACCESS"; SpecialFeature[SpecialFeature["SERIAL_ACCESS"] = 101] = "SERIAL_ACCESS"; SpecialFeature[SpecialFeature["MODBUS_DIRECT_ACCESS"] = 102] = "MODBUS_DIRECT_ACCESS"; SpecialFeature[SpecialFeature["TAPNPASS_CONTROL_ACCESS"] = 103] = "TAPNPASS_CONTROL_ACCESS"; SpecialFeature[SpecialFeature["SP_CODEEXEC_ACCESS"] = 104] = "SP_CODEEXEC_ACCESS"; SpecialFeature[SpecialFeature["MQTT_IDS_ACCESS"] = 105] = "MQTT_IDS_ACCESS"; SpecialFeature[SpecialFeature["VARIABLE_CONFIG_ACCESS"] = 106] = "VARIABLE_CONFIG_ACCESS"; SpecialFeature[SpecialFeature["FILE_SYSTEM_ACCESS"] = 107] = "FILE_SYSTEM_ACCESS"; })(SpecialFeature || (SpecialFeature = {})); /* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ var CpuFrequencySpeed; (function (CpuFrequencySpeed) { CpuFrequencySpeed[CpuFrequencySpeed["NORMAL"] = 0] = "NORMAL"; CpuFrequencySpeed[CpuFrequencySpeed["SLOW"] = 1] = "SLOW"; CpuFrequencySpeed[CpuFrequencySpeed["FAST"] = 2] = "FAST"; })(CpuFrequencySpeed || (CpuFrequencySpeed = {})); /** * Generated file. Do not edit */ TapStreamReader.prototype.readTapVersion = function () { const model = {}; model.major = this.readUnsigned(1); model.minor = this.readUnsigned(1); model.patch = this.readUnsigned(2); return model; }; // TapStreamWriter.prototype.write(model: TapVersion) : TapStreamWriter{ // return this.writeTapVersion(model) // } TapStreamWriter.prototype.writeTapVersion = function (model) { this.writeUnsigned(model.major !== undefined ? model.major : 0, 1); this.writeUnsigned(model.minor !== undefined ? model.minor : 0, 1); this.writeUnsigned(model.patch !== undefined ? model.patch : 0, 2); return this; }; /** * Generated file. Do not edit */ class TapVersionConverter { encode(model, stream = new TapStreamWriter()) { stream.writeTapVersion(model); return stream.toBytes; } decode(data) { const stream = data instanceof TapStreamReader ? data : TapStreamReader.create(data); return stream.readTapVersion(); } } /** * Generated bundle index. Do not edit. */ export { AbstractService, AppPathType, CpuFrequencySpeed, DEFAULT_TAP_MAX_FRAME_SIZE, HostProtocol, NFC_PAIRING_COMMAND, PathParameter, ServiceCallRunner, ServiceContainer, SpecialFeature, Tap, TapError, TapResponse, TapResponseStatusError, TapVersionConverter, TargetProtocol, VariableFormat, defaultValueIfTapRequetNotImplemented, defineTapPropertyExtension, extendServiceContainer, serviceCallToString, AppendChunkError as ɵa }; //# sourceMappingURL=iotize-tap.js.map