From 172f7759495865d5a66dd72340ff2d48042ea091 Mon Sep 17 00:00:00 2001 From: Karmo7 Date: Wed, 19 Mar 2025 16:56:03 +0200 Subject: [PATCH 01/37] Initial commit --- LICENSE | 21 +++++++++++++++++++++ README.md | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bc893f4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 CDP Technologies + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..831550f --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# JavascriptCDPLoggerClient +A simple Javascript interface to communicate with CDP applications containing a CDPLogger component to retrieve historic data. From 6e5c9358b0f36f0fdcaa2239024709ad2a6d9add Mon Sep 17 00:00:00 2001 From: Karmo7 Date: Wed, 19 Mar 2025 16:56:39 +0200 Subject: [PATCH 02/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 831550f..f00bc8d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# JavascriptCDPLoggerClient +# CDPLogger Client for Javascript A simple Javascript interface to communicate with CDP applications containing a CDPLogger component to retrieve historic data. From 671a042322956d9dda393feb511bef76fad10f7f Mon Sep 17 00:00:00 2001 From: stefanrammo <86823284+stefanrammo@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:34:47 +0200 Subject: [PATCH 03/37] Initial implementation: logger, example usage, and tests --- .gitignore | 2 + README.md | 34 +- client.js | 427 +++ generated/containerPb.js | 7898 ++++++++++++++++++++++++++++++++++++++ index.js | 56 + package-lock.json | 3490 +++++++++++++++++ package.json | 12 + test/client.test.js | 221 ++ test/fakeData.js | 110 + 9 files changed, 12248 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 client.js create mode 100644 generated/containerPb.js create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 test/client.test.js create mode 100644 test/fakeData.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e99588 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +protos/ \ No newline at end of file diff --git a/README.md b/README.md index f00bc8d..933c90e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# CDPLogger Client for Javascript -A simple Javascript interface to communicate with CDP applications containing a CDPLogger component to retrieve historic data. +# CDPLogger Client for JavaScript + +A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. + + +## Installation + +Clone the repository and install dependencies: + +```bash +npm install +``` + + +## Running Tests +To run the automatic tests with fake data, execute: + +```bash +npm test +``` + +## Usage +The index.js file contains a simple logger built for the CDP Studio example case. + +1. Set up and run the Logger in CDP Studio. +(Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) + +2. Run the index.js file from the command line: + +```bash +node index.js +``` \ No newline at end of file diff --git a/client.js b/client.js new file mode 100644 index 0000000..c2c4945 --- /dev/null +++ b/client.js @@ -0,0 +1,427 @@ +// Example: client.js +const root = require('./generated/containerPb.js'); +const Container = root.DBMessaging.Protobuf.Container; + +class Client { + constructor(host, port = 17000, autoReconnect = true) { + this.reqId = -1; + this.autoReconnect = autoReconnect; + this.isOpen = false; + this.queuedRequests = {}; + this.storedPromises = {}; + this.nameToId = {}; + this.idToName = {}; + this.timeDiff = 0; + this.timeReceived = null; + this.lastTimeRequest = Date.now() / 1000; + this.haveSentQueuedReq = false; + this.roundTripTimes = {}; + this.ws = this._connect(`ws://${host}:${port}`); + } + + _connect(url) { + const ws = new WebSocket(url); + ws._url = url; + ws.binaryType = 'arraybuffer'; + ws.onopen = () => this._onOpen(ws); + ws.onmessage = (event) => this._handleMessage(ws, event.data); + ws.onerror = (error) => this._onError(ws, error); + ws.onclose = () => this._onClose(ws); + return ws; + } + + _onOpen(ws) { + this.isOpen = true; + this._updateTimeDiff(); + this.lastTimeRequest = Date.now() / 1000; + } + + _onError(ws, error) { + if (!error) { + error = new Error("Something went wrong"); + } + if (!this.autoReconnect) { + for (const key in this.storedPromises) { + this.storedPromises[key].reject(error); + } + this.storedPromises = {}; + this.queuedRequests = {}; + } + } + + _onClose(ws) { + this.isOpen = false; + if (!this.autoReconnect) { + this._onError(ws, new Error("Connection was closed")); + } else { + // Try to reconnect after a delay + setTimeout(() => { + this.ws = this._connect(ws._url); + }, 1000); + } + } + + disconnect() { + this.autoReconnect = false; + this._cleanupQueuedRequests(); + this.isOpen = false; + if (this.ws) { + this.ws.close(); + } + } + + _cleanupQueuedRequests() { + for (const key in this.storedPromises) { + this.storedPromises[key].reject(new Error("Connection was closed")); + } + this.storedPromises = {}; + this.queuedRequests = {}; + } + + // --- Public API methods --- + + requestApiVersion() { + this._timeRequest(); + const requestId = this._getRequestId(); + if (!this.isOpen) { + this.queuedRequests[requestId] = "api_version"; + } else { + this._sendApiVersionRequest(requestId); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + requestLoggedNodes() { + this._timeRequest(); + const requestId = this._getRequestId(); + if (!this.isOpen) { + this.queuedRequests[requestId] = "logged_nodes"; + } else { + this._sendLoggedNodesRequest(requestId); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + requestLogLimits() { + this._timeRequest(); + const requestId = this._getRequestId(); + if (!this.isOpen) { + this.queuedRequests[requestId] = "log_limits"; + } else { + this._sendLogLimitsRequest(requestId); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + requestDataPoints(nodeNames, startS, endS, noOfDataPoints) { + this._timeRequest(); + const requestId = this._getRequestId(); + const promise = new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + if (!this.isOpen) { + this.queuedRequests[requestId] = ["node_values", nodeNames, startS, endS, noOfDataPoints]; + } else { + this._reqDataPoints(nodeNames, startS, endS, noOfDataPoints, requestId); + } + return promise; + } + + + _handleMessage(ws, message) { + // console.log("Raw data:", message); + const data = Container.decode(new Uint8Array(message)); + this._parseMessage(data); + } + + _parseMessage(data) { + switch (data.messageType) { + case Container.Type.eError: + if (this.storedPromises[data.error.requestId]) { + const { reject } = this.storedPromises[data.error.requestId]; + delete this.storedPromises[data.error.requestId]; + reject(new Error(data.error.errorMessage)); + } + break; + case Container.Type.eTimeResponse: + this.timeReceived = Date.now() / 1000; + if (this.storedPromises[data.timeResponse.requestId]) { + const { resolve } = this.storedPromises[data.timeResponse.requestId]; + delete this.storedPromises[data.timeResponse.requestId]; + resolve(data.timeResponse.timestamp); + } + break; + case Container.Type.eSignalInfoResponse: + const nodes = []; + this.nameToId = {}; + this.idToName = {}; + for (let i = 0; i < data.signalInfoResponse.name.length; i++) { + const node = { + name: data.signalInfoResponse.name[i], + routing: data.signalInfoResponse.path[i] + }; + this.nameToId[data.signalInfoResponse.name[i]] = data.signalInfoResponse.id[i]; + this.idToName[data.signalInfoResponse.id[i]] = data.signalInfoResponse.name[i]; + nodes.push(node); + } + if (this.storedPromises[data.signalInfoResponse.requestId]) { + const { resolve } = this.storedPromises[data.signalInfoResponse.requestId]; + delete this.storedPromises[data.signalInfoResponse.requestId]; + resolve(nodes); + } + break; + case Container.Type.eCriterionLimitsResponse: + data.criterionLimitsResponse.criterionMin += this.timeDiff; + data.criterionLimitsResponse.criterionMax += this.timeDiff; + const limits = { + start_s: data.criterionLimitsResponse.criterionMin, + end_s: data.criterionLimitsResponse.criterionMax + }; + if (this.storedPromises[data.criterionLimitsResponse.requestId]) { + const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; + delete this.storedPromises[data.criterionLimitsResponse.requestId]; + resolve(limits); + } + break; + case Container.Type.eVersionResponse: + const version = parseFloat(data.versionResponse.version); + if (version < 3.0) { + if (this.storedPromises[data.versionResponse.requestId]) { + const { reject } = this.storedPromises[data.versionResponse.requestId]; + delete this.storedPromises[data.versionResponse.requestId]; + reject(new Error("CDP version needs to be 3.0 or newer.")); + } + } else { + if (this.storedPromises[data.versionResponse.requestId]) { + const { resolve } = this.storedPromises[data.versionResponse.requestId]; + delete this.storedPromises[data.versionResponse.requestId]; + resolve(data.versionResponse.version); + } + } + break; + case Container.Type.eSignalDataResponse: + let dataPoints = []; + let index = 0; + for (const row of data.signalDataResponse.row) { + data.signalDataResponse.criterion[index] += this.timeDiff; + let signalNames = []; + for (const signalId of row.signalId) { + signalNames.push(this.idToName[signalId]); + } + const value = this._createValue( + signalNames, + row.minValues, + row.maxValues, + row.lastValues + ); + dataPoints.push({ + timestamp: data.signalDataResponse.criterion[index], + value: value + }); + index++; + } + if (this.storedPromises[data.signalDataResponse.requestId]) { + const { resolve } = this.storedPromises[data.signalDataResponse.requestId]; + delete this.storedPromises[data.signalDataResponse.requestId]; + resolve(dataPoints); + } + break; + default: + console.error("Unknown message type", data.messageType); + } + } + + _createValue(signalNames, minValues, maxValues, lastValues) { + const value = {}; + for (let i = 0; i < signalNames.length; i++) { + value[signalNames[i]] = { + min: this._valueFromVariant(minValues[i]), + max: this._valueFromVariant(maxValues[i]), + last: this._valueFromVariant(lastValues[i]) + }; + } + return value; + } + + _valueFromVariant(value) { + if (value.dValue !== undefined) return value.dValue; + if (value.fValue !== undefined) return value.fValue; + if (value.ui64Value !== undefined) return value.ui64Value; + if (value.i64Value !== undefined) return value.i64Value; + if (value.uiValue !== undefined) return value.uiValue; + if (value.iValue !== undefined) return value.iValue; + if (value.usValue !== undefined) return value.usValue; + if (value.sValue !== undefined) return value.sValue; + if (value.ucValue !== undefined) return value.ucValue; + if (value.cValue !== undefined) return value.cValue; + if (value.bValue !== undefined) return value.bValue; + if (value.strValue !== undefined) return value.strValue; + return null; + } + + _sendQueuedRequests() { + for (const requestId in this.queuedRequests) { + const req = this.queuedRequests[requestId]; + if (req === "logged_nodes") { + this._sendLoggedNodesRequest(requestId); + } else if (req === "log_limits") { + this._sendLogLimitsRequest(requestId); + } else if (Array.isArray(req) && req[0] === "node_values") { + this._reqDataPoints(req[1], req[2], req[3], req[4], requestId); + } else if (req === "api_version") { + this._sendApiVersionRequest(requestId); + } + } + this.queuedRequests = {}; + } + + _getRequestId() { + this.reqId += 1; + return this.reqId; + } + + _timeRequest() { + if ((Date.now() / 1000) > this.lastTimeRequest + 10) { + this._updateTimeDiff(); + } + } + + _updateTimeDiff() { + const requestId = this._getRequestId(); + const timeSent = Date.now() / 1000; + this._requestTime(requestId) + .then(timestamp => this._setTimeDiff(timestamp, timeSent)) + .catch(err => { + if (this.storedPromises[requestId]) { + this.storedPromises[requestId].reject(err); + } + }); + } + + _requestTime(reqId) { + const requestId = reqId; + this.lastTimeRequest = Date.now() / 1000; + this._sendTimeRequest(requestId); + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + _sendTimeRequest(requestId) { + // Create a Container message for time request + const container = Container.create(); + container.messageType = Container.Type.eTimeRequest; + container.timeRequest = { requestId: requestId }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + _setTimeDiff(timestamp, timeSent) { + const clientTime = this.timeReceived; + const roundTripTime = clientTime - timeSent; + const serverTime = (timestamp / 1e9) + roundTripTime / 2; + const timeDiff = clientTime - serverTime; + this.roundTripTimes[roundTripTime] = timeDiff; + if (Object.keys(this.roundTripTimes).length !== 3) { + this._updateTimeDiff(); + } else { + const minRoundTrip = Math.min(...Object.keys(this.roundTripTimes).map(Number)); + this.timeDiff = this.roundTripTimes[minRoundTrip]; + this.roundTripTimes = {}; + if (!this.haveSentQueuedReq) { + this._sendQueuedRequests(); + this.haveSentQueuedReq = true; + } + } + } + + _sendLoggedNodesRequest(requestId) { + const container = Container.create(); + container.messageType = Container.Type.eSignalInfoRequest; + container.signalInfoRequest = { requestId: requestId }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + _sendLogLimitsRequest(requestId) { + const container = Container.create(); + container.messageType = Container.Type.eCriterionLimitsRequest; + container.criterionLimitsRequest = { requestId: requestId }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + _reqDataPoints(nodeNames, startS, endS, noOfDataPoints, requestId) { + const _getDataPoints = (nodeIds) => { + this._sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints); + }; + + const rejectRequest = (error) => { + if (this.storedPromises[requestId]) { + const { reject } = this.storedPromises[requestId]; + delete this.storedPromises[requestId]; + reject(error); + } + }; + + if (!(endS < startS)) { + this._requestNodeIds(nodeNames) + .then(nodeIds => _getDataPoints(nodeIds)) + .catch(rejectRequest); + } else { + rejectRequest(new Error("InvalidRequestError on node values request: endS cannot be smaller than startS")); + } + } + + _requestNodeIds(nodeNames) { + return new Promise((resolve, reject) => { + const parseIds = () => { + for (const name of nodeNames) { + if (!(name in this.nameToId)) { + reject(new Error("Node with name " + name + " does not exist.")); + return; + } + } + resolve(nodeNames.map(name => this.nameToId[name])); + }; + + if (nodeNames.every(name => name in this.nameToId)) { + parseIds(); + } else { + this.requestLoggedNodes() + .then(() => parseIds()) + .catch(reject); + } + }); + } + + _sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints) { + const container = Container.create(); + container.messageType = Container.Type.eSignalDataRequest; + container.signalDataRequest = { + requestId: requestId, + signalId: nodeIds, + numOfDatapoints: noOfDataPoints, + criterionMin: startS - this.timeDiff, + criterionMax: endS - this.timeDiff + }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + _sendApiVersionRequest(requestId) { + const container = Container.create(); + container.messageType = Container.Type.eVersionRequest; + container.versionRequest = { requestId: requestId }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } +} + +module.exports = Client; diff --git a/generated/containerPb.js b/generated/containerPb.js new file mode 100644 index 0000000..db446d1 --- /dev/null +++ b/generated/containerPb.js @@ -0,0 +1,7898 @@ +/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ +"use strict"; + +var $protobuf = require("protobufjs/minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +$root.DBMessaging = (function() { + + /** + * Namespace DBMessaging. + * @exports DBMessaging + * @namespace + */ + var DBMessaging = {}; + + DBMessaging.Protobuf = (function() { + + /** + * Namespace Protobuf. + * @memberof DBMessaging + * @namespace + */ + var Protobuf = {}; + + Protobuf.Container = (function() { + + /** + * Properties of a Container. + * @memberof DBMessaging.Protobuf + * @interface IContainer + * @property {DBMessaging.Protobuf.Container.Type|null} [messageType] Container messageType + * @property {DBMessaging.Protobuf.ISignalInfoRequest|null} [signalInfoRequest] Container signalInfoRequest + * @property {DBMessaging.Protobuf.ISignalInfoResponse|null} [signalInfoResponse] Container signalInfoResponse + * @property {DBMessaging.Protobuf.ISignalDataRequest|null} [signalDataRequest] Container signalDataRequest + * @property {DBMessaging.Protobuf.ISignalDataResponse|null} [signalDataResponse] Container signalDataResponse + * @property {DBMessaging.Protobuf.ICriterionLimitsRequest|null} [criterionLimitsRequest] Container criterionLimitsRequest + * @property {DBMessaging.Protobuf.ICriterionLimitsResponse|null} [criterionLimitsResponse] Container criterionLimitsResponse + * @property {DBMessaging.Protobuf.IVersionRequest|null} [versionRequest] Container versionRequest + * @property {DBMessaging.Protobuf.IVersionResponse|null} [versionResponse] Container versionResponse + * @property {DBMessaging.Protobuf.IError|null} [error] Container error + * @property {DBMessaging.Protobuf.ITimeRequest|null} [timeRequest] Container timeRequest + * @property {DBMessaging.Protobuf.ITimeResponse|null} [timeResponse] Container timeResponse + * @property {DBMessaging.Protobuf.IEventSenderTagsRequest|null} [eventSenderTagsRequest] Container eventSenderTagsRequest + * @property {DBMessaging.Protobuf.IEventSenderTagsResponse|null} [eventSenderTagsResponse] Container eventSenderTagsResponse + * @property {DBMessaging.Protobuf.ICountEventsRequest|null} [countEventsRequest] Container countEventsRequest + * @property {DBMessaging.Protobuf.ICountEventsResponse|null} [countEventsResponse] Container countEventsResponse + * @property {DBMessaging.Protobuf.IEventsRequest|null} [eventsRequest] Container eventsRequest + * @property {DBMessaging.Protobuf.IEventsResponse|null} [eventsResponse] Container eventsResponse + */ + + /** + * Constructs a new Container. + * @memberof DBMessaging.Protobuf + * @classdesc Common union-style base type for all Protobuf messages in DB. + * @implements IContainer + * @constructor + * @param {DBMessaging.Protobuf.IContainer=} [properties] Properties to set + */ + function Container(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Container messageType. + * @member {DBMessaging.Protobuf.Container.Type} messageType + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.messageType = 1; + + /** + * Container signalInfoRequest. + * @member {DBMessaging.Protobuf.ISignalInfoRequest|null|undefined} signalInfoRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.signalInfoRequest = null; + + /** + * Container signalInfoResponse. + * @member {DBMessaging.Protobuf.ISignalInfoResponse|null|undefined} signalInfoResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.signalInfoResponse = null; + + /** + * Container signalDataRequest. + * @member {DBMessaging.Protobuf.ISignalDataRequest|null|undefined} signalDataRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.signalDataRequest = null; + + /** + * Container signalDataResponse. + * @member {DBMessaging.Protobuf.ISignalDataResponse|null|undefined} signalDataResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.signalDataResponse = null; + + /** + * Container criterionLimitsRequest. + * @member {DBMessaging.Protobuf.ICriterionLimitsRequest|null|undefined} criterionLimitsRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.criterionLimitsRequest = null; + + /** + * Container criterionLimitsResponse. + * @member {DBMessaging.Protobuf.ICriterionLimitsResponse|null|undefined} criterionLimitsResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.criterionLimitsResponse = null; + + /** + * Container versionRequest. + * @member {DBMessaging.Protobuf.IVersionRequest|null|undefined} versionRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.versionRequest = null; + + /** + * Container versionResponse. + * @member {DBMessaging.Protobuf.IVersionResponse|null|undefined} versionResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.versionResponse = null; + + /** + * Container error. + * @member {DBMessaging.Protobuf.IError|null|undefined} error + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.error = null; + + /** + * Container timeRequest. + * @member {DBMessaging.Protobuf.ITimeRequest|null|undefined} timeRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.timeRequest = null; + + /** + * Container timeResponse. + * @member {DBMessaging.Protobuf.ITimeResponse|null|undefined} timeResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.timeResponse = null; + + /** + * Container eventSenderTagsRequest. + * @member {DBMessaging.Protobuf.IEventSenderTagsRequest|null|undefined} eventSenderTagsRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.eventSenderTagsRequest = null; + + /** + * Container eventSenderTagsResponse. + * @member {DBMessaging.Protobuf.IEventSenderTagsResponse|null|undefined} eventSenderTagsResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.eventSenderTagsResponse = null; + + /** + * Container countEventsRequest. + * @member {DBMessaging.Protobuf.ICountEventsRequest|null|undefined} countEventsRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.countEventsRequest = null; + + /** + * Container countEventsResponse. + * @member {DBMessaging.Protobuf.ICountEventsResponse|null|undefined} countEventsResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.countEventsResponse = null; + + /** + * Container eventsRequest. + * @member {DBMessaging.Protobuf.IEventsRequest|null|undefined} eventsRequest + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.eventsRequest = null; + + /** + * Container eventsResponse. + * @member {DBMessaging.Protobuf.IEventsResponse|null|undefined} eventsResponse + * @memberof DBMessaging.Protobuf.Container + * @instance + */ + Container.prototype.eventsResponse = null; + + /** + * Creates a new Container instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {DBMessaging.Protobuf.IContainer=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.Container} Container instance + */ + Container.create = function create(properties) { + return new Container(properties); + }; + + /** + * Encodes the specified Container message. Does not implicitly {@link DBMessaging.Protobuf.Container.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {DBMessaging.Protobuf.IContainer} message Container message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Container.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.messageType != null && Object.hasOwnProperty.call(message, "messageType")) + writer.uint32(/* id 1, wireType 0 =*/8).int32(message.messageType); + if (message.signalInfoRequest != null && Object.hasOwnProperty.call(message, "signalInfoRequest")) + $root.DBMessaging.Protobuf.SignalInfoRequest.encode(message.signalInfoRequest, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.signalInfoResponse != null && Object.hasOwnProperty.call(message, "signalInfoResponse")) + $root.DBMessaging.Protobuf.SignalInfoResponse.encode(message.signalInfoResponse, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.signalDataRequest != null && Object.hasOwnProperty.call(message, "signalDataRequest")) + $root.DBMessaging.Protobuf.SignalDataRequest.encode(message.signalDataRequest, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + if (message.signalDataResponse != null && Object.hasOwnProperty.call(message, "signalDataResponse")) + $root.DBMessaging.Protobuf.SignalDataResponse.encode(message.signalDataResponse, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); + if (message.criterionLimitsRequest != null && Object.hasOwnProperty.call(message, "criterionLimitsRequest")) + $root.DBMessaging.Protobuf.CriterionLimitsRequest.encode(message.criterionLimitsRequest, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); + if (message.criterionLimitsResponse != null && Object.hasOwnProperty.call(message, "criterionLimitsResponse")) + $root.DBMessaging.Protobuf.CriterionLimitsResponse.encode(message.criterionLimitsResponse, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); + if (message.versionRequest != null && Object.hasOwnProperty.call(message, "versionRequest")) + $root.DBMessaging.Protobuf.VersionRequest.encode(message.versionRequest, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); + if (message.versionResponse != null && Object.hasOwnProperty.call(message, "versionResponse")) + $root.DBMessaging.Protobuf.VersionResponse.encode(message.versionResponse, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); + if (message.error != null && Object.hasOwnProperty.call(message, "error")) + $root.DBMessaging.Protobuf.Error.encode(message.error, writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim(); + if (message.timeRequest != null && Object.hasOwnProperty.call(message, "timeRequest")) + $root.DBMessaging.Protobuf.TimeRequest.encode(message.timeRequest, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); + if (message.timeResponse != null && Object.hasOwnProperty.call(message, "timeResponse")) + $root.DBMessaging.Protobuf.TimeResponse.encode(message.timeResponse, writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim(); + if (message.eventSenderTagsRequest != null && Object.hasOwnProperty.call(message, "eventSenderTagsRequest")) + $root.DBMessaging.Protobuf.EventSenderTagsRequest.encode(message.eventSenderTagsRequest, writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); + if (message.eventSenderTagsResponse != null && Object.hasOwnProperty.call(message, "eventSenderTagsResponse")) + $root.DBMessaging.Protobuf.EventSenderTagsResponse.encode(message.eventSenderTagsResponse, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); + if (message.countEventsRequest != null && Object.hasOwnProperty.call(message, "countEventsRequest")) + $root.DBMessaging.Protobuf.CountEventsRequest.encode(message.countEventsRequest, writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); + if (message.countEventsResponse != null && Object.hasOwnProperty.call(message, "countEventsResponse")) + $root.DBMessaging.Protobuf.CountEventsResponse.encode(message.countEventsResponse, writer.uint32(/* id 16, wireType 2 =*/130).fork()).ldelim(); + if (message.eventsRequest != null && Object.hasOwnProperty.call(message, "eventsRequest")) + $root.DBMessaging.Protobuf.EventsRequest.encode(message.eventsRequest, writer.uint32(/* id 17, wireType 2 =*/138).fork()).ldelim(); + if (message.eventsResponse != null && Object.hasOwnProperty.call(message, "eventsResponse")) + $root.DBMessaging.Protobuf.EventsResponse.encode(message.eventsResponse, writer.uint32(/* id 18, wireType 2 =*/146).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Container message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Container.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {DBMessaging.Protobuf.IContainer} message Container message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Container.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Container message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.Container} Container + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Container.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Container(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.messageType = reader.int32(); + break; + } + case 2: { + message.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.decode(reader, reader.uint32()); + break; + } + case 3: { + message.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.decode(reader, reader.uint32()); + break; + } + case 4: { + message.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.decode(reader, reader.uint32()); + break; + } + case 5: { + message.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.decode(reader, reader.uint32()); + break; + } + case 6: { + message.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.decode(reader, reader.uint32()); + break; + } + case 7: { + message.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.decode(reader, reader.uint32()); + break; + } + case 8: { + message.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.decode(reader, reader.uint32()); + break; + } + case 9: { + message.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.decode(reader, reader.uint32()); + break; + } + case 10: { + message.error = $root.DBMessaging.Protobuf.Error.decode(reader, reader.uint32()); + break; + } + case 11: { + message.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.decode(reader, reader.uint32()); + break; + } + case 12: { + message.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.decode(reader, reader.uint32()); + break; + } + case 13: { + message.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.decode(reader, reader.uint32()); + break; + } + case 14: { + message.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.decode(reader, reader.uint32()); + break; + } + case 15: { + message.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.decode(reader, reader.uint32()); + break; + } + case 16: { + message.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.decode(reader, reader.uint32()); + break; + } + case 17: { + message.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.decode(reader, reader.uint32()); + break; + } + case 18: { + message.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Container message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.Container} Container + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Container.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Container message. + * @function verify + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Container.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.messageType != null && message.hasOwnProperty("messageType")) + switch (message.messageType) { + default: + return "messageType: enum value expected"; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + break; + } + if (message.signalInfoRequest != null && message.hasOwnProperty("signalInfoRequest")) { + var error = $root.DBMessaging.Protobuf.SignalInfoRequest.verify(message.signalInfoRequest); + if (error) + return "signalInfoRequest." + error; + } + if (message.signalInfoResponse != null && message.hasOwnProperty("signalInfoResponse")) { + var error = $root.DBMessaging.Protobuf.SignalInfoResponse.verify(message.signalInfoResponse); + if (error) + return "signalInfoResponse." + error; + } + if (message.signalDataRequest != null && message.hasOwnProperty("signalDataRequest")) { + var error = $root.DBMessaging.Protobuf.SignalDataRequest.verify(message.signalDataRequest); + if (error) + return "signalDataRequest." + error; + } + if (message.signalDataResponse != null && message.hasOwnProperty("signalDataResponse")) { + var error = $root.DBMessaging.Protobuf.SignalDataResponse.verify(message.signalDataResponse); + if (error) + return "signalDataResponse." + error; + } + if (message.criterionLimitsRequest != null && message.hasOwnProperty("criterionLimitsRequest")) { + var error = $root.DBMessaging.Protobuf.CriterionLimitsRequest.verify(message.criterionLimitsRequest); + if (error) + return "criterionLimitsRequest." + error; + } + if (message.criterionLimitsResponse != null && message.hasOwnProperty("criterionLimitsResponse")) { + var error = $root.DBMessaging.Protobuf.CriterionLimitsResponse.verify(message.criterionLimitsResponse); + if (error) + return "criterionLimitsResponse." + error; + } + if (message.versionRequest != null && message.hasOwnProperty("versionRequest")) { + var error = $root.DBMessaging.Protobuf.VersionRequest.verify(message.versionRequest); + if (error) + return "versionRequest." + error; + } + if (message.versionResponse != null && message.hasOwnProperty("versionResponse")) { + var error = $root.DBMessaging.Protobuf.VersionResponse.verify(message.versionResponse); + if (error) + return "versionResponse." + error; + } + if (message.error != null && message.hasOwnProperty("error")) { + var error = $root.DBMessaging.Protobuf.Error.verify(message.error); + if (error) + return "error." + error; + } + if (message.timeRequest != null && message.hasOwnProperty("timeRequest")) { + var error = $root.DBMessaging.Protobuf.TimeRequest.verify(message.timeRequest); + if (error) + return "timeRequest." + error; + } + if (message.timeResponse != null && message.hasOwnProperty("timeResponse")) { + var error = $root.DBMessaging.Protobuf.TimeResponse.verify(message.timeResponse); + if (error) + return "timeResponse." + error; + } + if (message.eventSenderTagsRequest != null && message.hasOwnProperty("eventSenderTagsRequest")) { + var error = $root.DBMessaging.Protobuf.EventSenderTagsRequest.verify(message.eventSenderTagsRequest); + if (error) + return "eventSenderTagsRequest." + error; + } + if (message.eventSenderTagsResponse != null && message.hasOwnProperty("eventSenderTagsResponse")) { + var error = $root.DBMessaging.Protobuf.EventSenderTagsResponse.verify(message.eventSenderTagsResponse); + if (error) + return "eventSenderTagsResponse." + error; + } + if (message.countEventsRequest != null && message.hasOwnProperty("countEventsRequest")) { + var error = $root.DBMessaging.Protobuf.CountEventsRequest.verify(message.countEventsRequest); + if (error) + return "countEventsRequest." + error; + } + if (message.countEventsResponse != null && message.hasOwnProperty("countEventsResponse")) { + var error = $root.DBMessaging.Protobuf.CountEventsResponse.verify(message.countEventsResponse); + if (error) + return "countEventsResponse." + error; + } + if (message.eventsRequest != null && message.hasOwnProperty("eventsRequest")) { + var error = $root.DBMessaging.Protobuf.EventsRequest.verify(message.eventsRequest); + if (error) + return "eventsRequest." + error; + } + if (message.eventsResponse != null && message.hasOwnProperty("eventsResponse")) { + var error = $root.DBMessaging.Protobuf.EventsResponse.verify(message.eventsResponse); + if (error) + return "eventsResponse." + error; + } + return null; + }; + + /** + * Creates a Container message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.Container} Container + */ + Container.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.Container) + return object; + var message = new $root.DBMessaging.Protobuf.Container(); + switch (object.messageType) { + default: + if (typeof object.messageType === "number") { + message.messageType = object.messageType; + break; + } + break; + case "eSignalInfoRequest": + case 1: + message.messageType = 1; + break; + case "eSignalInfoResponse": + case 2: + message.messageType = 2; + break; + case "eSignalDataRequest": + case 3: + message.messageType = 3; + break; + case "eSignalDataResponse": + case 4: + message.messageType = 4; + break; + case "eCriterionLimitsRequest": + case 5: + message.messageType = 5; + break; + case "eCriterionLimitsResponse": + case 6: + message.messageType = 6; + break; + case "eVersionRequest": + case 7: + message.messageType = 7; + break; + case "eVersionResponse": + case 8: + message.messageType = 8; + break; + case "eError": + case 9: + message.messageType = 9; + break; + case "eTimeRequest": + case 10: + message.messageType = 10; + break; + case "eTimeResponse": + case 11: + message.messageType = 11; + break; + case "eEventSenderTagsRequest": + case 12: + message.messageType = 12; + break; + case "eEventSenderTagsResponse": + case 13: + message.messageType = 13; + break; + case "eCountEventsRequest": + case 14: + message.messageType = 14; + break; + case "eCountEventsResponse": + case 15: + message.messageType = 15; + break; + case "eEventsRequest": + case 16: + message.messageType = 16; + break; + case "eEventsResponse": + case 17: + message.messageType = 17; + break; + } + if (object.signalInfoRequest != null) { + if (typeof object.signalInfoRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.signalInfoRequest: object expected"); + message.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.fromObject(object.signalInfoRequest); + } + if (object.signalInfoResponse != null) { + if (typeof object.signalInfoResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.signalInfoResponse: object expected"); + message.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.fromObject(object.signalInfoResponse); + } + if (object.signalDataRequest != null) { + if (typeof object.signalDataRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.signalDataRequest: object expected"); + message.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.fromObject(object.signalDataRequest); + } + if (object.signalDataResponse != null) { + if (typeof object.signalDataResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.signalDataResponse: object expected"); + message.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.fromObject(object.signalDataResponse); + } + if (object.criterionLimitsRequest != null) { + if (typeof object.criterionLimitsRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.criterionLimitsRequest: object expected"); + message.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.fromObject(object.criterionLimitsRequest); + } + if (object.criterionLimitsResponse != null) { + if (typeof object.criterionLimitsResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.criterionLimitsResponse: object expected"); + message.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.fromObject(object.criterionLimitsResponse); + } + if (object.versionRequest != null) { + if (typeof object.versionRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.versionRequest: object expected"); + message.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.fromObject(object.versionRequest); + } + if (object.versionResponse != null) { + if (typeof object.versionResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.versionResponse: object expected"); + message.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.fromObject(object.versionResponse); + } + if (object.error != null) { + if (typeof object.error !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.error: object expected"); + message.error = $root.DBMessaging.Protobuf.Error.fromObject(object.error); + } + if (object.timeRequest != null) { + if (typeof object.timeRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.timeRequest: object expected"); + message.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.fromObject(object.timeRequest); + } + if (object.timeResponse != null) { + if (typeof object.timeResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.timeResponse: object expected"); + message.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.fromObject(object.timeResponse); + } + if (object.eventSenderTagsRequest != null) { + if (typeof object.eventSenderTagsRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.eventSenderTagsRequest: object expected"); + message.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.fromObject(object.eventSenderTagsRequest); + } + if (object.eventSenderTagsResponse != null) { + if (typeof object.eventSenderTagsResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.eventSenderTagsResponse: object expected"); + message.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.fromObject(object.eventSenderTagsResponse); + } + if (object.countEventsRequest != null) { + if (typeof object.countEventsRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.countEventsRequest: object expected"); + message.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.fromObject(object.countEventsRequest); + } + if (object.countEventsResponse != null) { + if (typeof object.countEventsResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.countEventsResponse: object expected"); + message.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.fromObject(object.countEventsResponse); + } + if (object.eventsRequest != null) { + if (typeof object.eventsRequest !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.eventsRequest: object expected"); + message.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.fromObject(object.eventsRequest); + } + if (object.eventsResponse != null) { + if (typeof object.eventsResponse !== "object") + throw TypeError(".DBMessaging.Protobuf.Container.eventsResponse: object expected"); + message.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.fromObject(object.eventsResponse); + } + return message; + }; + + /** + * Creates a plain object from a Container message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {DBMessaging.Protobuf.Container} message Container + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Container.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.messageType = options.enums === String ? "eSignalInfoRequest" : 1; + object.signalInfoRequest = null; + object.signalInfoResponse = null; + object.signalDataRequest = null; + object.signalDataResponse = null; + object.criterionLimitsRequest = null; + object.criterionLimitsResponse = null; + object.versionRequest = null; + object.versionResponse = null; + object.error = null; + object.timeRequest = null; + object.timeResponse = null; + object.eventSenderTagsRequest = null; + object.eventSenderTagsResponse = null; + object.countEventsRequest = null; + object.countEventsResponse = null; + object.eventsRequest = null; + object.eventsResponse = null; + } + if (message.messageType != null && message.hasOwnProperty("messageType")) + object.messageType = options.enums === String ? $root.DBMessaging.Protobuf.Container.Type[message.messageType] === undefined ? message.messageType : $root.DBMessaging.Protobuf.Container.Type[message.messageType] : message.messageType; + if (message.signalInfoRequest != null && message.hasOwnProperty("signalInfoRequest")) + object.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.toObject(message.signalInfoRequest, options); + if (message.signalInfoResponse != null && message.hasOwnProperty("signalInfoResponse")) + object.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.toObject(message.signalInfoResponse, options); + if (message.signalDataRequest != null && message.hasOwnProperty("signalDataRequest")) + object.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.toObject(message.signalDataRequest, options); + if (message.signalDataResponse != null && message.hasOwnProperty("signalDataResponse")) + object.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.toObject(message.signalDataResponse, options); + if (message.criterionLimitsRequest != null && message.hasOwnProperty("criterionLimitsRequest")) + object.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.toObject(message.criterionLimitsRequest, options); + if (message.criterionLimitsResponse != null && message.hasOwnProperty("criterionLimitsResponse")) + object.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.toObject(message.criterionLimitsResponse, options); + if (message.versionRequest != null && message.hasOwnProperty("versionRequest")) + object.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.toObject(message.versionRequest, options); + if (message.versionResponse != null && message.hasOwnProperty("versionResponse")) + object.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.toObject(message.versionResponse, options); + if (message.error != null && message.hasOwnProperty("error")) + object.error = $root.DBMessaging.Protobuf.Error.toObject(message.error, options); + if (message.timeRequest != null && message.hasOwnProperty("timeRequest")) + object.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.toObject(message.timeRequest, options); + if (message.timeResponse != null && message.hasOwnProperty("timeResponse")) + object.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.toObject(message.timeResponse, options); + if (message.eventSenderTagsRequest != null && message.hasOwnProperty("eventSenderTagsRequest")) + object.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.toObject(message.eventSenderTagsRequest, options); + if (message.eventSenderTagsResponse != null && message.hasOwnProperty("eventSenderTagsResponse")) + object.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.toObject(message.eventSenderTagsResponse, options); + if (message.countEventsRequest != null && message.hasOwnProperty("countEventsRequest")) + object.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.toObject(message.countEventsRequest, options); + if (message.countEventsResponse != null && message.hasOwnProperty("countEventsResponse")) + object.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.toObject(message.countEventsResponse, options); + if (message.eventsRequest != null && message.hasOwnProperty("eventsRequest")) + object.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.toObject(message.eventsRequest, options); + if (message.eventsResponse != null && message.hasOwnProperty("eventsResponse")) + object.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.toObject(message.eventsResponse, options); + return object; + }; + + /** + * Converts this Container to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.Container + * @instance + * @returns {Object.} JSON object + */ + Container.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Container + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.Container + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Container.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.Container"; + }; + + /** + * Type enum. + * @name DBMessaging.Protobuf.Container.Type + * @enum {number} + * @property {number} eSignalInfoRequest=1 eSignalInfoRequest value + * @property {number} eSignalInfoResponse=2 eSignalInfoResponse value + * @property {number} eSignalDataRequest=3 eSignalDataRequest value + * @property {number} eSignalDataResponse=4 eSignalDataResponse value + * @property {number} eCriterionLimitsRequest=5 eCriterionLimitsRequest value + * @property {number} eCriterionLimitsResponse=6 eCriterionLimitsResponse value + * @property {number} eVersionRequest=7 eVersionRequest value + * @property {number} eVersionResponse=8 eVersionResponse value + * @property {number} eError=9 eError value + * @property {number} eTimeRequest=10 eTimeRequest value + * @property {number} eTimeResponse=11 eTimeResponse value + * @property {number} eEventSenderTagsRequest=12 eEventSenderTagsRequest value + * @property {number} eEventSenderTagsResponse=13 eEventSenderTagsResponse value + * @property {number} eCountEventsRequest=14 eCountEventsRequest value + * @property {number} eCountEventsResponse=15 eCountEventsResponse value + * @property {number} eEventsRequest=16 eEventsRequest value + * @property {number} eEventsResponse=17 eEventsResponse value + */ + Container.Type = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[1] = "eSignalInfoRequest"] = 1; + values[valuesById[2] = "eSignalInfoResponse"] = 2; + values[valuesById[3] = "eSignalDataRequest"] = 3; + values[valuesById[4] = "eSignalDataResponse"] = 4; + values[valuesById[5] = "eCriterionLimitsRequest"] = 5; + values[valuesById[6] = "eCriterionLimitsResponse"] = 6; + values[valuesById[7] = "eVersionRequest"] = 7; + values[valuesById[8] = "eVersionResponse"] = 8; + values[valuesById[9] = "eError"] = 9; + values[valuesById[10] = "eTimeRequest"] = 10; + values[valuesById[11] = "eTimeResponse"] = 11; + values[valuesById[12] = "eEventSenderTagsRequest"] = 12; + values[valuesById[13] = "eEventSenderTagsResponse"] = 13; + values[valuesById[14] = "eCountEventsRequest"] = 14; + values[valuesById[15] = "eCountEventsResponse"] = 15; + values[valuesById[16] = "eEventsRequest"] = 16; + values[valuesById[17] = "eEventsResponse"] = 17; + return values; + })(); + + return Container; + })(); + + Protobuf.SignalInfoRequest = (function() { + + /** + * Properties of a SignalInfoRequest. + * @memberof DBMessaging.Protobuf + * @interface ISignalInfoRequest + * @property {number|null} [requestId] SignalInfoRequest requestId + */ + + /** + * Constructs a new SignalInfoRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a SignalInfoRequest. + * @implements ISignalInfoRequest + * @constructor + * @param {DBMessaging.Protobuf.ISignalInfoRequest=} [properties] Properties to set + */ + function SignalInfoRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SignalInfoRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @instance + */ + SignalInfoRequest.prototype.requestId = 0; + + /** + * Creates a new SignalInfoRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {DBMessaging.Protobuf.ISignalInfoRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest instance + */ + SignalInfoRequest.create = function create(properties) { + return new SignalInfoRequest(properties); + }; + + /** + * Encodes the specified SignalInfoRequest message. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {DBMessaging.Protobuf.ISignalInfoRequest} message SignalInfoRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalInfoRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + return writer; + }; + + /** + * Encodes the specified SignalInfoRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {DBMessaging.Protobuf.ISignalInfoRequest} message SignalInfoRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalInfoRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SignalInfoRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalInfoRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalInfoRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SignalInfoRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalInfoRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SignalInfoRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SignalInfoRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + return null; + }; + + /** + * Creates a SignalInfoRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest + */ + SignalInfoRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.SignalInfoRequest) + return object; + var message = new $root.DBMessaging.Protobuf.SignalInfoRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + return message; + }; + + /** + * Creates a plain object from a SignalInfoRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {DBMessaging.Protobuf.SignalInfoRequest} message SignalInfoRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SignalInfoRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + return object; + }; + + /** + * Converts this SignalInfoRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @instance + * @returns {Object.} JSON object + */ + SignalInfoRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SignalInfoRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.SignalInfoRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SignalInfoRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.SignalInfoRequest"; + }; + + return SignalInfoRequest; + })(); + + Protobuf.SignalInfoResponse = (function() { + + /** + * Properties of a SignalInfoResponse. + * @memberof DBMessaging.Protobuf + * @interface ISignalInfoResponse + * @property {number|null} [requestId] SignalInfoResponse requestId + * @property {Array.|null} [name] SignalInfoResponse name + * @property {Array.|null} [id] SignalInfoResponse id + * @property {Array.|null} [type] SignalInfoResponse type + * @property {Array.|null} [path] SignalInfoResponse path + * @property {Array.|null} [tagMap] SignalInfoResponse tagMap + */ + + /** + * Constructs a new SignalInfoResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a SignalInfoResponse. + * @implements ISignalInfoResponse + * @constructor + * @param {DBMessaging.Protobuf.ISignalInfoResponse=} [properties] Properties to set + */ + function SignalInfoResponse(properties) { + this.name = []; + this.id = []; + this.type = []; + this.path = []; + this.tagMap = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SignalInfoResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.requestId = 0; + + /** + * SignalInfoResponse name. + * @member {Array.} name + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.name = $util.emptyArray; + + /** + * SignalInfoResponse id. + * @member {Array.} id + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.id = $util.emptyArray; + + /** + * SignalInfoResponse type. + * @member {Array.} type + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.type = $util.emptyArray; + + /** + * SignalInfoResponse path. + * @member {Array.} path + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.path = $util.emptyArray; + + /** + * SignalInfoResponse tagMap. + * @member {Array.} tagMap + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + */ + SignalInfoResponse.prototype.tagMap = $util.emptyArray; + + /** + * Creates a new SignalInfoResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {DBMessaging.Protobuf.ISignalInfoResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse instance + */ + SignalInfoResponse.create = function create(properties) { + return new SignalInfoResponse(properties); + }; + + /** + * Encodes the specified SignalInfoResponse message. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {DBMessaging.Protobuf.ISignalInfoResponse} message SignalInfoResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalInfoResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.name != null && message.name.length) + for (var i = 0; i < message.name.length; ++i) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.name[i]); + if (message.id != null && message.id.length) + for (var i = 0; i < message.id.length; ++i) + writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.id[i]); + if (message.type != null && message.type.length) + for (var i = 0; i < message.type.length; ++i) + writer.uint32(/* id 4, wireType 0 =*/32).int32(message.type[i]); + if (message.path != null && message.path.length) + for (var i = 0; i < message.path.length; ++i) + writer.uint32(/* id 5, wireType 2 =*/42).string(message.path[i]); + if (message.tagMap != null && message.tagMap.length) + for (var i = 0; i < message.tagMap.length; ++i) + $root.DBMessaging.Protobuf.TagMap.encode(message.tagMap[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified SignalInfoResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {DBMessaging.Protobuf.ISignalInfoResponse} message SignalInfoResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalInfoResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SignalInfoResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalInfoResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalInfoResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + if (!(message.name && message.name.length)) + message.name = []; + message.name.push(reader.string()); + break; + } + case 3: { + if (!(message.id && message.id.length)) + message.id = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.id.push(reader.uint32()); + } else + message.id.push(reader.uint32()); + break; + } + case 4: { + if (!(message.type && message.type.length)) + message.type = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.type.push(reader.int32()); + } else + message.type.push(reader.int32()); + break; + } + case 5: { + if (!(message.path && message.path.length)) + message.path = []; + message.path.push(reader.string()); + break; + } + case 6: { + if (!(message.tagMap && message.tagMap.length)) + message.tagMap = []; + message.tagMap.push($root.DBMessaging.Protobuf.TagMap.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SignalInfoResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalInfoResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SignalInfoResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SignalInfoResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.name != null && message.hasOwnProperty("name")) { + if (!Array.isArray(message.name)) + return "name: array expected"; + for (var i = 0; i < message.name.length; ++i) + if (!$util.isString(message.name[i])) + return "name: string[] expected"; + } + if (message.id != null && message.hasOwnProperty("id")) { + if (!Array.isArray(message.id)) + return "id: array expected"; + for (var i = 0; i < message.id.length; ++i) + if (!$util.isInteger(message.id[i])) + return "id: integer[] expected"; + } + if (message.type != null && message.hasOwnProperty("type")) { + if (!Array.isArray(message.type)) + return "type: array expected"; + for (var i = 0; i < message.type.length; ++i) + switch (message.type[i]) { + default: + return "type: enum value[] expected"; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 100: + break; + } + } + if (message.path != null && message.hasOwnProperty("path")) { + if (!Array.isArray(message.path)) + return "path: array expected"; + for (var i = 0; i < message.path.length; ++i) + if (!$util.isString(message.path[i])) + return "path: string[] expected"; + } + if (message.tagMap != null && message.hasOwnProperty("tagMap")) { + if (!Array.isArray(message.tagMap)) + return "tagMap: array expected"; + for (var i = 0; i < message.tagMap.length; ++i) { + var error = $root.DBMessaging.Protobuf.TagMap.verify(message.tagMap[i]); + if (error) + return "tagMap." + error; + } + } + return null; + }; + + /** + * Creates a SignalInfoResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse + */ + SignalInfoResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.SignalInfoResponse) + return object; + var message = new $root.DBMessaging.Protobuf.SignalInfoResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.name) { + if (!Array.isArray(object.name)) + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.name: array expected"); + message.name = []; + for (var i = 0; i < object.name.length; ++i) + message.name[i] = String(object.name[i]); + } + if (object.id) { + if (!Array.isArray(object.id)) + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.id: array expected"); + message.id = []; + for (var i = 0; i < object.id.length; ++i) + message.id[i] = object.id[i] >>> 0; + } + if (object.type) { + if (!Array.isArray(object.type)) + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.type: array expected"); + message.type = []; + for (var i = 0; i < object.type.length; ++i) + switch (object.type[i]) { + default: + if (typeof object.type[i] === "number") { + message.type[i] = object.type[i]; + break; + } + case "eUNDEFINED": + case 0: + message.type[i] = 0; + break; + case "eDOUBLE": + case 1: + message.type[i] = 1; + break; + case "eUINT64": + case 2: + message.type[i] = 2; + break; + case "eINT64": + case 3: + message.type[i] = 3; + break; + case "eFLOAT": + case 4: + message.type[i] = 4; + break; + case "eUINT": + case 5: + message.type[i] = 5; + break; + case "eINT": + case 6: + message.type[i] = 6; + break; + case "eUSHORT": + case 7: + message.type[i] = 7; + break; + case "eSHORT": + case 8: + message.type[i] = 8; + break; + case "eUCHAR": + case 9: + message.type[i] = 9; + break; + case "eCHAR": + case 10: + message.type[i] = 10; + break; + case "eBOOL": + case 11: + message.type[i] = 11; + break; + case "eSTRING": + case 12: + message.type[i] = 12; + break; + case "eUSERTYPE": + case 100: + message.type[i] = 100; + break; + } + } + if (object.path) { + if (!Array.isArray(object.path)) + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.path: array expected"); + message.path = []; + for (var i = 0; i < object.path.length; ++i) + message.path[i] = String(object.path[i]); + } + if (object.tagMap) { + if (!Array.isArray(object.tagMap)) + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.tagMap: array expected"); + message.tagMap = []; + for (var i = 0; i < object.tagMap.length; ++i) { + if (typeof object.tagMap[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.tagMap: object expected"); + message.tagMap[i] = $root.DBMessaging.Protobuf.TagMap.fromObject(object.tagMap[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a SignalInfoResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {DBMessaging.Protobuf.SignalInfoResponse} message SignalInfoResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SignalInfoResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.name = []; + object.id = []; + object.type = []; + object.path = []; + object.tagMap = []; + } + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.name && message.name.length) { + object.name = []; + for (var j = 0; j < message.name.length; ++j) + object.name[j] = message.name[j]; + } + if (message.id && message.id.length) { + object.id = []; + for (var j = 0; j < message.id.length; ++j) + object.id[j] = message.id[j]; + } + if (message.type && message.type.length) { + object.type = []; + for (var j = 0; j < message.type.length; ++j) + object.type[j] = options.enums === String ? $root.ICD.Protobuf.CDPValueType[message.type[j]] === undefined ? message.type[j] : $root.ICD.Protobuf.CDPValueType[message.type[j]] : message.type[j]; + } + if (message.path && message.path.length) { + object.path = []; + for (var j = 0; j < message.path.length; ++j) + object.path[j] = message.path[j]; + } + if (message.tagMap && message.tagMap.length) { + object.tagMap = []; + for (var j = 0; j < message.tagMap.length; ++j) + object.tagMap[j] = $root.DBMessaging.Protobuf.TagMap.toObject(message.tagMap[j], options); + } + return object; + }; + + /** + * Converts this SignalInfoResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @instance + * @returns {Object.} JSON object + */ + SignalInfoResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SignalInfoResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.SignalInfoResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SignalInfoResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.SignalInfoResponse"; + }; + + return SignalInfoResponse; + })(); + + Protobuf.TagInfo = (function() { + + /** + * Properties of a TagInfo. + * @memberof DBMessaging.Protobuf + * @interface ITagInfo + * @property {string|null} [value] TagInfo value + * @property {string|null} [source] TagInfo source + */ + + /** + * Constructs a new TagInfo. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a TagInfo. + * @implements ITagInfo + * @constructor + * @param {DBMessaging.Protobuf.ITagInfo=} [properties] Properties to set + */ + function TagInfo(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * TagInfo value. + * @member {string} value + * @memberof DBMessaging.Protobuf.TagInfo + * @instance + */ + TagInfo.prototype.value = ""; + + /** + * TagInfo source. + * @member {string} source + * @memberof DBMessaging.Protobuf.TagInfo + * @instance + */ + TagInfo.prototype.source = ""; + + /** + * Creates a new TagInfo instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {DBMessaging.Protobuf.ITagInfo=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.TagInfo} TagInfo instance + */ + TagInfo.create = function create(properties) { + return new TagInfo(properties); + }; + + /** + * Encodes the specified TagInfo message. Does not implicitly {@link DBMessaging.Protobuf.TagInfo.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {DBMessaging.Protobuf.ITagInfo} message TagInfo message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TagInfo.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.value != null && Object.hasOwnProperty.call(message, "value")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.value); + if (message.source != null && Object.hasOwnProperty.call(message, "source")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.source); + return writer; + }; + + /** + * Encodes the specified TagInfo message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TagInfo.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {DBMessaging.Protobuf.ITagInfo} message TagInfo message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TagInfo.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TagInfo message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.TagInfo} TagInfo + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TagInfo.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TagInfo(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.value = reader.string(); + break; + } + case 2: { + message.source = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TagInfo message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.TagInfo} TagInfo + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TagInfo.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TagInfo message. + * @function verify + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TagInfo.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.value != null && message.hasOwnProperty("value")) + if (!$util.isString(message.value)) + return "value: string expected"; + if (message.source != null && message.hasOwnProperty("source")) + if (!$util.isString(message.source)) + return "source: string expected"; + return null; + }; + + /** + * Creates a TagInfo message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.TagInfo} TagInfo + */ + TagInfo.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.TagInfo) + return object; + var message = new $root.DBMessaging.Protobuf.TagInfo(); + if (object.value != null) + message.value = String(object.value); + if (object.source != null) + message.source = String(object.source); + return message; + }; + + /** + * Creates a plain object from a TagInfo message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {DBMessaging.Protobuf.TagInfo} message TagInfo + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TagInfo.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.value = ""; + object.source = ""; + } + if (message.value != null && message.hasOwnProperty("value")) + object.value = message.value; + if (message.source != null && message.hasOwnProperty("source")) + object.source = message.source; + return object; + }; + + /** + * Converts this TagInfo to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.TagInfo + * @instance + * @returns {Object.} JSON object + */ + TagInfo.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TagInfo + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.TagInfo + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TagInfo.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.TagInfo"; + }; + + return TagInfo; + })(); + + Protobuf.TagMap = (function() { + + /** + * Properties of a TagMap. + * @memberof DBMessaging.Protobuf + * @interface ITagMap + * @property {Object.|null} [tags] TagMap tags + */ + + /** + * Constructs a new TagMap. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a TagMap. + * @implements ITagMap + * @constructor + * @param {DBMessaging.Protobuf.ITagMap=} [properties] Properties to set + */ + function TagMap(properties) { + this.tags = {}; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * TagMap tags. + * @member {Object.} tags + * @memberof DBMessaging.Protobuf.TagMap + * @instance + */ + TagMap.prototype.tags = $util.emptyObject; + + /** + * Creates a new TagMap instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {DBMessaging.Protobuf.ITagMap=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.TagMap} TagMap instance + */ + TagMap.create = function create(properties) { + return new TagMap(properties); + }; + + /** + * Encodes the specified TagMap message. Does not implicitly {@link DBMessaging.Protobuf.TagMap.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {DBMessaging.Protobuf.ITagMap} message TagMap message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TagMap.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.tags != null && Object.hasOwnProperty.call(message, "tags")) + for (var keys = Object.keys(message.tags), i = 0; i < keys.length; ++i) { + writer.uint32(/* id 1, wireType 2 =*/10).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); + $root.DBMessaging.Protobuf.TagInfo.encode(message.tags[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); + } + return writer; + }; + + /** + * Encodes the specified TagMap message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TagMap.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {DBMessaging.Protobuf.ITagMap} message TagMap message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TagMap.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TagMap message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.TagMap} TagMap + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TagMap.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TagMap(), key, value; + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (message.tags === $util.emptyObject) + message.tags = {}; + var end2 = reader.uint32() + reader.pos; + key = ""; + value = null; + while (reader.pos < end2) { + var tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.string(); + break; + case 2: + value = $root.DBMessaging.Protobuf.TagInfo.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag2 & 7); + break; + } + } + message.tags[key] = value; + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TagMap message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.TagMap} TagMap + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TagMap.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TagMap message. + * @function verify + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TagMap.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.tags != null && message.hasOwnProperty("tags")) { + if (!$util.isObject(message.tags)) + return "tags: object expected"; + var key = Object.keys(message.tags); + for (var i = 0; i < key.length; ++i) { + var error = $root.DBMessaging.Protobuf.TagInfo.verify(message.tags[key[i]]); + if (error) + return "tags." + error; + } + } + return null; + }; + + /** + * Creates a TagMap message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.TagMap} TagMap + */ + TagMap.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.TagMap) + return object; + var message = new $root.DBMessaging.Protobuf.TagMap(); + if (object.tags) { + if (typeof object.tags !== "object") + throw TypeError(".DBMessaging.Protobuf.TagMap.tags: object expected"); + message.tags = {}; + for (var keys = Object.keys(object.tags), i = 0; i < keys.length; ++i) { + if (typeof object.tags[keys[i]] !== "object") + throw TypeError(".DBMessaging.Protobuf.TagMap.tags: object expected"); + message.tags[keys[i]] = $root.DBMessaging.Protobuf.TagInfo.fromObject(object.tags[keys[i]]); + } + } + return message; + }; + + /** + * Creates a plain object from a TagMap message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {DBMessaging.Protobuf.TagMap} message TagMap + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TagMap.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.objects || options.defaults) + object.tags = {}; + var keys2; + if (message.tags && (keys2 = Object.keys(message.tags)).length) { + object.tags = {}; + for (var j = 0; j < keys2.length; ++j) + object.tags[keys2[j]] = $root.DBMessaging.Protobuf.TagInfo.toObject(message.tags[keys2[j]], options); + } + return object; + }; + + /** + * Converts this TagMap to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.TagMap + * @instance + * @returns {Object.} JSON object + */ + TagMap.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TagMap + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.TagMap + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TagMap.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.TagMap"; + }; + + return TagMap; + })(); + + Protobuf.SignalDataRequest = (function() { + + /** + * Properties of a SignalDataRequest. + * @memberof DBMessaging.Protobuf + * @interface ISignalDataRequest + * @property {number|null} [requestId] SignalDataRequest requestId + * @property {Array.|null} [signalId] SignalDataRequest signalId + * @property {number|null} [criterionMin] SignalDataRequest criterionMin + * @property {number|null} [criterionMax] SignalDataRequest criterionMax + * @property {number|null} [numOfDatapoints] SignalDataRequest numOfDatapoints + * @property {number|null} [limit] SignalDataRequest limit + */ + + /** + * Constructs a new SignalDataRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a SignalDataRequest. + * @implements ISignalDataRequest + * @constructor + * @param {DBMessaging.Protobuf.ISignalDataRequest=} [properties] Properties to set + */ + function SignalDataRequest(properties) { + this.signalId = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SignalDataRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.requestId = 0; + + /** + * SignalDataRequest signalId. + * @member {Array.} signalId + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.signalId = $util.emptyArray; + + /** + * SignalDataRequest criterionMin. + * @member {number} criterionMin + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.criterionMin = 0; + + /** + * SignalDataRequest criterionMax. + * @member {number} criterionMax + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.criterionMax = 0; + + /** + * SignalDataRequest numOfDatapoints. + * @member {number} numOfDatapoints + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.numOfDatapoints = 0; + + /** + * SignalDataRequest limit. + * @member {number} limit + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + */ + SignalDataRequest.prototype.limit = 0; + + /** + * Creates a new SignalDataRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {DBMessaging.Protobuf.ISignalDataRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest instance + */ + SignalDataRequest.create = function create(properties) { + return new SignalDataRequest(properties); + }; + + /** + * Encodes the specified SignalDataRequest message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {DBMessaging.Protobuf.ISignalDataRequest} message SignalDataRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.signalId != null && message.signalId.length) + for (var i = 0; i < message.signalId.length; ++i) + writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.signalId[i]); + if (message.criterionMin != null && Object.hasOwnProperty.call(message, "criterionMin")) + writer.uint32(/* id 3, wireType 1 =*/25).double(message.criterionMin); + if (message.criterionMax != null && Object.hasOwnProperty.call(message, "criterionMax")) + writer.uint32(/* id 4, wireType 1 =*/33).double(message.criterionMax); + if (message.numOfDatapoints != null && Object.hasOwnProperty.call(message, "numOfDatapoints")) + writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.numOfDatapoints); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.limit); + return writer; + }; + + /** + * Encodes the specified SignalDataRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {DBMessaging.Protobuf.ISignalDataRequest} message SignalDataRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SignalDataRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + if (!(message.signalId && message.signalId.length)) + message.signalId = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.signalId.push(reader.uint32()); + } else + message.signalId.push(reader.uint32()); + break; + } + case 3: { + message.criterionMin = reader.double(); + break; + } + case 4: { + message.criterionMax = reader.double(); + break; + } + case 5: { + message.numOfDatapoints = reader.uint32(); + break; + } + case 6: { + message.limit = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SignalDataRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SignalDataRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SignalDataRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.signalId != null && message.hasOwnProperty("signalId")) { + if (!Array.isArray(message.signalId)) + return "signalId: array expected"; + for (var i = 0; i < message.signalId.length; ++i) + if (!$util.isInteger(message.signalId[i])) + return "signalId: integer[] expected"; + } + if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) + if (typeof message.criterionMin !== "number") + return "criterionMin: number expected"; + if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) + if (typeof message.criterionMax !== "number") + return "criterionMax: number expected"; + if (message.numOfDatapoints != null && message.hasOwnProperty("numOfDatapoints")) + if (!$util.isInteger(message.numOfDatapoints)) + return "numOfDatapoints: integer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) + if (!$util.isInteger(message.limit)) + return "limit: integer expected"; + return null; + }; + + /** + * Creates a SignalDataRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest + */ + SignalDataRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.SignalDataRequest) + return object; + var message = new $root.DBMessaging.Protobuf.SignalDataRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.signalId) { + if (!Array.isArray(object.signalId)) + throw TypeError(".DBMessaging.Protobuf.SignalDataRequest.signalId: array expected"); + message.signalId = []; + for (var i = 0; i < object.signalId.length; ++i) + message.signalId[i] = object.signalId[i] >>> 0; + } + if (object.criterionMin != null) + message.criterionMin = Number(object.criterionMin); + if (object.criterionMax != null) + message.criterionMax = Number(object.criterionMax); + if (object.numOfDatapoints != null) + message.numOfDatapoints = object.numOfDatapoints >>> 0; + if (object.limit != null) + message.limit = object.limit >>> 0; + return message; + }; + + /** + * Creates a plain object from a SignalDataRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {DBMessaging.Protobuf.SignalDataRequest} message SignalDataRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SignalDataRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.signalId = []; + if (options.defaults) { + object.requestId = 0; + object.criterionMin = 0; + object.criterionMax = 0; + object.numOfDatapoints = 0; + object.limit = 0; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.signalId && message.signalId.length) { + object.signalId = []; + for (var j = 0; j < message.signalId.length; ++j) + object.signalId[j] = message.signalId[j]; + } + if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) + object.criterionMin = options.json && !isFinite(message.criterionMin) ? String(message.criterionMin) : message.criterionMin; + if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) + object.criterionMax = options.json && !isFinite(message.criterionMax) ? String(message.criterionMax) : message.criterionMax; + if (message.numOfDatapoints != null && message.hasOwnProperty("numOfDatapoints")) + object.numOfDatapoints = message.numOfDatapoints; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = message.limit; + return object; + }; + + /** + * Converts this SignalDataRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @instance + * @returns {Object.} JSON object + */ + SignalDataRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SignalDataRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.SignalDataRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SignalDataRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataRequest"; + }; + + return SignalDataRequest; + })(); + + Protobuf.SignalDataResponse = (function() { + + /** + * Properties of a SignalDataResponse. + * @memberof DBMessaging.Protobuf + * @interface ISignalDataResponse + * @property {number|null} [requestId] SignalDataResponse requestId + * @property {Array.|null} [criterion] SignalDataResponse criterion + * @property {Array.|null} [row] SignalDataResponse row + */ + + /** + * Constructs a new SignalDataResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a SignalDataResponse. + * @implements ISignalDataResponse + * @constructor + * @param {DBMessaging.Protobuf.ISignalDataResponse=} [properties] Properties to set + */ + function SignalDataResponse(properties) { + this.criterion = []; + this.row = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SignalDataResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @instance + */ + SignalDataResponse.prototype.requestId = 0; + + /** + * SignalDataResponse criterion. + * @member {Array.} criterion + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @instance + */ + SignalDataResponse.prototype.criterion = $util.emptyArray; + + /** + * SignalDataResponse row. + * @member {Array.} row + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @instance + */ + SignalDataResponse.prototype.row = $util.emptyArray; + + /** + * Creates a new SignalDataResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {DBMessaging.Protobuf.ISignalDataResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse instance + */ + SignalDataResponse.create = function create(properties) { + return new SignalDataResponse(properties); + }; + + /** + * Encodes the specified SignalDataResponse message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {DBMessaging.Protobuf.ISignalDataResponse} message SignalDataResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.criterion != null && message.criterion.length) + for (var i = 0; i < message.criterion.length; ++i) + writer.uint32(/* id 2, wireType 1 =*/17).double(message.criterion[i]); + if (message.row != null && message.row.length) + for (var i = 0; i < message.row.length; ++i) + $root.DBMessaging.Protobuf.SignalDataRow.encode(message.row[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified SignalDataResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {DBMessaging.Protobuf.ISignalDataResponse} message SignalDataResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SignalDataResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + if (!(message.criterion && message.criterion.length)) + message.criterion = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.criterion.push(reader.double()); + } else + message.criterion.push(reader.double()); + break; + } + case 3: { + if (!(message.row && message.row.length)) + message.row = []; + message.row.push($root.DBMessaging.Protobuf.SignalDataRow.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SignalDataResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SignalDataResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SignalDataResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.criterion != null && message.hasOwnProperty("criterion")) { + if (!Array.isArray(message.criterion)) + return "criterion: array expected"; + for (var i = 0; i < message.criterion.length; ++i) + if (typeof message.criterion[i] !== "number") + return "criterion: number[] expected"; + } + if (message.row != null && message.hasOwnProperty("row")) { + if (!Array.isArray(message.row)) + return "row: array expected"; + for (var i = 0; i < message.row.length; ++i) { + var error = $root.DBMessaging.Protobuf.SignalDataRow.verify(message.row[i]); + if (error) + return "row." + error; + } + } + return null; + }; + + /** + * Creates a SignalDataResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse + */ + SignalDataResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.SignalDataResponse) + return object; + var message = new $root.DBMessaging.Protobuf.SignalDataResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.criterion) { + if (!Array.isArray(object.criterion)) + throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.criterion: array expected"); + message.criterion = []; + for (var i = 0; i < object.criterion.length; ++i) + message.criterion[i] = Number(object.criterion[i]); + } + if (object.row) { + if (!Array.isArray(object.row)) + throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.row: array expected"); + message.row = []; + for (var i = 0; i < object.row.length; ++i) { + if (typeof object.row[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.row: object expected"); + message.row[i] = $root.DBMessaging.Protobuf.SignalDataRow.fromObject(object.row[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a SignalDataResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {DBMessaging.Protobuf.SignalDataResponse} message SignalDataResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SignalDataResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.criterion = []; + object.row = []; + } + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.criterion && message.criterion.length) { + object.criterion = []; + for (var j = 0; j < message.criterion.length; ++j) + object.criterion[j] = options.json && !isFinite(message.criterion[j]) ? String(message.criterion[j]) : message.criterion[j]; + } + if (message.row && message.row.length) { + object.row = []; + for (var j = 0; j < message.row.length; ++j) + object.row[j] = $root.DBMessaging.Protobuf.SignalDataRow.toObject(message.row[j], options); + } + return object; + }; + + /** + * Converts this SignalDataResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @instance + * @returns {Object.} JSON object + */ + SignalDataResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SignalDataResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.SignalDataResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SignalDataResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataResponse"; + }; + + return SignalDataResponse; + })(); + + Protobuf.SignalDataRow = (function() { + + /** + * Properties of a SignalDataRow. + * @memberof DBMessaging.Protobuf + * @interface ISignalDataRow + * @property {Array.|null} [signalId] SignalDataRow signalId + * @property {Array.|null} [minValues] SignalDataRow minValues + * @property {Array.|null} [maxValues] SignalDataRow maxValues + * @property {Array.|null} [lastValues] SignalDataRow lastValues + */ + + /** + * Constructs a new SignalDataRow. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a SignalDataRow. + * @implements ISignalDataRow + * @constructor + * @param {DBMessaging.Protobuf.ISignalDataRow=} [properties] Properties to set + */ + function SignalDataRow(properties) { + this.signalId = []; + this.minValues = []; + this.maxValues = []; + this.lastValues = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * SignalDataRow signalId. + * @member {Array.} signalId + * @memberof DBMessaging.Protobuf.SignalDataRow + * @instance + */ + SignalDataRow.prototype.signalId = $util.emptyArray; + + /** + * SignalDataRow minValues. + * @member {Array.} minValues + * @memberof DBMessaging.Protobuf.SignalDataRow + * @instance + */ + SignalDataRow.prototype.minValues = $util.emptyArray; + + /** + * SignalDataRow maxValues. + * @member {Array.} maxValues + * @memberof DBMessaging.Protobuf.SignalDataRow + * @instance + */ + SignalDataRow.prototype.maxValues = $util.emptyArray; + + /** + * SignalDataRow lastValues. + * @member {Array.} lastValues + * @memberof DBMessaging.Protobuf.SignalDataRow + * @instance + */ + SignalDataRow.prototype.lastValues = $util.emptyArray; + + /** + * Creates a new SignalDataRow instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {DBMessaging.Protobuf.ISignalDataRow=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow instance + */ + SignalDataRow.create = function create(properties) { + return new SignalDataRow(properties); + }; + + /** + * Encodes the specified SignalDataRow message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRow.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {DBMessaging.Protobuf.ISignalDataRow} message SignalDataRow message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataRow.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.signalId != null && message.signalId.length) + for (var i = 0; i < message.signalId.length; ++i) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.signalId[i]); + if (message.minValues != null && message.minValues.length) + for (var i = 0; i < message.minValues.length; ++i) + $root.ICD.Protobuf.VariantValue.encode(message.minValues[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.maxValues != null && message.maxValues.length) + for (var i = 0; i < message.maxValues.length; ++i) + $root.ICD.Protobuf.VariantValue.encode(message.maxValues[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.lastValues != null && message.lastValues.length) + for (var i = 0; i < message.lastValues.length; ++i) + $root.ICD.Protobuf.VariantValue.encode(message.lastValues[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified SignalDataRow message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRow.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {DBMessaging.Protobuf.ISignalDataRow} message SignalDataRow message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SignalDataRow.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SignalDataRow message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataRow.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataRow(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.signalId && message.signalId.length)) + message.signalId = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.signalId.push(reader.uint32()); + } else + message.signalId.push(reader.uint32()); + break; + } + case 2: { + if (!(message.minValues && message.minValues.length)) + message.minValues = []; + message.minValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); + break; + } + case 3: { + if (!(message.maxValues && message.maxValues.length)) + message.maxValues = []; + message.maxValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); + break; + } + case 4: { + if (!(message.lastValues && message.lastValues.length)) + message.lastValues = []; + message.lastValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SignalDataRow message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SignalDataRow.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SignalDataRow message. + * @function verify + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SignalDataRow.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.signalId != null && message.hasOwnProperty("signalId")) { + if (!Array.isArray(message.signalId)) + return "signalId: array expected"; + for (var i = 0; i < message.signalId.length; ++i) + if (!$util.isInteger(message.signalId[i])) + return "signalId: integer[] expected"; + } + if (message.minValues != null && message.hasOwnProperty("minValues")) { + if (!Array.isArray(message.minValues)) + return "minValues: array expected"; + for (var i = 0; i < message.minValues.length; ++i) { + var error = $root.ICD.Protobuf.VariantValue.verify(message.minValues[i]); + if (error) + return "minValues." + error; + } + } + if (message.maxValues != null && message.hasOwnProperty("maxValues")) { + if (!Array.isArray(message.maxValues)) + return "maxValues: array expected"; + for (var i = 0; i < message.maxValues.length; ++i) { + var error = $root.ICD.Protobuf.VariantValue.verify(message.maxValues[i]); + if (error) + return "maxValues." + error; + } + } + if (message.lastValues != null && message.hasOwnProperty("lastValues")) { + if (!Array.isArray(message.lastValues)) + return "lastValues: array expected"; + for (var i = 0; i < message.lastValues.length; ++i) { + var error = $root.ICD.Protobuf.VariantValue.verify(message.lastValues[i]); + if (error) + return "lastValues." + error; + } + } + return null; + }; + + /** + * Creates a SignalDataRow message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow + */ + SignalDataRow.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.SignalDataRow) + return object; + var message = new $root.DBMessaging.Protobuf.SignalDataRow(); + if (object.signalId) { + if (!Array.isArray(object.signalId)) + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.signalId: array expected"); + message.signalId = []; + for (var i = 0; i < object.signalId.length; ++i) + message.signalId[i] = object.signalId[i] >>> 0; + } + if (object.minValues) { + if (!Array.isArray(object.minValues)) + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.minValues: array expected"); + message.minValues = []; + for (var i = 0; i < object.minValues.length; ++i) { + if (typeof object.minValues[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.minValues: object expected"); + message.minValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.minValues[i]); + } + } + if (object.maxValues) { + if (!Array.isArray(object.maxValues)) + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.maxValues: array expected"); + message.maxValues = []; + for (var i = 0; i < object.maxValues.length; ++i) { + if (typeof object.maxValues[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.maxValues: object expected"); + message.maxValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.maxValues[i]); + } + } + if (object.lastValues) { + if (!Array.isArray(object.lastValues)) + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.lastValues: array expected"); + message.lastValues = []; + for (var i = 0; i < object.lastValues.length; ++i) { + if (typeof object.lastValues[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.SignalDataRow.lastValues: object expected"); + message.lastValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.lastValues[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a SignalDataRow message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {DBMessaging.Protobuf.SignalDataRow} message SignalDataRow + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SignalDataRow.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.signalId = []; + object.minValues = []; + object.maxValues = []; + object.lastValues = []; + } + if (message.signalId && message.signalId.length) { + object.signalId = []; + for (var j = 0; j < message.signalId.length; ++j) + object.signalId[j] = message.signalId[j]; + } + if (message.minValues && message.minValues.length) { + object.minValues = []; + for (var j = 0; j < message.minValues.length; ++j) + object.minValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.minValues[j], options); + } + if (message.maxValues && message.maxValues.length) { + object.maxValues = []; + for (var j = 0; j < message.maxValues.length; ++j) + object.maxValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.maxValues[j], options); + } + if (message.lastValues && message.lastValues.length) { + object.lastValues = []; + for (var j = 0; j < message.lastValues.length; ++j) + object.lastValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.lastValues[j], options); + } + return object; + }; + + /** + * Converts this SignalDataRow to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.SignalDataRow + * @instance + * @returns {Object.} JSON object + */ + SignalDataRow.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SignalDataRow + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.SignalDataRow + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SignalDataRow.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataRow"; + }; + + return SignalDataRow; + })(); + + Protobuf.CriterionLimitsRequest = (function() { + + /** + * Properties of a CriterionLimitsRequest. + * @memberof DBMessaging.Protobuf + * @interface ICriterionLimitsRequest + * @property {number|null} [requestId] CriterionLimitsRequest requestId + */ + + /** + * Constructs a new CriterionLimitsRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a CriterionLimitsRequest. + * @implements ICriterionLimitsRequest + * @constructor + * @param {DBMessaging.Protobuf.ICriterionLimitsRequest=} [properties] Properties to set + */ + function CriterionLimitsRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * CriterionLimitsRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @instance + */ + CriterionLimitsRequest.prototype.requestId = 0; + + /** + * Creates a new CriterionLimitsRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest instance + */ + CriterionLimitsRequest.create = function create(properties) { + return new CriterionLimitsRequest(properties); + }; + + /** + * Encodes the specified CriterionLimitsRequest message. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsRequest} message CriterionLimitsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CriterionLimitsRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + return writer; + }; + + /** + * Encodes the specified CriterionLimitsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsRequest} message CriterionLimitsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CriterionLimitsRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a CriterionLimitsRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CriterionLimitsRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CriterionLimitsRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a CriterionLimitsRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CriterionLimitsRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a CriterionLimitsRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CriterionLimitsRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + return null; + }; + + /** + * Creates a CriterionLimitsRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest + */ + CriterionLimitsRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.CriterionLimitsRequest) + return object; + var message = new $root.DBMessaging.Protobuf.CriterionLimitsRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + return message; + }; + + /** + * Creates a plain object from a CriterionLimitsRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {DBMessaging.Protobuf.CriterionLimitsRequest} message CriterionLimitsRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CriterionLimitsRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + return object; + }; + + /** + * Converts this CriterionLimitsRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @instance + * @returns {Object.} JSON object + */ + CriterionLimitsRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for CriterionLimitsRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.CriterionLimitsRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + CriterionLimitsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.CriterionLimitsRequest"; + }; + + return CriterionLimitsRequest; + })(); + + Protobuf.CriterionLimitsResponse = (function() { + + /** + * Properties of a CriterionLimitsResponse. + * @memberof DBMessaging.Protobuf + * @interface ICriterionLimitsResponse + * @property {number|null} [requestId] CriterionLimitsResponse requestId + * @property {number|null} [criterionMin] CriterionLimitsResponse criterionMin + * @property {number|null} [criterionMax] CriterionLimitsResponse criterionMax + */ + + /** + * Constructs a new CriterionLimitsResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a CriterionLimitsResponse. + * @implements ICriterionLimitsResponse + * @constructor + * @param {DBMessaging.Protobuf.ICriterionLimitsResponse=} [properties] Properties to set + */ + function CriterionLimitsResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * CriterionLimitsResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @instance + */ + CriterionLimitsResponse.prototype.requestId = 0; + + /** + * CriterionLimitsResponse criterionMin. + * @member {number} criterionMin + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @instance + */ + CriterionLimitsResponse.prototype.criterionMin = 0; + + /** + * CriterionLimitsResponse criterionMax. + * @member {number} criterionMax + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @instance + */ + CriterionLimitsResponse.prototype.criterionMax = 0; + + /** + * Creates a new CriterionLimitsResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse instance + */ + CriterionLimitsResponse.create = function create(properties) { + return new CriterionLimitsResponse(properties); + }; + + /** + * Encodes the specified CriterionLimitsResponse message. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsResponse} message CriterionLimitsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CriterionLimitsResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.criterionMin != null && Object.hasOwnProperty.call(message, "criterionMin")) + writer.uint32(/* id 2, wireType 1 =*/17).double(message.criterionMin); + if (message.criterionMax != null && Object.hasOwnProperty.call(message, "criterionMax")) + writer.uint32(/* id 3, wireType 1 =*/25).double(message.criterionMax); + return writer; + }; + + /** + * Encodes the specified CriterionLimitsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {DBMessaging.Protobuf.ICriterionLimitsResponse} message CriterionLimitsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CriterionLimitsResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a CriterionLimitsResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CriterionLimitsResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CriterionLimitsResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.criterionMin = reader.double(); + break; + } + case 3: { + message.criterionMax = reader.double(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a CriterionLimitsResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CriterionLimitsResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a CriterionLimitsResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CriterionLimitsResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) + if (typeof message.criterionMin !== "number") + return "criterionMin: number expected"; + if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) + if (typeof message.criterionMax !== "number") + return "criterionMax: number expected"; + return null; + }; + + /** + * Creates a CriterionLimitsResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse + */ + CriterionLimitsResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.CriterionLimitsResponse) + return object; + var message = new $root.DBMessaging.Protobuf.CriterionLimitsResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.criterionMin != null) + message.criterionMin = Number(object.criterionMin); + if (object.criterionMax != null) + message.criterionMax = Number(object.criterionMax); + return message; + }; + + /** + * Creates a plain object from a CriterionLimitsResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {DBMessaging.Protobuf.CriterionLimitsResponse} message CriterionLimitsResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CriterionLimitsResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + object.criterionMin = 0; + object.criterionMax = 0; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) + object.criterionMin = options.json && !isFinite(message.criterionMin) ? String(message.criterionMin) : message.criterionMin; + if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) + object.criterionMax = options.json && !isFinite(message.criterionMax) ? String(message.criterionMax) : message.criterionMax; + return object; + }; + + /** + * Converts this CriterionLimitsResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @instance + * @returns {Object.} JSON object + */ + CriterionLimitsResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for CriterionLimitsResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.CriterionLimitsResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + CriterionLimitsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.CriterionLimitsResponse"; + }; + + return CriterionLimitsResponse; + })(); + + Protobuf.Event = (function() { + + /** + * Properties of an Event. + * @memberof DBMessaging.Protobuf + * @interface IEvent + * @property {string|null} [sender] Event sender + * @property {Object.|null} [data] Event data + * @property {number|null} [timestampSec] Event timestampSec + * @property {number|Long|null} [id] Event id + * @property {number|null} [code] Event code + * @property {number|null} [status] Event status + * @property {number|null} [logstampSec] Event logstampSec + */ + + /** + * Constructs a new Event. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an Event. + * @implements IEvent + * @constructor + * @param {DBMessaging.Protobuf.IEvent=} [properties] Properties to set + */ + function Event(properties) { + this.data = {}; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Event sender. + * @member {string} sender + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.sender = ""; + + /** + * Event data. + * @member {Object.} data + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.data = $util.emptyObject; + + /** + * Event timestampSec. + * @member {number} timestampSec + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.timestampSec = 0; + + /** + * Event id. + * @member {number|Long} id + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.id = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Event code. + * @member {number} code + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.code = 0; + + /** + * Event status. + * @member {number} status + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.status = 0; + + /** + * Event logstampSec. + * @member {number} logstampSec + * @memberof DBMessaging.Protobuf.Event + * @instance + */ + Event.prototype.logstampSec = 0; + + /** + * Creates a new Event instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {DBMessaging.Protobuf.IEvent=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.Event} Event instance + */ + Event.create = function create(properties) { + return new Event(properties); + }; + + /** + * Encodes the specified Event message. Does not implicitly {@link DBMessaging.Protobuf.Event.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {DBMessaging.Protobuf.IEvent} message Event message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Event.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.sender != null && Object.hasOwnProperty.call(message, "sender")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.sender); + if (message.data != null && Object.hasOwnProperty.call(message, "data")) + for (var keys = Object.keys(message.data), i = 0; i < keys.length; ++i) + writer.uint32(/* id 2, wireType 2 =*/18).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.data[keys[i]]).ldelim(); + if (message.timestampSec != null && Object.hasOwnProperty.call(message, "timestampSec")) + writer.uint32(/* id 3, wireType 1 =*/25).double(message.timestampSec); + if (message.id != null && Object.hasOwnProperty.call(message, "id")) + writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.id); + if (message.code != null && Object.hasOwnProperty.call(message, "code")) + writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.code); + if (message.status != null && Object.hasOwnProperty.call(message, "status")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.status); + if (message.logstampSec != null && Object.hasOwnProperty.call(message, "logstampSec")) + writer.uint32(/* id 7, wireType 1 =*/57).double(message.logstampSec); + return writer; + }; + + /** + * Encodes the specified Event message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Event.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {DBMessaging.Protobuf.IEvent} message Event message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Event.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Event message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.Event} Event + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Event.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Event(), key, value; + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.sender = reader.string(); + break; + } + case 2: { + if (message.data === $util.emptyObject) + message.data = {}; + var end2 = reader.uint32() + reader.pos; + key = ""; + value = ""; + while (reader.pos < end2) { + var tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.string(); + break; + case 2: + value = reader.string(); + break; + default: + reader.skipType(tag2 & 7); + break; + } + } + message.data[key] = value; + break; + } + case 3: { + message.timestampSec = reader.double(); + break; + } + case 4: { + message.id = reader.uint64(); + break; + } + case 5: { + message.code = reader.uint32(); + break; + } + case 6: { + message.status = reader.uint32(); + break; + } + case 7: { + message.logstampSec = reader.double(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Event message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.Event} Event + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Event.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Event message. + * @function verify + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Event.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.sender != null && message.hasOwnProperty("sender")) + if (!$util.isString(message.sender)) + return "sender: string expected"; + if (message.data != null && message.hasOwnProperty("data")) { + if (!$util.isObject(message.data)) + return "data: object expected"; + var key = Object.keys(message.data); + for (var i = 0; i < key.length; ++i) + if (!$util.isString(message.data[key[i]])) + return "data: string{k:string} expected"; + } + if (message.timestampSec != null && message.hasOwnProperty("timestampSec")) + if (typeof message.timestampSec !== "number") + return "timestampSec: number expected"; + if (message.id != null && message.hasOwnProperty("id")) + if (!$util.isInteger(message.id) && !(message.id && $util.isInteger(message.id.low) && $util.isInteger(message.id.high))) + return "id: integer|Long expected"; + if (message.code != null && message.hasOwnProperty("code")) + if (!$util.isInteger(message.code)) + return "code: integer expected"; + if (message.status != null && message.hasOwnProperty("status")) + if (!$util.isInteger(message.status)) + return "status: integer expected"; + if (message.logstampSec != null && message.hasOwnProperty("logstampSec")) + if (typeof message.logstampSec !== "number") + return "logstampSec: number expected"; + return null; + }; + + /** + * Creates an Event message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.Event} Event + */ + Event.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.Event) + return object; + var message = new $root.DBMessaging.Protobuf.Event(); + if (object.sender != null) + message.sender = String(object.sender); + if (object.data) { + if (typeof object.data !== "object") + throw TypeError(".DBMessaging.Protobuf.Event.data: object expected"); + message.data = {}; + for (var keys = Object.keys(object.data), i = 0; i < keys.length; ++i) + message.data[keys[i]] = String(object.data[keys[i]]); + } + if (object.timestampSec != null) + message.timestampSec = Number(object.timestampSec); + if (object.id != null) + if ($util.Long) + (message.id = $util.Long.fromValue(object.id)).unsigned = true; + else if (typeof object.id === "string") + message.id = parseInt(object.id, 10); + else if (typeof object.id === "number") + message.id = object.id; + else if (typeof object.id === "object") + message.id = new $util.LongBits(object.id.low >>> 0, object.id.high >>> 0).toNumber(true); + if (object.code != null) + message.code = object.code >>> 0; + if (object.status != null) + message.status = object.status >>> 0; + if (object.logstampSec != null) + message.logstampSec = Number(object.logstampSec); + return message; + }; + + /** + * Creates a plain object from an Event message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {DBMessaging.Protobuf.Event} message Event + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Event.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.objects || options.defaults) + object.data = {}; + if (options.defaults) { + object.sender = ""; + object.timestampSec = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.id = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.id = options.longs === String ? "0" : 0; + object.code = 0; + object.status = 0; + object.logstampSec = 0; + } + if (message.sender != null && message.hasOwnProperty("sender")) + object.sender = message.sender; + var keys2; + if (message.data && (keys2 = Object.keys(message.data)).length) { + object.data = {}; + for (var j = 0; j < keys2.length; ++j) + object.data[keys2[j]] = message.data[keys2[j]]; + } + if (message.timestampSec != null && message.hasOwnProperty("timestampSec")) + object.timestampSec = options.json && !isFinite(message.timestampSec) ? String(message.timestampSec) : message.timestampSec; + if (message.id != null && message.hasOwnProperty("id")) + if (typeof message.id === "number") + object.id = options.longs === String ? String(message.id) : message.id; + else + object.id = options.longs === String ? $util.Long.prototype.toString.call(message.id) : options.longs === Number ? new $util.LongBits(message.id.low >>> 0, message.id.high >>> 0).toNumber(true) : message.id; + if (message.code != null && message.hasOwnProperty("code")) + object.code = message.code; + if (message.status != null && message.hasOwnProperty("status")) + object.status = message.status; + if (message.logstampSec != null && message.hasOwnProperty("logstampSec")) + object.logstampSec = options.json && !isFinite(message.logstampSec) ? String(message.logstampSec) : message.logstampSec; + return object; + }; + + /** + * Converts this Event to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.Event + * @instance + * @returns {Object.} JSON object + */ + Event.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Event + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.Event + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Event.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.Event"; + }; + + return Event; + })(); + + Protobuf.EventQuery = (function() { + + /** + * Properties of an EventQuery. + * @memberof DBMessaging.Protobuf + * @interface IEventQuery + * @property {number|null} [timeRangeBegin] EventQuery timeRangeBegin + * @property {number|null} [timeRangeEnd] EventQuery timeRangeEnd + * @property {number|null} [codeMask] EventQuery codeMask + * @property {number|null} [limit] EventQuery limit + * @property {number|null} [offset] EventQuery offset + * @property {number|null} [flags] EventQuery flags + * @property {DBMessaging.Protobuf.EventQuery.IConditionList|null} [senderConditions] EventQuery senderConditions + * @property {Object.|null} [dataConditions] EventQuery dataConditions + */ + + /** + * Constructs a new EventQuery. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an EventQuery. + * @implements IEventQuery + * @constructor + * @param {DBMessaging.Protobuf.IEventQuery=} [properties] Properties to set + */ + function EventQuery(properties) { + this.dataConditions = {}; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * EventQuery timeRangeBegin. + * @member {number} timeRangeBegin + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.timeRangeBegin = 0; + + /** + * EventQuery timeRangeEnd. + * @member {number} timeRangeEnd + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.timeRangeEnd = 0; + + /** + * EventQuery codeMask. + * @member {number} codeMask + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.codeMask = 0; + + /** + * EventQuery limit. + * @member {number} limit + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.limit = 0; + + /** + * EventQuery offset. + * @member {number} offset + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.offset = 0; + + /** + * EventQuery flags. + * @member {number} flags + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.flags = 0; + + /** + * EventQuery senderConditions. + * @member {DBMessaging.Protobuf.EventQuery.IConditionList|null|undefined} senderConditions + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.senderConditions = null; + + /** + * EventQuery dataConditions. + * @member {Object.} dataConditions + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + */ + EventQuery.prototype.dataConditions = $util.emptyObject; + + /** + * Creates a new EventQuery instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {DBMessaging.Protobuf.IEventQuery=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventQuery} EventQuery instance + */ + EventQuery.create = function create(properties) { + return new EventQuery(properties); + }; + + /** + * Encodes the specified EventQuery message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {DBMessaging.Protobuf.IEventQuery} message EventQuery message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventQuery.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.timeRangeBegin != null && Object.hasOwnProperty.call(message, "timeRangeBegin")) + writer.uint32(/* id 1, wireType 1 =*/9).double(message.timeRangeBegin); + if (message.timeRangeEnd != null && Object.hasOwnProperty.call(message, "timeRangeEnd")) + writer.uint32(/* id 2, wireType 1 =*/17).double(message.timeRangeEnd); + if (message.codeMask != null && Object.hasOwnProperty.call(message, "codeMask")) + writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.codeMask); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.limit); + if (message.offset != null && Object.hasOwnProperty.call(message, "offset")) + writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.offset); + if (message.flags != null && Object.hasOwnProperty.call(message, "flags")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.flags); + if (message.senderConditions != null && Object.hasOwnProperty.call(message, "senderConditions")) + $root.DBMessaging.Protobuf.EventQuery.ConditionList.encode(message.senderConditions, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); + if (message.dataConditions != null && Object.hasOwnProperty.call(message, "dataConditions")) + for (var keys = Object.keys(message.dataConditions), i = 0; i < keys.length; ++i) { + writer.uint32(/* id 8, wireType 2 =*/66).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); + $root.DBMessaging.Protobuf.EventQuery.ConditionList.encode(message.dataConditions[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); + } + return writer; + }; + + /** + * Encodes the specified EventQuery message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {DBMessaging.Protobuf.IEventQuery} message EventQuery message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventQuery.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an EventQuery message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventQuery} EventQuery + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventQuery.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery(), key, value; + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.timeRangeBegin = reader.double(); + break; + } + case 2: { + message.timeRangeEnd = reader.double(); + break; + } + case 3: { + message.codeMask = reader.uint32(); + break; + } + case 4: { + message.limit = reader.uint32(); + break; + } + case 5: { + message.offset = reader.uint32(); + break; + } + case 6: { + message.flags = reader.uint32(); + break; + } + case 7: { + message.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.decode(reader, reader.uint32()); + break; + } + case 8: { + if (message.dataConditions === $util.emptyObject) + message.dataConditions = {}; + var end2 = reader.uint32() + reader.pos; + key = ""; + value = null; + while (reader.pos < end2) { + var tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.string(); + break; + case 2: + value = $root.DBMessaging.Protobuf.EventQuery.ConditionList.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag2 & 7); + break; + } + } + message.dataConditions[key] = value; + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an EventQuery message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventQuery} EventQuery + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventQuery.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an EventQuery message. + * @function verify + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + EventQuery.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.timeRangeBegin != null && message.hasOwnProperty("timeRangeBegin")) + if (typeof message.timeRangeBegin !== "number") + return "timeRangeBegin: number expected"; + if (message.timeRangeEnd != null && message.hasOwnProperty("timeRangeEnd")) + if (typeof message.timeRangeEnd !== "number") + return "timeRangeEnd: number expected"; + if (message.codeMask != null && message.hasOwnProperty("codeMask")) + if (!$util.isInteger(message.codeMask)) + return "codeMask: integer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) + if (!$util.isInteger(message.limit)) + return "limit: integer expected"; + if (message.offset != null && message.hasOwnProperty("offset")) + if (!$util.isInteger(message.offset)) + return "offset: integer expected"; + if (message.flags != null && message.hasOwnProperty("flags")) + if (!$util.isInteger(message.flags)) + return "flags: integer expected"; + if (message.senderConditions != null && message.hasOwnProperty("senderConditions")) { + var error = $root.DBMessaging.Protobuf.EventQuery.ConditionList.verify(message.senderConditions); + if (error) + return "senderConditions." + error; + } + if (message.dataConditions != null && message.hasOwnProperty("dataConditions")) { + if (!$util.isObject(message.dataConditions)) + return "dataConditions: object expected"; + var key = Object.keys(message.dataConditions); + for (var i = 0; i < key.length; ++i) { + var error = $root.DBMessaging.Protobuf.EventQuery.ConditionList.verify(message.dataConditions[key[i]]); + if (error) + return "dataConditions." + error; + } + } + return null; + }; + + /** + * Creates an EventQuery message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventQuery} EventQuery + */ + EventQuery.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventQuery) + return object; + var message = new $root.DBMessaging.Protobuf.EventQuery(); + if (object.timeRangeBegin != null) + message.timeRangeBegin = Number(object.timeRangeBegin); + if (object.timeRangeEnd != null) + message.timeRangeEnd = Number(object.timeRangeEnd); + if (object.codeMask != null) + message.codeMask = object.codeMask >>> 0; + if (object.limit != null) + message.limit = object.limit >>> 0; + if (object.offset != null) + message.offset = object.offset >>> 0; + if (object.flags != null) + message.flags = object.flags >>> 0; + if (object.senderConditions != null) { + if (typeof object.senderConditions !== "object") + throw TypeError(".DBMessaging.Protobuf.EventQuery.senderConditions: object expected"); + message.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.fromObject(object.senderConditions); + } + if (object.dataConditions) { + if (typeof object.dataConditions !== "object") + throw TypeError(".DBMessaging.Protobuf.EventQuery.dataConditions: object expected"); + message.dataConditions = {}; + for (var keys = Object.keys(object.dataConditions), i = 0; i < keys.length; ++i) { + if (typeof object.dataConditions[keys[i]] !== "object") + throw TypeError(".DBMessaging.Protobuf.EventQuery.dataConditions: object expected"); + message.dataConditions[keys[i]] = $root.DBMessaging.Protobuf.EventQuery.ConditionList.fromObject(object.dataConditions[keys[i]]); + } + } + return message; + }; + + /** + * Creates a plain object from an EventQuery message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {DBMessaging.Protobuf.EventQuery} message EventQuery + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + EventQuery.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.objects || options.defaults) + object.dataConditions = {}; + if (options.defaults) { + object.timeRangeBegin = 0; + object.timeRangeEnd = 0; + object.codeMask = 0; + object.limit = 0; + object.offset = 0; + object.flags = 0; + object.senderConditions = null; + } + if (message.timeRangeBegin != null && message.hasOwnProperty("timeRangeBegin")) + object.timeRangeBegin = options.json && !isFinite(message.timeRangeBegin) ? String(message.timeRangeBegin) : message.timeRangeBegin; + if (message.timeRangeEnd != null && message.hasOwnProperty("timeRangeEnd")) + object.timeRangeEnd = options.json && !isFinite(message.timeRangeEnd) ? String(message.timeRangeEnd) : message.timeRangeEnd; + if (message.codeMask != null && message.hasOwnProperty("codeMask")) + object.codeMask = message.codeMask; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = message.limit; + if (message.offset != null && message.hasOwnProperty("offset")) + object.offset = message.offset; + if (message.flags != null && message.hasOwnProperty("flags")) + object.flags = message.flags; + if (message.senderConditions != null && message.hasOwnProperty("senderConditions")) + object.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.toObject(message.senderConditions, options); + var keys2; + if (message.dataConditions && (keys2 = Object.keys(message.dataConditions)).length) { + object.dataConditions = {}; + for (var j = 0; j < keys2.length; ++j) + object.dataConditions[keys2[j]] = $root.DBMessaging.Protobuf.EventQuery.ConditionList.toObject(message.dataConditions[keys2[j]], options); + } + return object; + }; + + /** + * Converts this EventQuery to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventQuery + * @instance + * @returns {Object.} JSON object + */ + EventQuery.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for EventQuery + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventQuery + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + EventQuery.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery"; + }; + + /** + * MatchType enum. + * @name DBMessaging.Protobuf.EventQuery.MatchType + * @enum {number} + * @property {number} Exact=0 Exact value + * @property {number} Wildcard=1 Wildcard value + */ + EventQuery.MatchType = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "Exact"] = 0; + values[valuesById[1] = "Wildcard"] = 1; + return values; + })(); + + EventQuery.Condition = (function() { + + /** + * Properties of a Condition. + * @memberof DBMessaging.Protobuf.EventQuery + * @interface ICondition + * @property {string|null} [value] Condition value + * @property {DBMessaging.Protobuf.EventQuery.MatchType|null} [type] Condition type + */ + + /** + * Constructs a new Condition. + * @memberof DBMessaging.Protobuf.EventQuery + * @classdesc Represents a Condition. + * @implements ICondition + * @constructor + * @param {DBMessaging.Protobuf.EventQuery.ICondition=} [properties] Properties to set + */ + function Condition(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Condition value. + * @member {string} value + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @instance + */ + Condition.prototype.value = ""; + + /** + * Condition type. + * @member {DBMessaging.Protobuf.EventQuery.MatchType} type + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @instance + */ + Condition.prototype.type = 0; + + /** + * Creates a new Condition instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {DBMessaging.Protobuf.EventQuery.ICondition=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition instance + */ + Condition.create = function create(properties) { + return new Condition(properties); + }; + + /** + * Encodes the specified Condition message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.Condition.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {DBMessaging.Protobuf.EventQuery.ICondition} message Condition message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Condition.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.value != null && Object.hasOwnProperty.call(message, "value")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.value); + if (message.type != null && Object.hasOwnProperty.call(message, "type")) + writer.uint32(/* id 2, wireType 0 =*/16).int32(message.type); + return writer; + }; + + /** + * Encodes the specified Condition message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.Condition.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {DBMessaging.Protobuf.EventQuery.ICondition} message Condition message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Condition.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Condition message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Condition.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery.Condition(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.value = reader.string(); + break; + } + case 2: { + message.type = reader.int32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Condition message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Condition.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Condition message. + * @function verify + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Condition.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.value != null && message.hasOwnProperty("value")) + if (!$util.isString(message.value)) + return "value: string expected"; + if (message.type != null && message.hasOwnProperty("type")) + switch (message.type) { + default: + return "type: enum value expected"; + case 0: + case 1: + break; + } + return null; + }; + + /** + * Creates a Condition message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition + */ + Condition.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventQuery.Condition) + return object; + var message = new $root.DBMessaging.Protobuf.EventQuery.Condition(); + if (object.value != null) + message.value = String(object.value); + switch (object.type) { + default: + if (typeof object.type === "number") { + message.type = object.type; + break; + } + break; + case "Exact": + case 0: + message.type = 0; + break; + case "Wildcard": + case 1: + message.type = 1; + break; + } + return message; + }; + + /** + * Creates a plain object from a Condition message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {DBMessaging.Protobuf.EventQuery.Condition} message Condition + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Condition.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.value = ""; + object.type = options.enums === String ? "Exact" : 0; + } + if (message.value != null && message.hasOwnProperty("value")) + object.value = message.value; + if (message.type != null && message.hasOwnProperty("type")) + object.type = options.enums === String ? $root.DBMessaging.Protobuf.EventQuery.MatchType[message.type] === undefined ? message.type : $root.DBMessaging.Protobuf.EventQuery.MatchType[message.type] : message.type; + return object; + }; + + /** + * Converts this Condition to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @instance + * @returns {Object.} JSON object + */ + Condition.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Condition + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventQuery.Condition + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Condition.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery.Condition"; + }; + + return Condition; + })(); + + EventQuery.ConditionList = (function() { + + /** + * Properties of a ConditionList. + * @memberof DBMessaging.Protobuf.EventQuery + * @interface IConditionList + * @property {Array.|null} [conditions] ConditionList conditions + */ + + /** + * Constructs a new ConditionList. + * @memberof DBMessaging.Protobuf.EventQuery + * @classdesc Represents a ConditionList. + * @implements IConditionList + * @constructor + * @param {DBMessaging.Protobuf.EventQuery.IConditionList=} [properties] Properties to set + */ + function ConditionList(properties) { + this.conditions = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * ConditionList conditions. + * @member {Array.} conditions + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @instance + */ + ConditionList.prototype.conditions = $util.emptyArray; + + /** + * Creates a new ConditionList instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {DBMessaging.Protobuf.EventQuery.IConditionList=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList instance + */ + ConditionList.create = function create(properties) { + return new ConditionList(properties); + }; + + /** + * Encodes the specified ConditionList message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.ConditionList.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {DBMessaging.Protobuf.EventQuery.IConditionList} message ConditionList message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ConditionList.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.conditions != null && message.conditions.length) + for (var i = 0; i < message.conditions.length; ++i) + $root.DBMessaging.Protobuf.EventQuery.Condition.encode(message.conditions[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified ConditionList message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.ConditionList.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {DBMessaging.Protobuf.EventQuery.IConditionList} message ConditionList message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ConditionList.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ConditionList message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ConditionList.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery.ConditionList(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.conditions && message.conditions.length)) + message.conditions = []; + message.conditions.push($root.DBMessaging.Protobuf.EventQuery.Condition.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ConditionList message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ConditionList.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ConditionList message. + * @function verify + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ConditionList.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.conditions != null && message.hasOwnProperty("conditions")) { + if (!Array.isArray(message.conditions)) + return "conditions: array expected"; + for (var i = 0; i < message.conditions.length; ++i) { + var error = $root.DBMessaging.Protobuf.EventQuery.Condition.verify(message.conditions[i]); + if (error) + return "conditions." + error; + } + } + return null; + }; + + /** + * Creates a ConditionList message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList + */ + ConditionList.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventQuery.ConditionList) + return object; + var message = new $root.DBMessaging.Protobuf.EventQuery.ConditionList(); + if (object.conditions) { + if (!Array.isArray(object.conditions)) + throw TypeError(".DBMessaging.Protobuf.EventQuery.ConditionList.conditions: array expected"); + message.conditions = []; + for (var i = 0; i < object.conditions.length; ++i) { + if (typeof object.conditions[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.EventQuery.ConditionList.conditions: object expected"); + message.conditions[i] = $root.DBMessaging.Protobuf.EventQuery.Condition.fromObject(object.conditions[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a ConditionList message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {DBMessaging.Protobuf.EventQuery.ConditionList} message ConditionList + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ConditionList.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.conditions = []; + if (message.conditions && message.conditions.length) { + object.conditions = []; + for (var j = 0; j < message.conditions.length; ++j) + object.conditions[j] = $root.DBMessaging.Protobuf.EventQuery.Condition.toObject(message.conditions[j], options); + } + return object; + }; + + /** + * Converts this ConditionList to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @instance + * @returns {Object.} JSON object + */ + ConditionList.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ConditionList + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventQuery.ConditionList + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ConditionList.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery.ConditionList"; + }; + + return ConditionList; + })(); + + return EventQuery; + })(); + + Protobuf.EventSenderTagsRequest = (function() { + + /** + * Properties of an EventSenderTagsRequest. + * @memberof DBMessaging.Protobuf + * @interface IEventSenderTagsRequest + * @property {number|null} [requestId] EventSenderTagsRequest requestId + */ + + /** + * Constructs a new EventSenderTagsRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an EventSenderTagsRequest. + * @implements IEventSenderTagsRequest + * @constructor + * @param {DBMessaging.Protobuf.IEventSenderTagsRequest=} [properties] Properties to set + */ + function EventSenderTagsRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * EventSenderTagsRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @instance + */ + EventSenderTagsRequest.prototype.requestId = 0; + + /** + * Creates a new EventSenderTagsRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest instance + */ + EventSenderTagsRequest.create = function create(properties) { + return new EventSenderTagsRequest(properties); + }; + + /** + * Encodes the specified EventSenderTagsRequest message. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsRequest} message EventSenderTagsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventSenderTagsRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + return writer; + }; + + /** + * Encodes the specified EventSenderTagsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsRequest} message EventSenderTagsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventSenderTagsRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an EventSenderTagsRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventSenderTagsRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventSenderTagsRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an EventSenderTagsRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventSenderTagsRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an EventSenderTagsRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + EventSenderTagsRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + return null; + }; + + /** + * Creates an EventSenderTagsRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest + */ + EventSenderTagsRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventSenderTagsRequest) + return object; + var message = new $root.DBMessaging.Protobuf.EventSenderTagsRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + return message; + }; + + /** + * Creates a plain object from an EventSenderTagsRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {DBMessaging.Protobuf.EventSenderTagsRequest} message EventSenderTagsRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + EventSenderTagsRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + return object; + }; + + /** + * Converts this EventSenderTagsRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @instance + * @returns {Object.} JSON object + */ + EventSenderTagsRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for EventSenderTagsRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventSenderTagsRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + EventSenderTagsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventSenderTagsRequest"; + }; + + return EventSenderTagsRequest; + })(); + + Protobuf.EventSenderTagsResponse = (function() { + + /** + * Properties of an EventSenderTagsResponse. + * @memberof DBMessaging.Protobuf + * @interface IEventSenderTagsResponse + * @property {number|null} [requestId] EventSenderTagsResponse requestId + * @property {Object.|null} [senderTags] EventSenderTagsResponse senderTags + */ + + /** + * Constructs a new EventSenderTagsResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an EventSenderTagsResponse. + * @implements IEventSenderTagsResponse + * @constructor + * @param {DBMessaging.Protobuf.IEventSenderTagsResponse=} [properties] Properties to set + */ + function EventSenderTagsResponse(properties) { + this.senderTags = {}; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * EventSenderTagsResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @instance + */ + EventSenderTagsResponse.prototype.requestId = 0; + + /** + * EventSenderTagsResponse senderTags. + * @member {Object.} senderTags + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @instance + */ + EventSenderTagsResponse.prototype.senderTags = $util.emptyObject; + + /** + * Creates a new EventSenderTagsResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse instance + */ + EventSenderTagsResponse.create = function create(properties) { + return new EventSenderTagsResponse(properties); + }; + + /** + * Encodes the specified EventSenderTagsResponse message. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsResponse} message EventSenderTagsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventSenderTagsResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.senderTags != null && Object.hasOwnProperty.call(message, "senderTags")) + for (var keys = Object.keys(message.senderTags), i = 0; i < keys.length; ++i) { + writer.uint32(/* id 2, wireType 2 =*/18).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); + $root.DBMessaging.Protobuf.TagMap.encode(message.senderTags[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); + } + return writer; + }; + + /** + * Encodes the specified EventSenderTagsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {DBMessaging.Protobuf.IEventSenderTagsResponse} message EventSenderTagsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventSenderTagsResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an EventSenderTagsResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventSenderTagsResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventSenderTagsResponse(), key, value; + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + if (message.senderTags === $util.emptyObject) + message.senderTags = {}; + var end2 = reader.uint32() + reader.pos; + key = ""; + value = null; + while (reader.pos < end2) { + var tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.string(); + break; + case 2: + value = $root.DBMessaging.Protobuf.TagMap.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag2 & 7); + break; + } + } + message.senderTags[key] = value; + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an EventSenderTagsResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventSenderTagsResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an EventSenderTagsResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + EventSenderTagsResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.senderTags != null && message.hasOwnProperty("senderTags")) { + if (!$util.isObject(message.senderTags)) + return "senderTags: object expected"; + var key = Object.keys(message.senderTags); + for (var i = 0; i < key.length; ++i) { + var error = $root.DBMessaging.Protobuf.TagMap.verify(message.senderTags[key[i]]); + if (error) + return "senderTags." + error; + } + } + return null; + }; + + /** + * Creates an EventSenderTagsResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse + */ + EventSenderTagsResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventSenderTagsResponse) + return object; + var message = new $root.DBMessaging.Protobuf.EventSenderTagsResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.senderTags) { + if (typeof object.senderTags !== "object") + throw TypeError(".DBMessaging.Protobuf.EventSenderTagsResponse.senderTags: object expected"); + message.senderTags = {}; + for (var keys = Object.keys(object.senderTags), i = 0; i < keys.length; ++i) { + if (typeof object.senderTags[keys[i]] !== "object") + throw TypeError(".DBMessaging.Protobuf.EventSenderTagsResponse.senderTags: object expected"); + message.senderTags[keys[i]] = $root.DBMessaging.Protobuf.TagMap.fromObject(object.senderTags[keys[i]]); + } + } + return message; + }; + + /** + * Creates a plain object from an EventSenderTagsResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {DBMessaging.Protobuf.EventSenderTagsResponse} message EventSenderTagsResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + EventSenderTagsResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.objects || options.defaults) + object.senderTags = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + var keys2; + if (message.senderTags && (keys2 = Object.keys(message.senderTags)).length) { + object.senderTags = {}; + for (var j = 0; j < keys2.length; ++j) + object.senderTags[keys2[j]] = $root.DBMessaging.Protobuf.TagMap.toObject(message.senderTags[keys2[j]], options); + } + return object; + }; + + /** + * Converts this EventSenderTagsResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @instance + * @returns {Object.} JSON object + */ + EventSenderTagsResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for EventSenderTagsResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventSenderTagsResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + EventSenderTagsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventSenderTagsResponse"; + }; + + return EventSenderTagsResponse; + })(); + + Protobuf.CountEventsRequest = (function() { + + /** + * Properties of a CountEventsRequest. + * @memberof DBMessaging.Protobuf + * @interface ICountEventsRequest + * @property {number|null} [requestId] CountEventsRequest requestId + * @property {DBMessaging.Protobuf.IEventQuery|null} [query] CountEventsRequest query + */ + + /** + * Constructs a new CountEventsRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a CountEventsRequest. + * @implements ICountEventsRequest + * @constructor + * @param {DBMessaging.Protobuf.ICountEventsRequest=} [properties] Properties to set + */ + function CountEventsRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * CountEventsRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @instance + */ + CountEventsRequest.prototype.requestId = 0; + + /** + * CountEventsRequest query. + * @member {DBMessaging.Protobuf.IEventQuery|null|undefined} query + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @instance + */ + CountEventsRequest.prototype.query = null; + + /** + * Creates a new CountEventsRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {DBMessaging.Protobuf.ICountEventsRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest instance + */ + CountEventsRequest.create = function create(properties) { + return new CountEventsRequest(properties); + }; + + /** + * Encodes the specified CountEventsRequest message. Does not implicitly {@link DBMessaging.Protobuf.CountEventsRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {DBMessaging.Protobuf.ICountEventsRequest} message CountEventsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEventsRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.query != null && Object.hasOwnProperty.call(message, "query")) + $root.DBMessaging.Protobuf.EventQuery.encode(message.query, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified CountEventsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CountEventsRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {DBMessaging.Protobuf.ICountEventsRequest} message CountEventsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEventsRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a CountEventsRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEventsRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CountEventsRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.query = $root.DBMessaging.Protobuf.EventQuery.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a CountEventsRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEventsRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a CountEventsRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CountEventsRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.query != null && message.hasOwnProperty("query")) { + var error = $root.DBMessaging.Protobuf.EventQuery.verify(message.query); + if (error) + return "query." + error; + } + return null; + }; + + /** + * Creates a CountEventsRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest + */ + CountEventsRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.CountEventsRequest) + return object; + var message = new $root.DBMessaging.Protobuf.CountEventsRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.query != null) { + if (typeof object.query !== "object") + throw TypeError(".DBMessaging.Protobuf.CountEventsRequest.query: object expected"); + message.query = $root.DBMessaging.Protobuf.EventQuery.fromObject(object.query); + } + return message; + }; + + /** + * Creates a plain object from a CountEventsRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {DBMessaging.Protobuf.CountEventsRequest} message CountEventsRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CountEventsRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + object.query = null; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.query != null && message.hasOwnProperty("query")) + object.query = $root.DBMessaging.Protobuf.EventQuery.toObject(message.query, options); + return object; + }; + + /** + * Converts this CountEventsRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @instance + * @returns {Object.} JSON object + */ + CountEventsRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for CountEventsRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.CountEventsRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + CountEventsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.CountEventsRequest"; + }; + + return CountEventsRequest; + })(); + + Protobuf.CountEventsResponse = (function() { + + /** + * Properties of a CountEventsResponse. + * @memberof DBMessaging.Protobuf + * @interface ICountEventsResponse + * @property {number|null} [requestId] CountEventsResponse requestId + * @property {number|Long|null} [count] CountEventsResponse count + */ + + /** + * Constructs a new CountEventsResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a CountEventsResponse. + * @implements ICountEventsResponse + * @constructor + * @param {DBMessaging.Protobuf.ICountEventsResponse=} [properties] Properties to set + */ + function CountEventsResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * CountEventsResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @instance + */ + CountEventsResponse.prototype.requestId = 0; + + /** + * CountEventsResponse count. + * @member {number|Long} count + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @instance + */ + CountEventsResponse.prototype.count = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * Creates a new CountEventsResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {DBMessaging.Protobuf.ICountEventsResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse instance + */ + CountEventsResponse.create = function create(properties) { + return new CountEventsResponse(properties); + }; + + /** + * Encodes the specified CountEventsResponse message. Does not implicitly {@link DBMessaging.Protobuf.CountEventsResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {DBMessaging.Protobuf.ICountEventsResponse} message CountEventsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEventsResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.count != null && Object.hasOwnProperty.call(message, "count")) + writer.uint32(/* id 2, wireType 0 =*/16).int64(message.count); + return writer; + }; + + /** + * Encodes the specified CountEventsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CountEventsResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {DBMessaging.Protobuf.ICountEventsResponse} message CountEventsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEventsResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a CountEventsResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEventsResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CountEventsResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.count = reader.int64(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a CountEventsResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEventsResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a CountEventsResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CountEventsResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.count != null && message.hasOwnProperty("count")) + if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) + return "count: integer|Long expected"; + return null; + }; + + /** + * Creates a CountEventsResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse + */ + CountEventsResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.CountEventsResponse) + return object; + var message = new $root.DBMessaging.Protobuf.CountEventsResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.count != null) + if ($util.Long) + (message.count = $util.Long.fromValue(object.count)).unsigned = false; + else if (typeof object.count === "string") + message.count = parseInt(object.count, 10); + else if (typeof object.count === "number") + message.count = object.count; + else if (typeof object.count === "object") + message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(); + return message; + }; + + /** + * Creates a plain object from a CountEventsResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {DBMessaging.Protobuf.CountEventsResponse} message CountEventsResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CountEventsResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.count = options.longs === String ? "0" : 0; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.count != null && message.hasOwnProperty("count")) + if (typeof message.count === "number") + object.count = options.longs === String ? String(message.count) : message.count; + else + object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber() : message.count; + return object; + }; + + /** + * Converts this CountEventsResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @instance + * @returns {Object.} JSON object + */ + CountEventsResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for CountEventsResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.CountEventsResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + CountEventsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.CountEventsResponse"; + }; + + return CountEventsResponse; + })(); + + Protobuf.EventsRequest = (function() { + + /** + * Properties of an EventsRequest. + * @memberof DBMessaging.Protobuf + * @interface IEventsRequest + * @property {number|null} [requestId] EventsRequest requestId + * @property {DBMessaging.Protobuf.IEventQuery|null} [query] EventsRequest query + */ + + /** + * Constructs a new EventsRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an EventsRequest. + * @implements IEventsRequest + * @constructor + * @param {DBMessaging.Protobuf.IEventsRequest=} [properties] Properties to set + */ + function EventsRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * EventsRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.EventsRequest + * @instance + */ + EventsRequest.prototype.requestId = 0; + + /** + * EventsRequest query. + * @member {DBMessaging.Protobuf.IEventQuery|null|undefined} query + * @memberof DBMessaging.Protobuf.EventsRequest + * @instance + */ + EventsRequest.prototype.query = null; + + /** + * Creates a new EventsRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {DBMessaging.Protobuf.IEventsRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest instance + */ + EventsRequest.create = function create(properties) { + return new EventsRequest(properties); + }; + + /** + * Encodes the specified EventsRequest message. Does not implicitly {@link DBMessaging.Protobuf.EventsRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {DBMessaging.Protobuf.IEventsRequest} message EventsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventsRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.query != null && Object.hasOwnProperty.call(message, "query")) + $root.DBMessaging.Protobuf.EventQuery.encode(message.query, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified EventsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventsRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {DBMessaging.Protobuf.IEventsRequest} message EventsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventsRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an EventsRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventsRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventsRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.query = $root.DBMessaging.Protobuf.EventQuery.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an EventsRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventsRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an EventsRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + EventsRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.query != null && message.hasOwnProperty("query")) { + var error = $root.DBMessaging.Protobuf.EventQuery.verify(message.query); + if (error) + return "query." + error; + } + return null; + }; + + /** + * Creates an EventsRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest + */ + EventsRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventsRequest) + return object; + var message = new $root.DBMessaging.Protobuf.EventsRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.query != null) { + if (typeof object.query !== "object") + throw TypeError(".DBMessaging.Protobuf.EventsRequest.query: object expected"); + message.query = $root.DBMessaging.Protobuf.EventQuery.fromObject(object.query); + } + return message; + }; + + /** + * Creates a plain object from an EventsRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {DBMessaging.Protobuf.EventsRequest} message EventsRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + EventsRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + object.query = null; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.query != null && message.hasOwnProperty("query")) + object.query = $root.DBMessaging.Protobuf.EventQuery.toObject(message.query, options); + return object; + }; + + /** + * Converts this EventsRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventsRequest + * @instance + * @returns {Object.} JSON object + */ + EventsRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for EventsRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventsRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + EventsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventsRequest"; + }; + + return EventsRequest; + })(); + + Protobuf.EventsResponse = (function() { + + /** + * Properties of an EventsResponse. + * @memberof DBMessaging.Protobuf + * @interface IEventsResponse + * @property {number|null} [requestId] EventsResponse requestId + * @property {Array.|null} [events] EventsResponse events + */ + + /** + * Constructs a new EventsResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an EventsResponse. + * @implements IEventsResponse + * @constructor + * @param {DBMessaging.Protobuf.IEventsResponse=} [properties] Properties to set + */ + function EventsResponse(properties) { + this.events = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * EventsResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.EventsResponse + * @instance + */ + EventsResponse.prototype.requestId = 0; + + /** + * EventsResponse events. + * @member {Array.} events + * @memberof DBMessaging.Protobuf.EventsResponse + * @instance + */ + EventsResponse.prototype.events = $util.emptyArray; + + /** + * Creates a new EventsResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {DBMessaging.Protobuf.IEventsResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse instance + */ + EventsResponse.create = function create(properties) { + return new EventsResponse(properties); + }; + + /** + * Encodes the specified EventsResponse message. Does not implicitly {@link DBMessaging.Protobuf.EventsResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {DBMessaging.Protobuf.IEventsResponse} message EventsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventsResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.events != null && message.events.length) + for (var i = 0; i < message.events.length; ++i) + $root.DBMessaging.Protobuf.Event.encode(message.events[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified EventsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventsResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {DBMessaging.Protobuf.IEventsResponse} message EventsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + EventsResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an EventsResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventsResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventsResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + if (!(message.events && message.events.length)) + message.events = []; + message.events.push($root.DBMessaging.Protobuf.Event.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an EventsResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + EventsResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an EventsResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + EventsResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.events != null && message.hasOwnProperty("events")) { + if (!Array.isArray(message.events)) + return "events: array expected"; + for (var i = 0; i < message.events.length; ++i) { + var error = $root.DBMessaging.Protobuf.Event.verify(message.events[i]); + if (error) + return "events." + error; + } + } + return null; + }; + + /** + * Creates an EventsResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse + */ + EventsResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.EventsResponse) + return object; + var message = new $root.DBMessaging.Protobuf.EventsResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.events) { + if (!Array.isArray(object.events)) + throw TypeError(".DBMessaging.Protobuf.EventsResponse.events: array expected"); + message.events = []; + for (var i = 0; i < object.events.length; ++i) { + if (typeof object.events[i] !== "object") + throw TypeError(".DBMessaging.Protobuf.EventsResponse.events: object expected"); + message.events[i] = $root.DBMessaging.Protobuf.Event.fromObject(object.events[i]); + } + } + return message; + }; + + /** + * Creates a plain object from an EventsResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {DBMessaging.Protobuf.EventsResponse} message EventsResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + EventsResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.events = []; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.events && message.events.length) { + object.events = []; + for (var j = 0; j < message.events.length; ++j) + object.events[j] = $root.DBMessaging.Protobuf.Event.toObject(message.events[j], options); + } + return object; + }; + + /** + * Converts this EventsResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.EventsResponse + * @instance + * @returns {Object.} JSON object + */ + EventsResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for EventsResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.EventsResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + EventsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.EventsResponse"; + }; + + return EventsResponse; + })(); + + Protobuf.VersionRequest = (function() { + + /** + * Properties of a VersionRequest. + * @memberof DBMessaging.Protobuf + * @interface IVersionRequest + * @property {number|null} [requestId] VersionRequest requestId + */ + + /** + * Constructs a new VersionRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a VersionRequest. + * @implements IVersionRequest + * @constructor + * @param {DBMessaging.Protobuf.IVersionRequest=} [properties] Properties to set + */ + function VersionRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * VersionRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.VersionRequest + * @instance + */ + VersionRequest.prototype.requestId = 0; + + /** + * Creates a new VersionRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {DBMessaging.Protobuf.IVersionRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest instance + */ + VersionRequest.create = function create(properties) { + return new VersionRequest(properties); + }; + + /** + * Encodes the specified VersionRequest message. Does not implicitly {@link DBMessaging.Protobuf.VersionRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {DBMessaging.Protobuf.IVersionRequest} message VersionRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VersionRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + return writer; + }; + + /** + * Encodes the specified VersionRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.VersionRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {DBMessaging.Protobuf.IVersionRequest} message VersionRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VersionRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a VersionRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VersionRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.VersionRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a VersionRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VersionRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a VersionRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + VersionRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + return null; + }; + + /** + * Creates a VersionRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest + */ + VersionRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.VersionRequest) + return object; + var message = new $root.DBMessaging.Protobuf.VersionRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + return message; + }; + + /** + * Creates a plain object from a VersionRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {DBMessaging.Protobuf.VersionRequest} message VersionRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + VersionRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + return object; + }; + + /** + * Converts this VersionRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.VersionRequest + * @instance + * @returns {Object.} JSON object + */ + VersionRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for VersionRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.VersionRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + VersionRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.VersionRequest"; + }; + + return VersionRequest; + })(); + + Protobuf.VersionResponse = (function() { + + /** + * Properties of a VersionResponse. + * @memberof DBMessaging.Protobuf + * @interface IVersionResponse + * @property {number|null} [requestId] VersionResponse requestId + * @property {string|null} [version] VersionResponse version + */ + + /** + * Constructs a new VersionResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a VersionResponse. + * @implements IVersionResponse + * @constructor + * @param {DBMessaging.Protobuf.IVersionResponse=} [properties] Properties to set + */ + function VersionResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * VersionResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.VersionResponse + * @instance + */ + VersionResponse.prototype.requestId = 0; + + /** + * VersionResponse version. + * @member {string} version + * @memberof DBMessaging.Protobuf.VersionResponse + * @instance + */ + VersionResponse.prototype.version = ""; + + /** + * Creates a new VersionResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {DBMessaging.Protobuf.IVersionResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse instance + */ + VersionResponse.create = function create(properties) { + return new VersionResponse(properties); + }; + + /** + * Encodes the specified VersionResponse message. Does not implicitly {@link DBMessaging.Protobuf.VersionResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {DBMessaging.Protobuf.IVersionResponse} message VersionResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VersionResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.version != null && Object.hasOwnProperty.call(message, "version")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.version); + return writer; + }; + + /** + * Encodes the specified VersionResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.VersionResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {DBMessaging.Protobuf.IVersionResponse} message VersionResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VersionResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a VersionResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VersionResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.VersionResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.version = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a VersionResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VersionResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a VersionResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + VersionResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.version != null && message.hasOwnProperty("version")) + if (!$util.isString(message.version)) + return "version: string expected"; + return null; + }; + + /** + * Creates a VersionResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse + */ + VersionResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.VersionResponse) + return object; + var message = new $root.DBMessaging.Protobuf.VersionResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.version != null) + message.version = String(object.version); + return message; + }; + + /** + * Creates a plain object from a VersionResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {DBMessaging.Protobuf.VersionResponse} message VersionResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + VersionResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + object.version = ""; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.version != null && message.hasOwnProperty("version")) + object.version = message.version; + return object; + }; + + /** + * Converts this VersionResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.VersionResponse + * @instance + * @returns {Object.} JSON object + */ + VersionResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for VersionResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.VersionResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + VersionResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.VersionResponse"; + }; + + return VersionResponse; + })(); + + Protobuf.Error = (function() { + + /** + * Properties of an Error. + * @memberof DBMessaging.Protobuf + * @interface IError + * @property {number|null} [requestId] Error requestId + * @property {string|null} [errorMessage] Error errorMessage + * @property {number|null} [errorCode] Error errorCode + */ + + /** + * Constructs a new Error. + * @memberof DBMessaging.Protobuf + * @classdesc Represents an Error. + * @implements IError + * @constructor + * @param {DBMessaging.Protobuf.IError=} [properties] Properties to set + */ + function Error(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Error requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.Error + * @instance + */ + Error.prototype.requestId = 0; + + /** + * Error errorMessage. + * @member {string} errorMessage + * @memberof DBMessaging.Protobuf.Error + * @instance + */ + Error.prototype.errorMessage = ""; + + /** + * Error errorCode. + * @member {number} errorCode + * @memberof DBMessaging.Protobuf.Error + * @instance + */ + Error.prototype.errorCode = 0; + + /** + * Creates a new Error instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {DBMessaging.Protobuf.IError=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.Error} Error instance + */ + Error.create = function create(properties) { + return new Error(properties); + }; + + /** + * Encodes the specified Error message. Does not implicitly {@link DBMessaging.Protobuf.Error.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {DBMessaging.Protobuf.IError} message Error message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Error.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.errorMessage != null && Object.hasOwnProperty.call(message, "errorMessage")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.errorMessage); + if (message.errorCode != null && Object.hasOwnProperty.call(message, "errorCode")) + writer.uint32(/* id 3, wireType 0 =*/24).int32(message.errorCode); + return writer; + }; + + /** + * Encodes the specified Error message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Error.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {DBMessaging.Protobuf.IError} message Error message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Error.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Error message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.Error} Error + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Error.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Error(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.errorMessage = reader.string(); + break; + } + case 3: { + message.errorCode = reader.int32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Error message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.Error} Error + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Error.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Error message. + * @function verify + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Error.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.errorMessage != null && message.hasOwnProperty("errorMessage")) + if (!$util.isString(message.errorMessage)) + return "errorMessage: string expected"; + if (message.errorCode != null && message.hasOwnProperty("errorCode")) + if (!$util.isInteger(message.errorCode)) + return "errorCode: integer expected"; + return null; + }; + + /** + * Creates an Error message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.Error} Error + */ + Error.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.Error) + return object; + var message = new $root.DBMessaging.Protobuf.Error(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.errorMessage != null) + message.errorMessage = String(object.errorMessage); + if (object.errorCode != null) + message.errorCode = object.errorCode | 0; + return message; + }; + + /** + * Creates a plain object from an Error message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {DBMessaging.Protobuf.Error} message Error + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Error.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + object.errorMessage = ""; + object.errorCode = 0; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.errorMessage != null && message.hasOwnProperty("errorMessage")) + object.errorMessage = message.errorMessage; + if (message.errorCode != null && message.hasOwnProperty("errorCode")) + object.errorCode = message.errorCode; + return object; + }; + + /** + * Converts this Error to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.Error + * @instance + * @returns {Object.} JSON object + */ + Error.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Error + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.Error + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Error.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.Error"; + }; + + return Error; + })(); + + Protobuf.TimeRequest = (function() { + + /** + * Properties of a TimeRequest. + * @memberof DBMessaging.Protobuf + * @interface ITimeRequest + * @property {number|null} [requestId] TimeRequest requestId + */ + + /** + * Constructs a new TimeRequest. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a TimeRequest. + * @implements ITimeRequest + * @constructor + * @param {DBMessaging.Protobuf.ITimeRequest=} [properties] Properties to set + */ + function TimeRequest(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * TimeRequest requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.TimeRequest + * @instance + */ + TimeRequest.prototype.requestId = 0; + + /** + * Creates a new TimeRequest instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {DBMessaging.Protobuf.ITimeRequest=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest instance + */ + TimeRequest.create = function create(properties) { + return new TimeRequest(properties); + }; + + /** + * Encodes the specified TimeRequest message. Does not implicitly {@link DBMessaging.Protobuf.TimeRequest.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {DBMessaging.Protobuf.ITimeRequest} message TimeRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TimeRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + return writer; + }; + + /** + * Encodes the specified TimeRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TimeRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {DBMessaging.Protobuf.ITimeRequest} message TimeRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TimeRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TimeRequest message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TimeRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TimeRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TimeRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TimeRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TimeRequest message. + * @function verify + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TimeRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + return null; + }; + + /** + * Creates a TimeRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest + */ + TimeRequest.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.TimeRequest) + return object; + var message = new $root.DBMessaging.Protobuf.TimeRequest(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + return message; + }; + + /** + * Creates a plain object from a TimeRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {DBMessaging.Protobuf.TimeRequest} message TimeRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TimeRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.requestId = 0; + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + return object; + }; + + /** + * Converts this TimeRequest to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.TimeRequest + * @instance + * @returns {Object.} JSON object + */ + TimeRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TimeRequest + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.TimeRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TimeRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.TimeRequest"; + }; + + return TimeRequest; + })(); + + Protobuf.TimeResponse = (function() { + + /** + * Properties of a TimeResponse. + * @memberof DBMessaging.Protobuf + * @interface ITimeResponse + * @property {number|null} [requestId] TimeResponse requestId + * @property {number|Long|null} [timestamp] TimeResponse timestamp + */ + + /** + * Constructs a new TimeResponse. + * @memberof DBMessaging.Protobuf + * @classdesc Represents a TimeResponse. + * @implements ITimeResponse + * @constructor + * @param {DBMessaging.Protobuf.ITimeResponse=} [properties] Properties to set + */ + function TimeResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * TimeResponse requestId. + * @member {number} requestId + * @memberof DBMessaging.Protobuf.TimeResponse + * @instance + */ + TimeResponse.prototype.requestId = 0; + + /** + * TimeResponse timestamp. + * @member {number|Long} timestamp + * @memberof DBMessaging.Protobuf.TimeResponse + * @instance + */ + TimeResponse.prototype.timestamp = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * Creates a new TimeResponse instance using the specified properties. + * @function create + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {DBMessaging.Protobuf.ITimeResponse=} [properties] Properties to set + * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse instance + */ + TimeResponse.create = function create(properties) { + return new TimeResponse(properties); + }; + + /** + * Encodes the specified TimeResponse message. Does not implicitly {@link DBMessaging.Protobuf.TimeResponse.verify|verify} messages. + * @function encode + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {DBMessaging.Protobuf.ITimeResponse} message TimeResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TimeResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); + if (message.timestamp != null && Object.hasOwnProperty.call(message, "timestamp")) + writer.uint32(/* id 2, wireType 1 =*/17).fixed64(message.timestamp); + return writer; + }; + + /** + * Encodes the specified TimeResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TimeResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {DBMessaging.Protobuf.ITimeResponse} message TimeResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TimeResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TimeResponse message from the specified reader or buffer. + * @function decode + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TimeResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TimeResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.requestId = reader.uint32(); + break; + } + case 2: { + message.timestamp = reader.fixed64(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TimeResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TimeResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TimeResponse message. + * @function verify + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TimeResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.requestId != null && message.hasOwnProperty("requestId")) + if (!$util.isInteger(message.requestId)) + return "requestId: integer expected"; + if (message.timestamp != null && message.hasOwnProperty("timestamp")) + if (!$util.isInteger(message.timestamp) && !(message.timestamp && $util.isInteger(message.timestamp.low) && $util.isInteger(message.timestamp.high))) + return "timestamp: integer|Long expected"; + return null; + }; + + /** + * Creates a TimeResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {Object.} object Plain object + * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse + */ + TimeResponse.fromObject = function fromObject(object) { + if (object instanceof $root.DBMessaging.Protobuf.TimeResponse) + return object; + var message = new $root.DBMessaging.Protobuf.TimeResponse(); + if (object.requestId != null) + message.requestId = object.requestId >>> 0; + if (object.timestamp != null) + if ($util.Long) + (message.timestamp = $util.Long.fromValue(object.timestamp)).unsigned = false; + else if (typeof object.timestamp === "string") + message.timestamp = parseInt(object.timestamp, 10); + else if (typeof object.timestamp === "number") + message.timestamp = object.timestamp; + else if (typeof object.timestamp === "object") + message.timestamp = new $util.LongBits(object.timestamp.low >>> 0, object.timestamp.high >>> 0).toNumber(); + return message; + }; + + /** + * Creates a plain object from a TimeResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {DBMessaging.Protobuf.TimeResponse} message TimeResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TimeResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.requestId = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.timestamp = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.timestamp = options.longs === String ? "0" : 0; + } + if (message.requestId != null && message.hasOwnProperty("requestId")) + object.requestId = message.requestId; + if (message.timestamp != null && message.hasOwnProperty("timestamp")) + if (typeof message.timestamp === "number") + object.timestamp = options.longs === String ? String(message.timestamp) : message.timestamp; + else + object.timestamp = options.longs === String ? $util.Long.prototype.toString.call(message.timestamp) : options.longs === Number ? new $util.LongBits(message.timestamp.low >>> 0, message.timestamp.high >>> 0).toNumber() : message.timestamp; + return object; + }; + + /** + * Converts this TimeResponse to JSON. + * @function toJSON + * @memberof DBMessaging.Protobuf.TimeResponse + * @instance + * @returns {Object.} JSON object + */ + TimeResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TimeResponse + * @function getTypeUrl + * @memberof DBMessaging.Protobuf.TimeResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TimeResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/DBMessaging.Protobuf.TimeResponse"; + }; + + return TimeResponse; + })(); + + return Protobuf; + })(); + + return DBMessaging; +})(); + +$root.ICD = (function() { + + /** + * Namespace ICD. + * @exports ICD + * @namespace + */ + var ICD = {}; + + ICD.Protobuf = (function() { + + /** + * Namespace Protobuf. + * @memberof ICD + * @namespace + */ + var Protobuf = {}; + + /** + * CDP value type identifier. + * @name ICD.Protobuf.CDPValueType + * @enum {number} + * @property {number} eUNDEFINED=0 eUNDEFINED value + * @property {number} eDOUBLE=1 eDOUBLE value + * @property {number} eUINT64=2 eUINT64 value + * @property {number} eINT64=3 eINT64 value + * @property {number} eFLOAT=4 eFLOAT value + * @property {number} eUINT=5 eUINT value + * @property {number} eINT=6 eINT value + * @property {number} eUSHORT=7 eUSHORT value + * @property {number} eSHORT=8 eSHORT value + * @property {number} eUCHAR=9 eUCHAR value + * @property {number} eCHAR=10 eCHAR value + * @property {number} eBOOL=11 eBOOL value + * @property {number} eSTRING=12 eSTRING value + * @property {number} eUSERTYPE=100 eUSERTYPE value + */ + Protobuf.CDPValueType = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "eUNDEFINED"] = 0; + values[valuesById[1] = "eDOUBLE"] = 1; + values[valuesById[2] = "eUINT64"] = 2; + values[valuesById[3] = "eINT64"] = 3; + values[valuesById[4] = "eFLOAT"] = 4; + values[valuesById[5] = "eUINT"] = 5; + values[valuesById[6] = "eINT"] = 6; + values[valuesById[7] = "eUSHORT"] = 7; + values[valuesById[8] = "eSHORT"] = 8; + values[valuesById[9] = "eUCHAR"] = 9; + values[valuesById[10] = "eCHAR"] = 10; + values[valuesById[11] = "eBOOL"] = 11; + values[valuesById[12] = "eSTRING"] = 12; + values[valuesById[100] = "eUSERTYPE"] = 100; + return values; + })(); + + Protobuf.VariantValue = (function() { + + /** + * Properties of a VariantValue. + * @memberof ICD.Protobuf + * @interface IVariantValue + * @property {number|null} [nodeId] VariantValue nodeId + * @property {number|null} [dValue] VariantValue dValue + * @property {number|null} [fValue] VariantValue fValue + * @property {number|Long|null} [ui64Value] VariantValue ui64Value + * @property {number|Long|null} [i64Value] VariantValue i64Value + * @property {number|null} [uiValue] VariantValue uiValue + * @property {number|null} [iValue] VariantValue iValue + * @property {number|null} [usValue] VariantValue usValue + * @property {number|null} [sValue] VariantValue sValue + * @property {number|null} [ucValue] VariantValue ucValue + * @property {number|null} [cValue] VariantValue cValue + * @property {boolean|null} [bValue] VariantValue bValue + * @property {string|null} [strValue] VariantValue strValue + * @property {number|null} [timestamp] VariantValue timestamp + */ + + /** + * Constructs a new VariantValue. + * @memberof ICD.Protobuf + * @classdesc Common Variant value type for a remote node. + * @implements IVariantValue + * @constructor + * @param {ICD.Protobuf.IVariantValue=} [properties] Properties to set + */ + function VariantValue(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * VariantValue nodeId. + * @member {number} nodeId + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.nodeId = 0; + + /** + * VariantValue dValue. + * @member {number} dValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.dValue = 0; + + /** + * VariantValue fValue. + * @member {number} fValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.fValue = 0; + + /** + * VariantValue ui64Value. + * @member {number|Long} ui64Value + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.ui64Value = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * VariantValue i64Value. + * @member {number|Long} i64Value + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.i64Value = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * VariantValue uiValue. + * @member {number} uiValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.uiValue = 0; + + /** + * VariantValue iValue. + * @member {number} iValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.iValue = 0; + + /** + * VariantValue usValue. + * @member {number} usValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.usValue = 0; + + /** + * VariantValue sValue. + * @member {number} sValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.sValue = 0; + + /** + * VariantValue ucValue. + * @member {number} ucValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.ucValue = 0; + + /** + * VariantValue cValue. + * @member {number} cValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.cValue = 0; + + /** + * VariantValue bValue. + * @member {boolean} bValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.bValue = false; + + /** + * VariantValue strValue. + * @member {string} strValue + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.strValue = ""; + + /** + * VariantValue timestamp. + * @member {number} timestamp + * @memberof ICD.Protobuf.VariantValue + * @instance + */ + VariantValue.prototype.timestamp = 0; + + /** + * Creates a new VariantValue instance using the specified properties. + * @function create + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {ICD.Protobuf.IVariantValue=} [properties] Properties to set + * @returns {ICD.Protobuf.VariantValue} VariantValue instance + */ + VariantValue.create = function create(properties) { + return new VariantValue(properties); + }; + + /** + * Encodes the specified VariantValue message. Does not implicitly {@link ICD.Protobuf.VariantValue.verify|verify} messages. + * @function encode + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {ICD.Protobuf.IVariantValue} message VariantValue message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VariantValue.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.nodeId != null && Object.hasOwnProperty.call(message, "nodeId")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.nodeId); + if (message.dValue != null && Object.hasOwnProperty.call(message, "dValue")) + writer.uint32(/* id 2, wireType 1 =*/17).double(message.dValue); + if (message.fValue != null && Object.hasOwnProperty.call(message, "fValue")) + writer.uint32(/* id 3, wireType 5 =*/29).float(message.fValue); + if (message.ui64Value != null && Object.hasOwnProperty.call(message, "ui64Value")) + writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.ui64Value); + if (message.i64Value != null && Object.hasOwnProperty.call(message, "i64Value")) + writer.uint32(/* id 5, wireType 0 =*/40).sint64(message.i64Value); + if (message.uiValue != null && Object.hasOwnProperty.call(message, "uiValue")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.uiValue); + if (message.iValue != null && Object.hasOwnProperty.call(message, "iValue")) + writer.uint32(/* id 7, wireType 0 =*/56).sint32(message.iValue); + if (message.usValue != null && Object.hasOwnProperty.call(message, "usValue")) + writer.uint32(/* id 8, wireType 0 =*/64).uint32(message.usValue); + if (message.sValue != null && Object.hasOwnProperty.call(message, "sValue")) + writer.uint32(/* id 9, wireType 0 =*/72).sint32(message.sValue); + if (message.ucValue != null && Object.hasOwnProperty.call(message, "ucValue")) + writer.uint32(/* id 10, wireType 0 =*/80).uint32(message.ucValue); + if (message.cValue != null && Object.hasOwnProperty.call(message, "cValue")) + writer.uint32(/* id 11, wireType 0 =*/88).sint32(message.cValue); + if (message.bValue != null && Object.hasOwnProperty.call(message, "bValue")) + writer.uint32(/* id 12, wireType 0 =*/96).bool(message.bValue); + if (message.strValue != null && Object.hasOwnProperty.call(message, "strValue")) + writer.uint32(/* id 13, wireType 2 =*/106).string(message.strValue); + if (message.timestamp != null && Object.hasOwnProperty.call(message, "timestamp")) + writer.uint32(/* id 14, wireType 1 =*/113).double(message.timestamp); + return writer; + }; + + /** + * Encodes the specified VariantValue message, length delimited. Does not implicitly {@link ICD.Protobuf.VariantValue.verify|verify} messages. + * @function encodeDelimited + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {ICD.Protobuf.IVariantValue} message VariantValue message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + VariantValue.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a VariantValue message from the specified reader or buffer. + * @function decode + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {ICD.Protobuf.VariantValue} VariantValue + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VariantValue.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.ICD.Protobuf.VariantValue(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.nodeId = reader.uint32(); + break; + } + case 2: { + message.dValue = reader.double(); + break; + } + case 3: { + message.fValue = reader.float(); + break; + } + case 4: { + message.ui64Value = reader.uint64(); + break; + } + case 5: { + message.i64Value = reader.sint64(); + break; + } + case 6: { + message.uiValue = reader.uint32(); + break; + } + case 7: { + message.iValue = reader.sint32(); + break; + } + case 8: { + message.usValue = reader.uint32(); + break; + } + case 9: { + message.sValue = reader.sint32(); + break; + } + case 10: { + message.ucValue = reader.uint32(); + break; + } + case 11: { + message.cValue = reader.sint32(); + break; + } + case 12: { + message.bValue = reader.bool(); + break; + } + case 13: { + message.strValue = reader.string(); + break; + } + case 14: { + message.timestamp = reader.double(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a VariantValue message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {ICD.Protobuf.VariantValue} VariantValue + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + VariantValue.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a VariantValue message. + * @function verify + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + VariantValue.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.nodeId != null && message.hasOwnProperty("nodeId")) + if (!$util.isInteger(message.nodeId)) + return "nodeId: integer expected"; + if (message.dValue != null && message.hasOwnProperty("dValue")) + if (typeof message.dValue !== "number") + return "dValue: number expected"; + if (message.fValue != null && message.hasOwnProperty("fValue")) + if (typeof message.fValue !== "number") + return "fValue: number expected"; + if (message.ui64Value != null && message.hasOwnProperty("ui64Value")) + if (!$util.isInteger(message.ui64Value) && !(message.ui64Value && $util.isInteger(message.ui64Value.low) && $util.isInteger(message.ui64Value.high))) + return "ui64Value: integer|Long expected"; + if (message.i64Value != null && message.hasOwnProperty("i64Value")) + if (!$util.isInteger(message.i64Value) && !(message.i64Value && $util.isInteger(message.i64Value.low) && $util.isInteger(message.i64Value.high))) + return "i64Value: integer|Long expected"; + if (message.uiValue != null && message.hasOwnProperty("uiValue")) + if (!$util.isInteger(message.uiValue)) + return "uiValue: integer expected"; + if (message.iValue != null && message.hasOwnProperty("iValue")) + if (!$util.isInteger(message.iValue)) + return "iValue: integer expected"; + if (message.usValue != null && message.hasOwnProperty("usValue")) + if (!$util.isInteger(message.usValue)) + return "usValue: integer expected"; + if (message.sValue != null && message.hasOwnProperty("sValue")) + if (!$util.isInteger(message.sValue)) + return "sValue: integer expected"; + if (message.ucValue != null && message.hasOwnProperty("ucValue")) + if (!$util.isInteger(message.ucValue)) + return "ucValue: integer expected"; + if (message.cValue != null && message.hasOwnProperty("cValue")) + if (!$util.isInteger(message.cValue)) + return "cValue: integer expected"; + if (message.bValue != null && message.hasOwnProperty("bValue")) + if (typeof message.bValue !== "boolean") + return "bValue: boolean expected"; + if (message.strValue != null && message.hasOwnProperty("strValue")) + if (!$util.isString(message.strValue)) + return "strValue: string expected"; + if (message.timestamp != null && message.hasOwnProperty("timestamp")) + if (typeof message.timestamp !== "number") + return "timestamp: number expected"; + return null; + }; + + /** + * Creates a VariantValue message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {Object.} object Plain object + * @returns {ICD.Protobuf.VariantValue} VariantValue + */ + VariantValue.fromObject = function fromObject(object) { + if (object instanceof $root.ICD.Protobuf.VariantValue) + return object; + var message = new $root.ICD.Protobuf.VariantValue(); + if (object.nodeId != null) + message.nodeId = object.nodeId >>> 0; + if (object.dValue != null) + message.dValue = Number(object.dValue); + if (object.fValue != null) + message.fValue = Number(object.fValue); + if (object.ui64Value != null) + if ($util.Long) + (message.ui64Value = $util.Long.fromValue(object.ui64Value)).unsigned = true; + else if (typeof object.ui64Value === "string") + message.ui64Value = parseInt(object.ui64Value, 10); + else if (typeof object.ui64Value === "number") + message.ui64Value = object.ui64Value; + else if (typeof object.ui64Value === "object") + message.ui64Value = new $util.LongBits(object.ui64Value.low >>> 0, object.ui64Value.high >>> 0).toNumber(true); + if (object.i64Value != null) + if ($util.Long) + (message.i64Value = $util.Long.fromValue(object.i64Value)).unsigned = false; + else if (typeof object.i64Value === "string") + message.i64Value = parseInt(object.i64Value, 10); + else if (typeof object.i64Value === "number") + message.i64Value = object.i64Value; + else if (typeof object.i64Value === "object") + message.i64Value = new $util.LongBits(object.i64Value.low >>> 0, object.i64Value.high >>> 0).toNumber(); + if (object.uiValue != null) + message.uiValue = object.uiValue >>> 0; + if (object.iValue != null) + message.iValue = object.iValue | 0; + if (object.usValue != null) + message.usValue = object.usValue >>> 0; + if (object.sValue != null) + message.sValue = object.sValue | 0; + if (object.ucValue != null) + message.ucValue = object.ucValue >>> 0; + if (object.cValue != null) + message.cValue = object.cValue | 0; + if (object.bValue != null) + message.bValue = Boolean(object.bValue); + if (object.strValue != null) + message.strValue = String(object.strValue); + if (object.timestamp != null) + message.timestamp = Number(object.timestamp); + return message; + }; + + /** + * Creates a plain object from a VariantValue message. Also converts values to other types if specified. + * @function toObject + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {ICD.Protobuf.VariantValue} message VariantValue + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + VariantValue.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.nodeId = 0; + object.dValue = 0; + object.fValue = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.ui64Value = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.ui64Value = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.i64Value = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.i64Value = options.longs === String ? "0" : 0; + object.uiValue = 0; + object.iValue = 0; + object.usValue = 0; + object.sValue = 0; + object.ucValue = 0; + object.cValue = 0; + object.bValue = false; + object.strValue = ""; + object.timestamp = 0; + } + if (message.nodeId != null && message.hasOwnProperty("nodeId")) + object.nodeId = message.nodeId; + if (message.dValue != null && message.hasOwnProperty("dValue")) + object.dValue = options.json && !isFinite(message.dValue) ? String(message.dValue) : message.dValue; + if (message.fValue != null && message.hasOwnProperty("fValue")) + object.fValue = options.json && !isFinite(message.fValue) ? String(message.fValue) : message.fValue; + if (message.ui64Value != null && message.hasOwnProperty("ui64Value")) + if (typeof message.ui64Value === "number") + object.ui64Value = options.longs === String ? String(message.ui64Value) : message.ui64Value; + else + object.ui64Value = options.longs === String ? $util.Long.prototype.toString.call(message.ui64Value) : options.longs === Number ? new $util.LongBits(message.ui64Value.low >>> 0, message.ui64Value.high >>> 0).toNumber(true) : message.ui64Value; + if (message.i64Value != null && message.hasOwnProperty("i64Value")) + if (typeof message.i64Value === "number") + object.i64Value = options.longs === String ? String(message.i64Value) : message.i64Value; + else + object.i64Value = options.longs === String ? $util.Long.prototype.toString.call(message.i64Value) : options.longs === Number ? new $util.LongBits(message.i64Value.low >>> 0, message.i64Value.high >>> 0).toNumber() : message.i64Value; + if (message.uiValue != null && message.hasOwnProperty("uiValue")) + object.uiValue = message.uiValue; + if (message.iValue != null && message.hasOwnProperty("iValue")) + object.iValue = message.iValue; + if (message.usValue != null && message.hasOwnProperty("usValue")) + object.usValue = message.usValue; + if (message.sValue != null && message.hasOwnProperty("sValue")) + object.sValue = message.sValue; + if (message.ucValue != null && message.hasOwnProperty("ucValue")) + object.ucValue = message.ucValue; + if (message.cValue != null && message.hasOwnProperty("cValue")) + object.cValue = message.cValue; + if (message.bValue != null && message.hasOwnProperty("bValue")) + object.bValue = message.bValue; + if (message.strValue != null && message.hasOwnProperty("strValue")) + object.strValue = message.strValue; + if (message.timestamp != null && message.hasOwnProperty("timestamp")) + object.timestamp = options.json && !isFinite(message.timestamp) ? String(message.timestamp) : message.timestamp; + return object; + }; + + /** + * Converts this VariantValue to JSON. + * @function toJSON + * @memberof ICD.Protobuf.VariantValue + * @instance + * @returns {Object.} JSON object + */ + VariantValue.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for VariantValue + * @function getTypeUrl + * @memberof ICD.Protobuf.VariantValue + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + VariantValue.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/ICD.Protobuf.VariantValue"; + }; + + return VariantValue; + })(); + + return Protobuf; + })(); + + return ICD; +})(); + +module.exports = $root; diff --git a/index.js b/index.js new file mode 100644 index 0000000..28d1487 --- /dev/null +++ b/index.js @@ -0,0 +1,56 @@ +// index.js +global.WebSocket = require('ws'); +const Client = require('./client'); + +const client = new Client('127.0.0.1', 17000, false); + +// Print the node information (name and routing) +function printLoggedNodes() { + client.requestLoggedNodes() + .then(nodes => { + console.log("Connected nodes:"); + nodes.forEach(node => { + console.log(`Name: ${node.name}, Routing: ${node.routing}`); + }); + console.log('--------------------'); + }) + .catch(err => { + console.error("Error retrieving logged nodes:", err); + }); +} + +function onDataPointsReceived(dataPoints) { + dataPoints.forEach(point => { + console.log(`Timestamp: ${point.timestamp}`); + if (point.value && point.value["Output"]) { + const val = point.value["Output"]; + console.log(`Min: ${val.min}`); + console.log(`Max: ${val.max}`); + console.log(`Last: ${val.last}`); + } else { + console.log("No data for 'Output':", point); + } + console.log('--------------------'); + }); + // When finished processing, disconnect and exit + setTimeout(() => { + client.disconnect(); + process.exit(0); + }, 5000); +} + +function requestDataPoints(limits) { + console.log("Log limits received:", limits); + return client.requestDataPoints(["Output"], limits.start_s, limits.end_s, 25); +} + +function onError(error) { + console.error("Error:", error); +} + +// Kick off both the nodes request and data points request: +printLoggedNodes(); +client.requestLogLimits() + .then(requestDataPoints) + .then(onDataPointsReceived) + .catch(onError); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..edf340a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3490 @@ +{ + "name": "cdplogger-js", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "protobufjs": "^7.4.0" + }, + "devDependencies": { + "jest": "^29.7.0", + "ws": "^8.18.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "dev": true, + "dependencies": { + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.26.10" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.120", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", + "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/long": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b79cf3a --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "devDependencies": { + "jest": "^29.7.0", + "ws": "^8.18.1" + }, + "scripts": { + "test": "jest" + }, + "dependencies": { + "protobufjs": "^7.4.0" + } +} diff --git a/test/client.test.js b/test/client.test.js new file mode 100644 index 0000000..98024cb --- /dev/null +++ b/test/client.test.js @@ -0,0 +1,221 @@ +// client.test.js +global.WebSocket = require('ws'); +const Client = require('../client'); +const fakeData = require('./fakeData'); + + +describe('ClientTester', () => { + let client; + beforeEach(() => { + // Override _connect to return a fake ws object that doesn't try to connect. + Client.prototype._connect = function(url) { + return { + _url: url, + close: jest.fn(), + // You can add any other dummy methods as needed. + }; + }; + // Create a new client instance. + client = new Client('127.0.0.1', 17000, true); + // Adjust the client’s lastTimeRequest so that a new time request will be triggered. + client.lastTimeRequest = Date.now() / 1000 - 11; + // Prepopulate the lookup maps. + client.idToName = { 0: "Output", 1: "CPULoad" }; + client.nameToId = { "Output": 0, "CPULoad": 1 }; + }); + + afterEach(() => { + client = null; + }); + + test('test_this', () => { + expect(true).toBe(true); + }); + + test('test_run_event_loop', () => { + // In our JS version we might not have a runEventLoop, + // so we simulate it by adding a dummy method. + client.runEventLoop = jest.fn(); + client.runEventLoop(); + expect(client.runEventLoop).toHaveBeenCalled(); + }); + + test('test_disconnect', () => { + // Replace ws and _cleanupQueuedRequests with mocks. + client.ws = { close: jest.fn() }; + client._cleanupQueuedRequests = jest.fn(); + client.disconnect(); + expect(client.ws.close).toHaveBeenCalled(); + expect(client._cleanupQueuedRequests).toHaveBeenCalled(); + }); + + test('test_time_request', () => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._timeRequest(); + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + }); + + test('test_version_request_also_sends_time_request', () => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendApiVersionRequest = jest.fn(); + client.requestApiVersion(); + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + expect(client._sendApiVersionRequest).toHaveBeenCalledWith(1); + }); + + test('test_log_limits_request_also_sends_time_request', () => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLogLimitsRequest = jest.fn(); + client.requestLogLimits(); + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + expect(client._sendLogLimitsRequest).toHaveBeenCalledWith(1); + }); + + test('test_logged_nodes_request_also_sends_time_request', () => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLoggedNodesRequest = jest.fn(); + client.requestLoggedNodes(); + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + expect(client._sendLoggedNodesRequest).toHaveBeenCalledWith(1); + }); + + test('test_data_points_request_also_sends_time_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendDataPointsRequest = jest.fn(); + client.requestDataPoints(["Output", "CPULoad"], 1530613239.0, 1530613270.0, 500); + // Wait a tick for the promise chain to complete. + setImmediate(() => { + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + expect(client._sendDataPointsRequest).toHaveBeenCalledWith([0, 1], 1530613239.0, 1530613270.0, 1, 500); + done(); + }); + }); + + + test('test_version_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendApiVersionRequest = jest.fn(); + client.requestApiVersion() + .then(version => { + expect(version).not.toBeNull(); + done(); + }) + .catch(done.fail); + // Simulate a valid API version response. + const response = fakeData.createApiVersionResponse(); + client._parseMessage(response); + }); + + test('test_version_request_error', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendApiVersionRequest = jest.fn(); + client.requestApiVersion() + .then(() => done.fail("Promise should not resolve")) + .catch(err => { + expect(err).toBeInstanceOf(Error); + done(); + }); + // Simulate an API version error (version too low). + const response = fakeData.createApiVersionErrorResponse(); + client._parseMessage(response); + }); + + test('test_log_limits_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLogLimitsRequest = jest.fn(); + client.requestLogLimits() + .then(limits => { + expect(limits.start_s).toBeCloseTo(1529497537.61); + expect(limits.end_s).toBeCloseTo(1531389483.02); + done(); + }) + .catch(done.fail); + const response = fakeData.createLogLimitsResponse(); + client._parseMessage(response); + }); + + test('test_log_limits_request_with_time_diff', done => { + client.timeDiff = 10; + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLogLimitsRequest = jest.fn(); + client.requestLogLimits() + .then(limits => { + expect(limits.start_s).toBeCloseTo(1529497537.61 + 10); + expect(limits.end_s).toBeCloseTo(1531389483.02 + 10); + done(); + }) + .catch(done.fail); + const response = fakeData.createLogLimitsResponse(); + client._parseMessage(response); + }); + + test('test_logged_nodes_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLoggedNodesRequest = jest.fn(); + client.requestLoggedNodes() + .then(nodes => { + expect(nodes[0].name).toBe("Output"); + expect(nodes[0].routing).toBe("loggerApp.Sine.Output"); + done(); + }) + .catch(done.fail); + const response = fakeData.createLoggedNodesResponse(1); + client._parseMessage(response); + }); + + test('test_data_points_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendDataPointsRequest = jest.fn(); + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) + .then(dataPoints => { + expect(dataPoints[0].timestamp).toBeCloseTo(1531313250.0); + expect(dataPoints[0].value["Output"].min).toBeCloseTo(0.638855091434); + expect(dataPoints[0].value["Output"].max).toBeCloseTo(0.639955091434); + expect(dataPoints[0].value["Output"].last).toBeCloseTo(0.638855091434); + done(); + }) + .catch(done.fail); + const response = fakeData.createDataPointResponse(); + client._parseMessage(response); + }); + + test('test_data_points_request_error_on_names', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLoggedNodesRequest = jest.fn(); + client.requestDataPoints(["Outputt", "CPULoad"], 1531313250.0, 1531461231.0, 500) + .catch(error => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toMatch(/Outputt/); + done(); + }); + // Simulate a logged nodes response that does not include "Outputt" + const response = fakeData.createLoggedNodesResponse(2); + client._parseMessage(response); + }); + + test('test_error_response_on_log_limits_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendLogLimitsRequest = jest.fn(); + client.requestLogLimits() + .catch(error => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe("Error message"); + done(); + }); + const response = fakeData.createErrorResponse(); + client._parseMessage(response); + }); +}); diff --git a/test/fakeData.js b/test/fakeData.js new file mode 100644 index 0000000..74f9fdc --- /dev/null +++ b/test/fakeData.js @@ -0,0 +1,110 @@ +// Define a simple Container object to simulate our protobuf types. +const Container = { + Type: { + eSignalInfoRequest: 1, + eSignalInfoResponse: 2, + eSignalDataRequest: 3, + eSignalDataResponse: 4, + eCriterionLimitsRequest: 5, + eCriterionLimitsResponse: 6, + eVersionRequest: 7, + eVersionResponse: 8, + eError: 9, + eTimeRequest: 10, + eTimeResponse: 11, + eEventSenderTagsRequest: 12, + eEventSenderTagsResponse: 13, + eCountEventsRequest: 14, + eCountEventsResponse: 15, + eEventsRequest: 16, + eEventsResponse: 17 + } +}; + +function createApiVersionResponse() { + return { + messageType: Container.Type.eVersionResponse, + versionResponse: { requestId: 1, version: "3.0" } + }; +} + +function createApiVersionErrorResponse() { + return { + messageType: Container.Type.eVersionResponse, + versionResponse: { requestId: 1, version: "1.0" } + }; +} + +function createLogLimitsResponse() { + return { + messageType: Container.Type.eCriterionLimitsResponse, // value 6 + criterionLimitsResponse: { + requestId: 1, + criterionMin: 1529497537.61, + criterionMax: 1531389483.02 + } + }; +} + +function createLoggedNodesResponse(requestId) { + return { + messageType: Container.Type.eSignalInfoResponse, + signalInfoResponse: { + requestId: requestId, + name: ["Output", "CPULoad", "MemUsed", "CDPSignal"], + id: [0, 1, 2, 3], + type: [], + path: [ + "loggerApp.Sine.Output", + "loggerApp.CPULoad", + "loggerApp.MemUsed", + "loggerApp.CDPSignal" + ] + } + }; +} + +function createDataPointResponse() { + return { + messageType: Container.Type.eSignalDataResponse, + signalDataResponse: { + requestId: 1, + criterion: [1531313250.0, 1530613239.063119], + row: [ + { + signalId: [0, 1], + minValues: [{ dValue: 0.638855091434 }, { dValue: 0.538855091434 }], + maxValues: [{ dValue: 0.639955091434 }, { dValue: 0.53955091434 }], + lastValues: [{ dValue: 0.638855091434 }, { dValue: 0.538855091434 }] + }, + { + signalId: [0, 1], + minValues: [{ dValue: 0.738855091434 }, { dValue: 0.338855091434 }], + maxValues: [{ dValue: 0.739955091434 }, { dValue: 0.358855091434 }], + lastValues: [{ dValue: 0.738855091434 }, { dValue: 0.348855091434 }] + } + ] + } + }; +} + +function createErrorResponse() { + return { + messageType: Container.Type.eError, + error: { + requestId: 1, + errorMessage: "Error message", + errorCode: 1234567 + } + }; +} + +module.exports = { + createApiVersionResponse, + createApiVersionErrorResponse, + createLogLimitsResponse, + createLoggedNodesResponse, + createDataPointResponse, + createErrorResponse, + Container +}; From cbea69569434f92e1c29f535e4ddb659b1cb52bc Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Sun, 23 Mar 2025 15:25:15 +0200 Subject: [PATCH 04/37] Added support for Events and a test A test for Events using the example case in CDP Studio --- .gitignore | 3 +- README.md | 14 ++- client.js | 224 +++++++++++++++++++++++++++++++++++-------- event.js | 117 ++++++++++++++++++++++ index.js | 121 ++++++++++++++++------- package-lock.json | 2 +- test/client.test.js | 91 +++++++++++++----- test/testTimeSync.js | 134 ++++++++++++++++++++++++++ 8 files changed, 605 insertions(+), 101 deletions(-) create mode 100644 event.js create mode 100644 test/testTimeSync.js diff --git a/.gitignore b/.gitignore index 9e99588..909f568 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -protos/ \ No newline at end of file +protos/ +helpers/ \ No newline at end of file diff --git a/README.md b/README.md index 933c90e..ad458c1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # CDPLogger Client for JavaScript -A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. +A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. +For more information about CDP Studio see https://cdpstudio.com/. ## Installation @@ -13,20 +14,29 @@ npm install ## Running Tests + To run the automatic tests with fake data, execute: ```bash npm test ``` + ## Usage + The index.js file contains a simple logger built for the CDP Studio example case. 1. Set up and run the Logger in CDP Studio. (Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) +https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html 2. Run the index.js file from the command line: ```bash node index.js -``` \ No newline at end of file +``` + + +## Contact + +Email: support@cdptech.com \ No newline at end of file diff --git a/client.js b/client.js index c2c4945..e0df47b 100644 --- a/client.js +++ b/client.js @@ -1,22 +1,59 @@ -// Example: client.js +const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; +const CDPValueType = root.ICD.Protobuf.CDPValueType; class Client { - constructor(host, port = 17000, autoReconnect = true) { + /** + * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000") + * @param {boolean} [autoReconnect=true] - Automatically reconnect if the connection is lost + */ + constructor(endpoint, autoReconnect = true) { + // If endpoint does not start with "ws://" or "wss://", prepend "ws://" + let url = endpoint; + if (!/^wss?:\/\//.test(url)) { + url = `ws://${url}`; + } + this.reqId = -1; this.autoReconnect = autoReconnect; + + // Time synchronization is enabled by default. + this.enableTimeSync = true; + this.isOpen = false; this.queuedRequests = {}; this.storedPromises = {}; this.nameToId = {}; this.idToName = {}; + + // New mapping for signal types. + this.nameToType = {}; + + // Time-diff related this.timeDiff = 0; this.timeReceived = null; this.lastTimeRequest = Date.now() / 1000; this.haveSentQueuedReq = false; this.roundTripTimes = {}; - this.ws = this._connect(`ws://${host}:${port}`); + + // Create the WebSocket connection + this.ws = this._connect(url); + } + + /** + * Enable or disable time synchronization. + * @param {boolean} enable - If true, time sync is enabled; if false, time sync is disabled. + */ + setEnableTimeSync(enable) { + this.enableTimeSync = enable; + if (!enable) { + // Cancel any pending time sync requests so they won’t update timeDiff later. + for (const key in this.storedPromises) { + this.storedPromises[key].reject(new Error("Time sync disabled")); + } + this.storedPromises = {}; + } } _connect(url) { @@ -32,7 +69,9 @@ class Client { _onOpen(ws) { this.isOpen = true; - this._updateTimeDiff(); + if (this.enableTimeSync) { + this._updateTimeDiff(); + } this.lastTimeRequest = Date.now() / 1000; } @@ -133,9 +172,42 @@ class Client { return promise; } + /** + * Request events based on the provided query parameters. + * @param {Object} query - An object matching the EventQuery schema. + * For example: + * { + * timeRangeBegin: 1620000000, + * timeRangeEnd: 1620003600, + * codeMask: 0, + * limit: 100, + * offset: 0, + * flags: 1 // Numeric flags as defined in your protocol + * } + * @returns {Promise} Resolves with an array of events. + */ + requestEvents(query) { + this._timeRequest(); + const requestId = this._getRequestId(); + if (!this.isOpen) { + this.queuedRequests[requestId] = { type: "events", query: query }; + } else { + this._sendEventsRequest(requestId, query); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + _sendEventsRequest(requestId, query) { + const container = Container.create(); + container.messageType = Container.Type.eEventsRequest; + container.eventsRequest = { requestId: requestId, query: query }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } _handleMessage(ws, message) { - // console.log("Raw data:", message); const data = Container.decode(new Uint8Array(message)); this._parseMessage(data); } @@ -149,6 +221,7 @@ class Client { reject(new Error(data.error.errorMessage)); } break; + case Container.Type.eTimeResponse: this.timeReceived = Date.now() / 1000; if (this.storedPromises[data.timeResponse.requestId]) { @@ -157,7 +230,8 @@ class Client { resolve(data.timeResponse.timestamp); } break; - case Container.Type.eSignalInfoResponse: + + case Container.Type.eSignalInfoResponse: { const nodes = []; this.nameToId = {}; this.idToName = {}; @@ -166,6 +240,9 @@ class Client { name: data.signalInfoResponse.name[i], routing: data.signalInfoResponse.path[i] }; + if (data.signalInfoResponse.tagMap && data.signalInfoResponse.tagMap[i]) { + node.tags = this._convertTagMap(data.signalInfoResponse.tagMap[i]); + } this.nameToId[data.signalInfoResponse.name[i]] = data.signalInfoResponse.id[i]; this.idToName[data.signalInfoResponse.id[i]] = data.signalInfoResponse.name[i]; nodes.push(node); @@ -176,26 +253,33 @@ class Client { resolve(nodes); } break; + } + case Container.Type.eCriterionLimitsResponse: - data.criterionLimitsResponse.criterionMin += this.timeDiff; - data.criterionLimitsResponse.criterionMax += this.timeDiff; - const limits = { - start_s: data.criterionLimitsResponse.criterionMin, - end_s: data.criterionLimitsResponse.criterionMax - }; - if (this.storedPromises[data.criterionLimitsResponse.requestId]) { - const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; - delete this.storedPromises[data.criterionLimitsResponse.requestId]; - resolve(limits); + if (this.enableTimeSync) { + data.criterionLimitsResponse.criterionMin += this.timeDiff; + data.criterionLimitsResponse.criterionMax += this.timeDiff; + } + { + const limits = { + startS: data.criterionLimitsResponse.criterionMin, + endS: data.criterionLimitsResponse.criterionMax + }; + if (this.storedPromises[data.criterionLimitsResponse.requestId]) { + const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; + delete this.storedPromises[data.criterionLimitsResponse.requestId]; + resolve(limits); + } } break; - case Container.Type.eVersionResponse: + + case Container.Type.eVersionResponse: { const version = parseFloat(data.versionResponse.version); if (version < 3.0) { if (this.storedPromises[data.versionResponse.requestId]) { const { reject } = this.storedPromises[data.versionResponse.requestId]; delete this.storedPromises[data.versionResponse.requestId]; - reject(new Error("CDP version needs to be 3.0 or newer.")); + reject(new Error("CDP version needs to be 4.3 or newer.")); } } else { if (this.storedPromises[data.versionResponse.requestId]) { @@ -205,11 +289,15 @@ class Client { } } break; - case Container.Type.eSignalDataResponse: + } + + case Container.Type.eSignalDataResponse: { let dataPoints = []; let index = 0; for (const row of data.signalDataResponse.row) { - data.signalDataResponse.criterion[index] += this.timeDiff; + if (this.enableTimeSync) { + data.signalDataResponse.criterion[index] += this.timeDiff; + } let signalNames = []; for (const signalId of row.signalId) { signalNames.push(this.idToName[signalId]); @@ -232,37 +320,79 @@ class Client { resolve(dataPoints); } break; + } + + case Container.Type.eEventsResponse: { + if (this.storedPromises[data.eventsResponse.requestId]) { + const { resolve } = this.storedPromises[data.eventsResponse.requestId]; + delete this.storedPromises[data.eventsResponse.requestId]; + resolve(data.eventsResponse.events); + } + break; + } + default: console.error("Unknown message type", data.messageType); } } + _convertTagMap(tagMapObj) { + const result = {}; + if (!tagMapObj || !tagMapObj.tags) { + return result; + } + for (const [tagKey, tagInfo] of Object.entries(tagMapObj.tags)) { + result[tagKey] = { + value: tagInfo.value, + source: tagInfo.source + }; + } + return result; + } + _createValue(signalNames, minValues, maxValues, lastValues) { const value = {}; for (let i = 0; i < signalNames.length; i++) { + const signalType = this.nameToType[signalNames[i]] || CDPValueType.eDOUBLE; value[signalNames[i]] = { - min: this._valueFromVariant(minValues[i]), - max: this._valueFromVariant(maxValues[i]), - last: this._valueFromVariant(lastValues[i]) + min: this._valueFromVariant(minValues[i], signalType), + max: this._valueFromVariant(maxValues[i], signalType), + last: this._valueFromVariant(lastValues[i], signalType) }; } return value; } - _valueFromVariant(value) { - if (value.dValue !== undefined) return value.dValue; - if (value.fValue !== undefined) return value.fValue; - if (value.ui64Value !== undefined) return value.ui64Value; - if (value.i64Value !== undefined) return value.i64Value; - if (value.uiValue !== undefined) return value.uiValue; - if (value.iValue !== undefined) return value.iValue; - if (value.usValue !== undefined) return value.usValue; - if (value.sValue !== undefined) return value.sValue; - if (value.ucValue !== undefined) return value.ucValue; - if (value.cValue !== undefined) return value.cValue; - if (value.bValue !== undefined) return value.bValue; - if (value.strValue !== undefined) return value.strValue; - return null; + _valueFromVariant(variant, type) { + if (!variant) return null; + switch (type) { + case CDPValueType.eDOUBLE: + return variant.dValue; + case CDPValueType.eFLOAT: + return variant.fValue; + case CDPValueType.eUINT64: + return variant.ui64Value; + case CDPValueType.eINT64: + return variant.i64Value; + case CDPValueType.eUINT: + return variant.uiValue; + case CDPValueType.eINT: + return variant.iValue; + case CDPValueType.eUSHORT: + return variant.usValue; + case CDPValueType.eSHORT: + return variant.sValue; + case CDPValueType.eUCHAR: + return variant.ucValue; + case CDPValueType.eCHAR: + return variant.cValue; + case CDPValueType.eBOOL: + return variant.bValue; + case CDPValueType.eSTRING: + return variant.strValue; + default: + return null; + } } _sendQueuedRequests() { @@ -276,6 +406,8 @@ class Client { this._reqDataPoints(req[1], req[2], req[3], req[4], requestId); } else if (req === "api_version") { this._sendApiVersionRequest(requestId); + } else if (req && req.type === "events") { + this._sendEventsRequest(requestId, req.query); } } this.queuedRequests = {}; @@ -287,12 +419,14 @@ class Client { } _timeRequest() { + if (!this.enableTimeSync) return; if ((Date.now() / 1000) > this.lastTimeRequest + 10) { this._updateTimeDiff(); } } _updateTimeDiff() { + if (!this.enableTimeSync) return; const requestId = this._getRequestId(); const timeSent = Date.now() / 1000; this._requestTime(requestId) @@ -305,16 +439,21 @@ class Client { } _requestTime(reqId) { + if (!this.enableTimeSync) { + return Promise.resolve(0); + } const requestId = reqId; this.lastTimeRequest = Date.now() / 1000; + // Always send the time request. this._sendTimeRequest(requestId); - return new Promise((resolve, reject) => { + // Create the promise and store the callbacks. + const promise = new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); + return promise; } - + _sendTimeRequest(requestId) { - // Create a Container message for time request const container = Container.create(); container.messageType = Container.Type.eTimeRequest; container.timeRequest = { requestId: requestId }; @@ -323,6 +462,7 @@ class Client { } _setTimeDiff(timestamp, timeSent) { + if (!this.enableTimeSync) return; const clientTime = this.timeReceived; const roundTripTime = clientTime - timeSent; const serverTime = (timestamp / 1e9) + roundTripTime / 2; @@ -408,8 +548,8 @@ class Client { requestId: requestId, signalId: nodeIds, numOfDatapoints: noOfDataPoints, - criterionMin: startS - this.timeDiff, - criterionMax: endS - this.timeDiff + criterionMin: this.enableTimeSync ? (startS - this.timeDiff) : startS, + criterionMax: this.enableTimeSync ? (endS - this.timeDiff) : endS }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); diff --git a/event.js b/event.js new file mode 100644 index 0000000..9bc1602 --- /dev/null +++ b/event.js @@ -0,0 +1,117 @@ +// event.js +global.WebSocket = require('ws'); +const Client = require('./client'); + +/** + * Recursively normalizes an object/value. + * If the value is a string, it trims whitespace. + * If it's an object (or array), it normalizes each property. + * This helps ensure that logically identical values produce the same string. + * + * @param {*} val - The value to normalize. + * @returns {*} - The normalized value. + */ +function normalizeValue(val) { + if (typeof val === 'string') { + return val.trim(); + } else if (typeof val === 'object' && val !== null) { + if (Array.isArray(val)) { + return val.map(normalizeValue); + } else { + const keys = Object.keys(val).sort(); + const normalized = {}; + for (const key of keys) { + normalized[key.trim()] = normalizeValue(val[key]); + } + return normalized; + } + } + return val; +} + +/** + * Recursively returns a canonical JSON string for the given object. + * Keys are sorted so that two objects with the same properties produce the same string. + * + * @param {*} obj - The object/value to canonicalize. + * @returns {string} - The canonical JSON string. + */ +function canonicalize(obj) { + if (typeof obj !== 'object' || obj === null) { + return JSON.stringify(obj); + } + if (Array.isArray(obj)) { + return '[' + obj.map(canonicalize).join(',') + ']'; + } + const keys = Object.keys(obj).sort(); + const result = keys + .map(key => JSON.stringify(key) + ':' + canonicalize(obj[key])) + .join(','); + return '{' + result + '}'; +} + +(async function main() { + const client = new Client('ws://127.0.0.1:17000', false); + try { + // Example query: adjust the time range, etc., as needed: + const query = { + timeRangeBegin: 1742540000, + timeRangeEnd: 1742550000, + codeMask: 0xFFFFFFFF, + limit: 100, + offset: 0, + flags: 1 // 'NewestFirst' from your enum + }; + + const events = await client.requestEvents(query); + + // De-duplicate events using a composite key built from normalized fields. + // We'll canonicalize e.data to handle reordered JSON keys. + const seen = new Set(); + const uniqueEvents = []; + + for (const e of events) { + const tsPart = (typeof e.timestampSec !== 'undefined' && e.timestampSec !== null) + ? String(e.timestampSec) + : ''; + + const codePart = (typeof e.code !== 'undefined' && e.code !== null) + ? String(e.code) + : ''; + + const senderPart = (typeof e.sender !== 'undefined' && e.sender !== null) + ? String(e.sender) + : ''; + + // Canonicalize the data so that JSON field order does not matter + const dataPart = e.data + ? canonicalize(normalizeValue(e.data)) + : ''; + + const compositeKey = `${tsPart}-${codePart}-${senderPart}-${dataPart}`; + + if (!seen.has(compositeKey)) { + seen.add(compositeKey); + uniqueEvents.push(e); + } + } + + // Print the unique events + if (uniqueEvents.length === 0) { + console.log("No events found."); + } else { + for (const evt of uniqueEvents) { + console.log(`Timestamp: ${evt.timestampSec}`); + console.log(`Code: ${evt.code}`); + console.log(`Sender: ${evt.sender}`); + console.log(`Data: ${JSON.stringify(evt.data)}`); + console.log('--------------------'); + } + } + } catch (err) { + console.error("Error retrieving events:", err); + } finally { + client.disconnect(); + process.exit(0); + } +})(); diff --git a/index.js b/index.js index 28d1487..e76f24f 100644 --- a/index.js +++ b/index.js @@ -1,56 +1,113 @@ // index.js +// Example demonstration including an events query for a specific time range (UTC 9:40) + global.WebSocket = require('ws'); const Client = require('./client'); -const client = new Client('127.0.0.1', 17000, false); - -// Print the node information (name and routing) +// Print the node information (name, routing, and tags) function printLoggedNodes() { client.requestLoggedNodes() .then(nodes => { console.log("Connected nodes:"); nodes.forEach(node => { console.log(`Name: ${node.name}, Routing: ${node.routing}`); + if (node.tags) { + console.log("Tags:"); + Object.entries(node.tags).forEach(([key, tagInfo]) => { + console.log(` ${key}: value=${tagInfo.value}, source=${tagInfo.source}`); + }); + } + console.log('--------------------'); }); - console.log('--------------------'); }) .catch(err => { console.error("Error retrieving logged nodes:", err); }); } -function onDataPointsReceived(dataPoints) { - dataPoints.forEach(point => { - console.log(`Timestamp: ${point.timestamp}`); - if (point.value && point.value["Output"]) { - const val = point.value["Output"]; - console.log(`Min: ${val.min}`); - console.log(`Max: ${val.max}`); - console.log(`Last: ${val.last}`); +// Print data points for the "Output" node. +async function printDataPoints() { + try { + const limits = await client.requestLogLimits(); + console.log("Log limits received:", limits); + + const dataPoints = await client.requestDataPoints(["Output"], limits.startS, limits.endS, 25); + console.log("Data Points retrieved:"); + dataPoints.forEach(point => { + console.log(`Timestamp: ${point.timestamp}`); + if (point.value && point.value["Output"]) { + const val = point.value["Output"]; + console.log(`Min: ${val.min}`); + console.log(`Max: ${val.max}`); + console.log(`Last: ${val.last}`); + } else { + console.log("No data for 'Output':", point); + } + console.log('--------------------'); + }); + } catch (err) { + console.error("Error retrieving data points:", err); + } +} + +// Print events retrieved within a time range corresponding to UTC 9:40. +// In this example, we use a 5-minute window starting at UTC 9:40. +async function printEvents() { + try { + // Specify the target time for events in UTC. + // Adjust the date as needed; here we assume a specific date. + const targetDate = new Date("2025-03-21T09:38:00Z"); + const targetTime = targetDate.getTime() / 1000; + // Define a window of 5 minutes (300 seconds) + const timeWindow = 5 * 60; + + const eventQuery = { + timeRangeBegin: targetTime, + timeRangeEnd: targetTime + timeWindow, + codeMask: 0, + limit: 100, + offset: 0, + flags: 0, + // Optionally, add senderConditions or dataConditions if desired. + }; + + const events = await client.requestEvents(eventQuery); + console.log("Events retrieved:"); + if (!events || events.length === 0) { + console.log("No events found with the current query."); } else { - console.log("No data for 'Output':", point); + events.forEach(evt => { + console.log(`Timestamp: ${evt.timestampSec}`); + console.log(` Code: ${evt.data && evt.data.Code ? evt.data.Code : "N/A"}`); + console.log(` Source: ${evt.data && evt.data.Source ? evt.data.Source : "N/A"}`); + console.log(` Text: ${evt.data && evt.data.Text ? evt.data.Text : "N/A"}`); + console.log('--------------------'); + }); } - console.log('--------------------'); - }); - // When finished processing, disconnect and exit - setTimeout(() => { - client.disconnect(); - process.exit(0); - }, 5000); + } catch (err) { + console.error("Error retrieving events:", err); + } } -function requestDataPoints(limits) { - console.log("Log limits received:", limits); - return client.requestDataPoints(["Output"], limits.start_s, limits.end_s, 25); +async function main() { + try { + printLoggedNodes(); + await printDataPoints(); + await printEvents(); + } catch (error) { + console.error("Error in main:", error); + } finally { + client.disconnect(); + process.exit(0); + } } -function onError(error) { - console.error("Error:", error); -} +// Create a new client instance. (In this example, autoReconnect is disabled.) +const client = new Client('ws://127.0.0.1:17000', false); -// Kick off both the nodes request and data points request: -printLoggedNodes(); -client.requestLogLimits() - .then(requestDataPoints) - .then(onDataPointsReceived) - .catch(onError); +// Instead of overriding ws.onopen (which may cancel internal logic), +// add an event listener so that _onOpen is still called. +client.ws.addEventListener("open", () => { + console.log("WebSocket connection established."); + main(); +}); diff --git a/package-lock.json b/package-lock.json index edf340a..cdbd936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "cdplogger-js", + "name": "JavascriptCDPLoggerClient", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test/client.test.js b/test/client.test.js index 98024cb..b53da15 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -1,22 +1,21 @@ -// client.test.js +/*global WebSocket*/ global.WebSocket = require('ws'); const Client = require('../client'); const fakeData = require('./fakeData'); - describe('ClientTester', () => { let client; beforeEach(() => { - // Override _connect to return a fake ws object that doesn't try to connect. - Client.prototype._connect = function(url) { - return { - _url: url, - close: jest.fn(), - // You can add any other dummy methods as needed. + // Override _connect to return a fake ws object that doesn't try to connect. + Client.prototype._connect = function(url) { + return { + _url: url, + close: jest.fn(), + send: jest.fn() + }; }; - }; - // Create a new client instance. - client = new Client('127.0.0.1', 17000, true); + // Create a new client instance using two parameters: endpoint and autoReconnect. + client = new Client('127.0.0.1:17000', true); // Adjust the client’s lastTimeRequest so that a new time request will be triggered. client.lastTimeRequest = Date.now() / 1000 - 11; // Prepopulate the lookup maps. @@ -33,15 +32,12 @@ describe('ClientTester', () => { }); test('test_run_event_loop', () => { - // In our JS version we might not have a runEventLoop, - // so we simulate it by adding a dummy method. client.runEventLoop = jest.fn(); client.runEventLoop(); expect(client.runEventLoop).toHaveBeenCalled(); }); test('test_disconnect', () => { - // Replace ws and _cleanupQueuedRequests with mocks. client.ws = { close: jest.fn() }; client._cleanupQueuedRequests = jest.fn(); client.disconnect(); @@ -95,7 +91,6 @@ describe('ClientTester', () => { done(); }); }); - test('test_version_request', done => { client.isOpen = true; @@ -133,8 +128,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.start_s).toBeCloseTo(1529497537.61); - expect(limits.end_s).toBeCloseTo(1531389483.02); + expect(limits.startS).toBeCloseTo(1529497537.61); + expect(limits.endS).toBeCloseTo(1531389483.02); done(); }) .catch(done.fail); @@ -149,8 +144,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.start_s).toBeCloseTo(1529497537.61 + 10); - expect(limits.end_s).toBeCloseTo(1531389483.02 + 10); + expect(limits.startS).toBeCloseTo(1529497537.61 + 10); + expect(limits.endS).toBeCloseTo(1531389483.02 + 10); done(); }) .catch(done.fail); @@ -194,14 +189,36 @@ describe('ClientTester', () => { client.isOpen = true; client._sendTimeRequest = jest.fn(); client._sendLoggedNodesRequest = jest.fn(); - client.requestDataPoints(["Outputt", "CPULoad"], 1531313250.0, 1531461231.0, 500) + + // Remove "Output" so that the lookup fails. + delete client.nameToId["Output"]; + for (const id in client.idToName) { + if (client.idToName[id] === "Output") { + delete client.idToName[id]; + } + } + + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) .catch(error => { expect(error).toBeInstanceOf(Error); - expect(error.message).toMatch(/Outputt/); + expect(error.message).toMatch(/Output/); done(); }); - // Simulate a logged nodes response that does not include "Outputt" - const response = fakeData.createLoggedNodesResponse(2); + // Simulate a logged nodes response that does NOT include "Output". + const response = { + messageType: fakeData.Container.Type.eSignalInfoResponse, + signalInfoResponse: { + requestId: 2, + name: ["CPULoad", "MemUsed", "CDPSignal"], + id: [1, 2, 3], + type: [], + path: [ + "loggerApp.CPULoad", + "loggerApp.MemUsed", + "loggerApp.CDPSignal" + ] + } + }; client._parseMessage(response); }); @@ -218,4 +235,32 @@ describe('ClientTester', () => { const response = fakeData.createErrorResponse(); client._parseMessage(response); }); + + // Added test for events + test('test_events_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendEventsRequest = jest.fn(); + client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) + .then(events => { + expect(events).toBeDefined(); + expect(events.length).toBe(1); + expect(events[0].sender).toBe("TestSender"); + expect(events[0].data.key).toBe("value"); + expect(events[0].timestampSec).toBeCloseTo(1500); + done(); + }) + .catch(done.fail); + // Simulate an events response. + const response = { + messageType: fakeData.Container.Type.eEventsResponse, + eventsResponse: { + requestId: 1, + events: [ + { sender: "TestSender", data: { key: "value" }, timestampSec: 1500, id: 42, code: 100, status: 1, logstampSec: 1500 } + ] + } + }; + client._parseMessage(response); + }); }); diff --git a/test/testTimeSync.js b/test/testTimeSync.js new file mode 100644 index 0000000..d587a3b --- /dev/null +++ b/test/testTimeSync.js @@ -0,0 +1,134 @@ +// testTimeSync.js +const Client = require('../client'); +const fakeData = require('./fakeData'); + +// Override WebSocket with a dummy that provides a send() method. +global.WebSocket = class { + constructor(url) { + this._url = url; + } + send(data) { + // For our test we simply ignore the sent data. + } +}; + +/** + * Helper function to run an API method with time sync enabled and then disabled. + * It forces an update (by setting lastTimeRequest to an old value) before each call. + * The simulateResponse callback simulates the corresponding response by calling _parseMessage. + */ +async function runThrough(methodName, callFunc, simulateResponse) { + console.log(`\n=== Running ${methodName} with time sync ENABLED ===`); + // Force a time update by setting lastTimeRequest to an old value. + client.lastTimeRequest = Date.now() / 1000 - 20; + // Call the API method. + callFunc(); + // Simulate a response if needed. + if (simulateResponse) simulateResponse(); + // Wait longer for the time sync update to complete. + await new Promise(resolve => setTimeout(resolve, 300)); + console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec`); + + // Now disable time sync. + // Clear any pending time requests so they don't update timeDiff later. + client.storedPromises = {}; + client.setEnableTimeSync(false); + console.log(`\n=== Running ${methodName} with time sync DISABLED ===`); + const previousTimeDiff = client.timeDiff; + client.lastTimeRequest = Date.now() / 1000 - 20; + callFunc(); + // When time sync is disabled, do NOT simulate a response. + await new Promise(resolve => setTimeout(resolve, 300)); + console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)`); + // Re-enable time sync for subsequent tests. + client.setEnableTimeSync(true); +} + +async function runTest() { + // Create a new client instance with only endpoint and autoReconnect. + client = new Client('127.0.0.1:17000', true); + + // Override _sendTimeRequest to simulate an immediate server time response with variable delay. + client._sendTimeRequest = function (requestId) { + console.log(`_sendTimeRequest called with requestId: ${requestId}`); + // Simulate variable network delay (e.g., 50 to 300ms) + const delay = Math.floor(Math.random() * 250) + 50; + setTimeout(() => { + // Simulate a server timestamp in nanoseconds. + const simulatedTimestamp = Date.now() * 1e6; + console.log(`Simulated timestamp for request ${requestId} after ${delay}ms: ${simulatedTimestamp}`); + if (client.storedPromises[requestId]) { + client.storedPromises[requestId].resolve(simulatedTimestamp); + delete client.storedPromises[requestId]; + } + }, delay); + }; + + // Override _updateTimeDiff to perform one measurement and log its details. + client._updateTimeDiff = function () { + if (!this.enableTimeSync) return; + const requestId = this._getRequestId(); + const timeSent = Date.now() / 1000; + // Call _requestTime (which now calls our overridden _sendTimeRequest). + this._requestTime(requestId) + .then(timestamp => { + // Simulate a time response arriving. + this.timeReceived = Date.now() / 1000; + const roundTripTime = this.timeReceived - timeSent; + const serverTime = (timestamp / 1e9) + roundTripTime / 2; + const computedTimeDiff = this.timeReceived - serverTime; + this.timeDiff = computedTimeDiff; + console.log("=== Time Sync Measurement ==="); + console.log(`Time Sent: ${timeSent.toFixed(6)} sec`); + console.log(`Time Received: ${this.timeReceived.toFixed(6)} sec`); + console.log(`Round Trip Time: ${roundTripTime.toFixed(6)} sec`); + console.log(`Simulated Server Time: ${serverTime.toFixed(6)} sec`); + console.log(`Computed timeDiff: ${computedTimeDiff.toFixed(6)} sec`); + }) + .catch(err => console.error(err)); + }; + + // Use the production _requestTime (which already checks enableTimeSync). + // No override needed here. + + // Now run through several public API methods. + await runThrough( + "requestApiVersion", + () => client.requestApiVersion(), + () => { + // Simulate a valid API version response. + const response = fakeData.createApiVersionResponse(); + client._parseMessage(response); + } + ); + + await runThrough( + "requestLogLimits", + () => client.requestLogLimits(), + () => { + const response = fakeData.createLogLimitsResponse(); + client._parseMessage(response); + } + ); + + await runThrough( + "requestLoggedNodes", + () => client.requestLoggedNodes(), + () => { + const response = fakeData.createLoggedNodesResponse(1); + client._parseMessage(response); + } + ); + + await runThrough( + "requestDataPoints", + () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500), + () => { + const response = fakeData.createDataPointResponse(); + client._parseMessage(response); + } + ); +} + +let client; +runTest().catch(console.error); From a5b481003a6dcc11b7412c6bc44d0897f2b820d7 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Sun, 23 Mar 2025 15:33:10 +0200 Subject: [PATCH 05/37] Revert "Added support for Events and a test" This reverts commit cbea69569434f92e1c29f535e4ddb659b1cb52bc. --- .gitignore | 3 +- README.md | 14 +-- client.js | 224 ++++++++----------------------------------- event.js | 117 ---------------------- index.js | 121 +++++++---------------- package-lock.json | 2 +- test/client.test.js | 91 +++++------------- test/testTimeSync.js | 134 -------------------------- 8 files changed, 101 insertions(+), 605 deletions(-) delete mode 100644 event.js delete mode 100644 test/testTimeSync.js diff --git a/.gitignore b/.gitignore index 909f568..9e99588 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ node_modules/ -protos/ -helpers/ \ No newline at end of file +protos/ \ No newline at end of file diff --git a/README.md b/README.md index ad458c1..933c90e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # CDPLogger Client for JavaScript -A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -For more information about CDP Studio see https://cdpstudio.com/. +A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. ## Installation @@ -14,29 +13,20 @@ npm install ## Running Tests - To run the automatic tests with fake data, execute: ```bash npm test ``` - ## Usage - The index.js file contains a simple logger built for the CDP Studio example case. 1. Set up and run the Logger in CDP Studio. (Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) -https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html 2. Run the index.js file from the command line: ```bash node index.js -``` - - -## Contact - -Email: support@cdptech.com \ No newline at end of file +``` \ No newline at end of file diff --git a/client.js b/client.js index e0df47b..c2c4945 100644 --- a/client.js +++ b/client.js @@ -1,59 +1,22 @@ -const WebSocket = require('ws'); +// Example: client.js const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; -const CDPValueType = root.ICD.Protobuf.CDPValueType; class Client { - /** - * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000") - * @param {boolean} [autoReconnect=true] - Automatically reconnect if the connection is lost - */ - constructor(endpoint, autoReconnect = true) { - // If endpoint does not start with "ws://" or "wss://", prepend "ws://" - let url = endpoint; - if (!/^wss?:\/\//.test(url)) { - url = `ws://${url}`; - } - + constructor(host, port = 17000, autoReconnect = true) { this.reqId = -1; this.autoReconnect = autoReconnect; - - // Time synchronization is enabled by default. - this.enableTimeSync = true; - this.isOpen = false; this.queuedRequests = {}; this.storedPromises = {}; this.nameToId = {}; this.idToName = {}; - - // New mapping for signal types. - this.nameToType = {}; - - // Time-diff related this.timeDiff = 0; this.timeReceived = null; this.lastTimeRequest = Date.now() / 1000; this.haveSentQueuedReq = false; this.roundTripTimes = {}; - - // Create the WebSocket connection - this.ws = this._connect(url); - } - - /** - * Enable or disable time synchronization. - * @param {boolean} enable - If true, time sync is enabled; if false, time sync is disabled. - */ - setEnableTimeSync(enable) { - this.enableTimeSync = enable; - if (!enable) { - // Cancel any pending time sync requests so they won’t update timeDiff later. - for (const key in this.storedPromises) { - this.storedPromises[key].reject(new Error("Time sync disabled")); - } - this.storedPromises = {}; - } + this.ws = this._connect(`ws://${host}:${port}`); } _connect(url) { @@ -69,9 +32,7 @@ class Client { _onOpen(ws) { this.isOpen = true; - if (this.enableTimeSync) { - this._updateTimeDiff(); - } + this._updateTimeDiff(); this.lastTimeRequest = Date.now() / 1000; } @@ -172,42 +133,9 @@ class Client { return promise; } - /** - * Request events based on the provided query parameters. - * @param {Object} query - An object matching the EventQuery schema. - * For example: - * { - * timeRangeBegin: 1620000000, - * timeRangeEnd: 1620003600, - * codeMask: 0, - * limit: 100, - * offset: 0, - * flags: 1 // Numeric flags as defined in your protocol - * } - * @returns {Promise} Resolves with an array of events. - */ - requestEvents(query) { - this._timeRequest(); - const requestId = this._getRequestId(); - if (!this.isOpen) { - this.queuedRequests[requestId] = { type: "events", query: query }; - } else { - this._sendEventsRequest(requestId, query); - } - return new Promise((resolve, reject) => { - this.storedPromises[requestId] = { resolve, reject }; - }); - } - - _sendEventsRequest(requestId, query) { - const container = Container.create(); - container.messageType = Container.Type.eEventsRequest; - container.eventsRequest = { requestId: requestId, query: query }; - const buffer = Container.encode(container).finish(); - this.ws.send(buffer); - } _handleMessage(ws, message) { + // console.log("Raw data:", message); const data = Container.decode(new Uint8Array(message)); this._parseMessage(data); } @@ -221,7 +149,6 @@ class Client { reject(new Error(data.error.errorMessage)); } break; - case Container.Type.eTimeResponse: this.timeReceived = Date.now() / 1000; if (this.storedPromises[data.timeResponse.requestId]) { @@ -230,8 +157,7 @@ class Client { resolve(data.timeResponse.timestamp); } break; - - case Container.Type.eSignalInfoResponse: { + case Container.Type.eSignalInfoResponse: const nodes = []; this.nameToId = {}; this.idToName = {}; @@ -240,9 +166,6 @@ class Client { name: data.signalInfoResponse.name[i], routing: data.signalInfoResponse.path[i] }; - if (data.signalInfoResponse.tagMap && data.signalInfoResponse.tagMap[i]) { - node.tags = this._convertTagMap(data.signalInfoResponse.tagMap[i]); - } this.nameToId[data.signalInfoResponse.name[i]] = data.signalInfoResponse.id[i]; this.idToName[data.signalInfoResponse.id[i]] = data.signalInfoResponse.name[i]; nodes.push(node); @@ -253,33 +176,26 @@ class Client { resolve(nodes); } break; - } - case Container.Type.eCriterionLimitsResponse: - if (this.enableTimeSync) { - data.criterionLimitsResponse.criterionMin += this.timeDiff; - data.criterionLimitsResponse.criterionMax += this.timeDiff; - } - { - const limits = { - startS: data.criterionLimitsResponse.criterionMin, - endS: data.criterionLimitsResponse.criterionMax - }; - if (this.storedPromises[data.criterionLimitsResponse.requestId]) { - const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; - delete this.storedPromises[data.criterionLimitsResponse.requestId]; - resolve(limits); - } + data.criterionLimitsResponse.criterionMin += this.timeDiff; + data.criterionLimitsResponse.criterionMax += this.timeDiff; + const limits = { + start_s: data.criterionLimitsResponse.criterionMin, + end_s: data.criterionLimitsResponse.criterionMax + }; + if (this.storedPromises[data.criterionLimitsResponse.requestId]) { + const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; + delete this.storedPromises[data.criterionLimitsResponse.requestId]; + resolve(limits); } break; - - case Container.Type.eVersionResponse: { + case Container.Type.eVersionResponse: const version = parseFloat(data.versionResponse.version); if (version < 3.0) { if (this.storedPromises[data.versionResponse.requestId]) { const { reject } = this.storedPromises[data.versionResponse.requestId]; delete this.storedPromises[data.versionResponse.requestId]; - reject(new Error("CDP version needs to be 4.3 or newer.")); + reject(new Error("CDP version needs to be 3.0 or newer.")); } } else { if (this.storedPromises[data.versionResponse.requestId]) { @@ -289,15 +205,11 @@ class Client { } } break; - } - - case Container.Type.eSignalDataResponse: { + case Container.Type.eSignalDataResponse: let dataPoints = []; let index = 0; for (const row of data.signalDataResponse.row) { - if (this.enableTimeSync) { - data.signalDataResponse.criterion[index] += this.timeDiff; - } + data.signalDataResponse.criterion[index] += this.timeDiff; let signalNames = []; for (const signalId of row.signalId) { signalNames.push(this.idToName[signalId]); @@ -320,79 +232,37 @@ class Client { resolve(dataPoints); } break; - } - - case Container.Type.eEventsResponse: { - if (this.storedPromises[data.eventsResponse.requestId]) { - const { resolve } = this.storedPromises[data.eventsResponse.requestId]; - delete this.storedPromises[data.eventsResponse.requestId]; - resolve(data.eventsResponse.events); - } - break; - } - default: console.error("Unknown message type", data.messageType); } } - _convertTagMap(tagMapObj) { - const result = {}; - if (!tagMapObj || !tagMapObj.tags) { - return result; - } - for (const [tagKey, tagInfo] of Object.entries(tagMapObj.tags)) { - result[tagKey] = { - value: tagInfo.value, - source: tagInfo.source - }; - } - return result; - } - _createValue(signalNames, minValues, maxValues, lastValues) { const value = {}; for (let i = 0; i < signalNames.length; i++) { - const signalType = this.nameToType[signalNames[i]] || CDPValueType.eDOUBLE; value[signalNames[i]] = { - min: this._valueFromVariant(minValues[i], signalType), - max: this._valueFromVariant(maxValues[i], signalType), - last: this._valueFromVariant(lastValues[i], signalType) + min: this._valueFromVariant(minValues[i]), + max: this._valueFromVariant(maxValues[i]), + last: this._valueFromVariant(lastValues[i]) }; } return value; } - _valueFromVariant(variant, type) { - if (!variant) return null; - switch (type) { - case CDPValueType.eDOUBLE: - return variant.dValue; - case CDPValueType.eFLOAT: - return variant.fValue; - case CDPValueType.eUINT64: - return variant.ui64Value; - case CDPValueType.eINT64: - return variant.i64Value; - case CDPValueType.eUINT: - return variant.uiValue; - case CDPValueType.eINT: - return variant.iValue; - case CDPValueType.eUSHORT: - return variant.usValue; - case CDPValueType.eSHORT: - return variant.sValue; - case CDPValueType.eUCHAR: - return variant.ucValue; - case CDPValueType.eCHAR: - return variant.cValue; - case CDPValueType.eBOOL: - return variant.bValue; - case CDPValueType.eSTRING: - return variant.strValue; - default: - return null; - } + _valueFromVariant(value) { + if (value.dValue !== undefined) return value.dValue; + if (value.fValue !== undefined) return value.fValue; + if (value.ui64Value !== undefined) return value.ui64Value; + if (value.i64Value !== undefined) return value.i64Value; + if (value.uiValue !== undefined) return value.uiValue; + if (value.iValue !== undefined) return value.iValue; + if (value.usValue !== undefined) return value.usValue; + if (value.sValue !== undefined) return value.sValue; + if (value.ucValue !== undefined) return value.ucValue; + if (value.cValue !== undefined) return value.cValue; + if (value.bValue !== undefined) return value.bValue; + if (value.strValue !== undefined) return value.strValue; + return null; } _sendQueuedRequests() { @@ -406,8 +276,6 @@ class Client { this._reqDataPoints(req[1], req[2], req[3], req[4], requestId); } else if (req === "api_version") { this._sendApiVersionRequest(requestId); - } else if (req && req.type === "events") { - this._sendEventsRequest(requestId, req.query); } } this.queuedRequests = {}; @@ -419,14 +287,12 @@ class Client { } _timeRequest() { - if (!this.enableTimeSync) return; if ((Date.now() / 1000) > this.lastTimeRequest + 10) { this._updateTimeDiff(); } } _updateTimeDiff() { - if (!this.enableTimeSync) return; const requestId = this._getRequestId(); const timeSent = Date.now() / 1000; this._requestTime(requestId) @@ -439,21 +305,16 @@ class Client { } _requestTime(reqId) { - if (!this.enableTimeSync) { - return Promise.resolve(0); - } const requestId = reqId; this.lastTimeRequest = Date.now() / 1000; - // Always send the time request. this._sendTimeRequest(requestId); - // Create the promise and store the callbacks. - const promise = new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); - return promise; } - + _sendTimeRequest(requestId) { + // Create a Container message for time request const container = Container.create(); container.messageType = Container.Type.eTimeRequest; container.timeRequest = { requestId: requestId }; @@ -462,7 +323,6 @@ class Client { } _setTimeDiff(timestamp, timeSent) { - if (!this.enableTimeSync) return; const clientTime = this.timeReceived; const roundTripTime = clientTime - timeSent; const serverTime = (timestamp / 1e9) + roundTripTime / 2; @@ -548,8 +408,8 @@ class Client { requestId: requestId, signalId: nodeIds, numOfDatapoints: noOfDataPoints, - criterionMin: this.enableTimeSync ? (startS - this.timeDiff) : startS, - criterionMax: this.enableTimeSync ? (endS - this.timeDiff) : endS + criterionMin: startS - this.timeDiff, + criterionMax: endS - this.timeDiff }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); diff --git a/event.js b/event.js deleted file mode 100644 index 9bc1602..0000000 --- a/event.js +++ /dev/null @@ -1,117 +0,0 @@ -// event.js -global.WebSocket = require('ws'); -const Client = require('./client'); - -/** - * Recursively normalizes an object/value. - * If the value is a string, it trims whitespace. - * If it's an object (or array), it normalizes each property. - * This helps ensure that logically identical values produce the same string. - * - * @param {*} val - The value to normalize. - * @returns {*} - The normalized value. - */ -function normalizeValue(val) { - if (typeof val === 'string') { - return val.trim(); - } else if (typeof val === 'object' && val !== null) { - if (Array.isArray(val)) { - return val.map(normalizeValue); - } else { - const keys = Object.keys(val).sort(); - const normalized = {}; - for (const key of keys) { - normalized[key.trim()] = normalizeValue(val[key]); - } - return normalized; - } - } - return val; -} - -/** - * Recursively returns a canonical JSON string for the given object. - * Keys are sorted so that two objects with the same properties produce the same string. - * - * @param {*} obj - The object/value to canonicalize. - * @returns {string} - The canonical JSON string. - */ -function canonicalize(obj) { - if (typeof obj !== 'object' || obj === null) { - return JSON.stringify(obj); - } - if (Array.isArray(obj)) { - return '[' + obj.map(canonicalize).join(',') + ']'; - } - const keys = Object.keys(obj).sort(); - const result = keys - .map(key => JSON.stringify(key) + ':' + canonicalize(obj[key])) - .join(','); - return '{' + result + '}'; -} - -(async function main() { - const client = new Client('ws://127.0.0.1:17000', false); - try { - // Example query: adjust the time range, etc., as needed: - const query = { - timeRangeBegin: 1742540000, - timeRangeEnd: 1742550000, - codeMask: 0xFFFFFFFF, - limit: 100, - offset: 0, - flags: 1 // 'NewestFirst' from your enum - }; - - const events = await client.requestEvents(query); - - // De-duplicate events using a composite key built from normalized fields. - // We'll canonicalize e.data to handle reordered JSON keys. - const seen = new Set(); - const uniqueEvents = []; - - for (const e of events) { - const tsPart = (typeof e.timestampSec !== 'undefined' && e.timestampSec !== null) - ? String(e.timestampSec) - : ''; - - const codePart = (typeof e.code !== 'undefined' && e.code !== null) - ? String(e.code) - : ''; - - const senderPart = (typeof e.sender !== 'undefined' && e.sender !== null) - ? String(e.sender) - : ''; - - // Canonicalize the data so that JSON field order does not matter - const dataPart = e.data - ? canonicalize(normalizeValue(e.data)) - : ''; - - const compositeKey = `${tsPart}-${codePart}-${senderPart}-${dataPart}`; - - if (!seen.has(compositeKey)) { - seen.add(compositeKey); - uniqueEvents.push(e); - } - } - - // Print the unique events - if (uniqueEvents.length === 0) { - console.log("No events found."); - } else { - for (const evt of uniqueEvents) { - console.log(`Timestamp: ${evt.timestampSec}`); - console.log(`Code: ${evt.code}`); - console.log(`Sender: ${evt.sender}`); - console.log(`Data: ${JSON.stringify(evt.data)}`); - console.log('--------------------'); - } - } - } catch (err) { - console.error("Error retrieving events:", err); - } finally { - client.disconnect(); - process.exit(0); - } -})(); diff --git a/index.js b/index.js index e76f24f..28d1487 100644 --- a/index.js +++ b/index.js @@ -1,113 +1,56 @@ // index.js -// Example demonstration including an events query for a specific time range (UTC 9:40) - global.WebSocket = require('ws'); const Client = require('./client'); -// Print the node information (name, routing, and tags) +const client = new Client('127.0.0.1', 17000, false); + +// Print the node information (name and routing) function printLoggedNodes() { client.requestLoggedNodes() .then(nodes => { console.log("Connected nodes:"); nodes.forEach(node => { console.log(`Name: ${node.name}, Routing: ${node.routing}`); - if (node.tags) { - console.log("Tags:"); - Object.entries(node.tags).forEach(([key, tagInfo]) => { - console.log(` ${key}: value=${tagInfo.value}, source=${tagInfo.source}`); - }); - } - console.log('--------------------'); }); + console.log('--------------------'); }) .catch(err => { console.error("Error retrieving logged nodes:", err); }); } -// Print data points for the "Output" node. -async function printDataPoints() { - try { - const limits = await client.requestLogLimits(); - console.log("Log limits received:", limits); - - const dataPoints = await client.requestDataPoints(["Output"], limits.startS, limits.endS, 25); - console.log("Data Points retrieved:"); - dataPoints.forEach(point => { - console.log(`Timestamp: ${point.timestamp}`); - if (point.value && point.value["Output"]) { - const val = point.value["Output"]; - console.log(`Min: ${val.min}`); - console.log(`Max: ${val.max}`); - console.log(`Last: ${val.last}`); - } else { - console.log("No data for 'Output':", point); - } - console.log('--------------------'); - }); - } catch (err) { - console.error("Error retrieving data points:", err); - } -} - -// Print events retrieved within a time range corresponding to UTC 9:40. -// In this example, we use a 5-minute window starting at UTC 9:40. -async function printEvents() { - try { - // Specify the target time for events in UTC. - // Adjust the date as needed; here we assume a specific date. - const targetDate = new Date("2025-03-21T09:38:00Z"); - const targetTime = targetDate.getTime() / 1000; - // Define a window of 5 minutes (300 seconds) - const timeWindow = 5 * 60; - - const eventQuery = { - timeRangeBegin: targetTime, - timeRangeEnd: targetTime + timeWindow, - codeMask: 0, - limit: 100, - offset: 0, - flags: 0, - // Optionally, add senderConditions or dataConditions if desired. - }; - - const events = await client.requestEvents(eventQuery); - console.log("Events retrieved:"); - if (!events || events.length === 0) { - console.log("No events found with the current query."); +function onDataPointsReceived(dataPoints) { + dataPoints.forEach(point => { + console.log(`Timestamp: ${point.timestamp}`); + if (point.value && point.value["Output"]) { + const val = point.value["Output"]; + console.log(`Min: ${val.min}`); + console.log(`Max: ${val.max}`); + console.log(`Last: ${val.last}`); } else { - events.forEach(evt => { - console.log(`Timestamp: ${evt.timestampSec}`); - console.log(` Code: ${evt.data && evt.data.Code ? evt.data.Code : "N/A"}`); - console.log(` Source: ${evt.data && evt.data.Source ? evt.data.Source : "N/A"}`); - console.log(` Text: ${evt.data && evt.data.Text ? evt.data.Text : "N/A"}`); - console.log('--------------------'); - }); + console.log("No data for 'Output':", point); } - } catch (err) { - console.error("Error retrieving events:", err); - } -} - -async function main() { - try { - printLoggedNodes(); - await printDataPoints(); - await printEvents(); - } catch (error) { - console.error("Error in main:", error); - } finally { + console.log('--------------------'); + }); + // When finished processing, disconnect and exit + setTimeout(() => { client.disconnect(); process.exit(0); - } + }, 5000); +} + +function requestDataPoints(limits) { + console.log("Log limits received:", limits); + return client.requestDataPoints(["Output"], limits.start_s, limits.end_s, 25); } -// Create a new client instance. (In this example, autoReconnect is disabled.) -const client = new Client('ws://127.0.0.1:17000', false); +function onError(error) { + console.error("Error:", error); +} -// Instead of overriding ws.onopen (which may cancel internal logic), -// add an event listener so that _onOpen is still called. -client.ws.addEventListener("open", () => { - console.log("WebSocket connection established."); - main(); -}); +// Kick off both the nodes request and data points request: +printLoggedNodes(); +client.requestLogLimits() + .then(requestDataPoints) + .then(onDataPointsReceived) + .catch(onError); diff --git a/package-lock.json b/package-lock.json index cdbd936..edf340a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "JavascriptCDPLoggerClient", + "name": "cdplogger-js", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test/client.test.js b/test/client.test.js index b53da15..98024cb 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -1,21 +1,22 @@ -/*global WebSocket*/ +// client.test.js global.WebSocket = require('ws'); const Client = require('../client'); const fakeData = require('./fakeData'); + describe('ClientTester', () => { let client; beforeEach(() => { - // Override _connect to return a fake ws object that doesn't try to connect. - Client.prototype._connect = function(url) { - return { - _url: url, - close: jest.fn(), - send: jest.fn() - }; + // Override _connect to return a fake ws object that doesn't try to connect. + Client.prototype._connect = function(url) { + return { + _url: url, + close: jest.fn(), + // You can add any other dummy methods as needed. }; - // Create a new client instance using two parameters: endpoint and autoReconnect. - client = new Client('127.0.0.1:17000', true); + }; + // Create a new client instance. + client = new Client('127.0.0.1', 17000, true); // Adjust the client’s lastTimeRequest so that a new time request will be triggered. client.lastTimeRequest = Date.now() / 1000 - 11; // Prepopulate the lookup maps. @@ -32,12 +33,15 @@ describe('ClientTester', () => { }); test('test_run_event_loop', () => { + // In our JS version we might not have a runEventLoop, + // so we simulate it by adding a dummy method. client.runEventLoop = jest.fn(); client.runEventLoop(); expect(client.runEventLoop).toHaveBeenCalled(); }); test('test_disconnect', () => { + // Replace ws and _cleanupQueuedRequests with mocks. client.ws = { close: jest.fn() }; client._cleanupQueuedRequests = jest.fn(); client.disconnect(); @@ -91,6 +95,7 @@ describe('ClientTester', () => { done(); }); }); + test('test_version_request', done => { client.isOpen = true; @@ -128,8 +133,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.startS).toBeCloseTo(1529497537.61); - expect(limits.endS).toBeCloseTo(1531389483.02); + expect(limits.start_s).toBeCloseTo(1529497537.61); + expect(limits.end_s).toBeCloseTo(1531389483.02); done(); }) .catch(done.fail); @@ -144,8 +149,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.startS).toBeCloseTo(1529497537.61 + 10); - expect(limits.endS).toBeCloseTo(1531389483.02 + 10); + expect(limits.start_s).toBeCloseTo(1529497537.61 + 10); + expect(limits.end_s).toBeCloseTo(1531389483.02 + 10); done(); }) .catch(done.fail); @@ -189,36 +194,14 @@ describe('ClientTester', () => { client.isOpen = true; client._sendTimeRequest = jest.fn(); client._sendLoggedNodesRequest = jest.fn(); - - // Remove "Output" so that the lookup fails. - delete client.nameToId["Output"]; - for (const id in client.idToName) { - if (client.idToName[id] === "Output") { - delete client.idToName[id]; - } - } - - client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) + client.requestDataPoints(["Outputt", "CPULoad"], 1531313250.0, 1531461231.0, 500) .catch(error => { expect(error).toBeInstanceOf(Error); - expect(error.message).toMatch(/Output/); + expect(error.message).toMatch(/Outputt/); done(); }); - // Simulate a logged nodes response that does NOT include "Output". - const response = { - messageType: fakeData.Container.Type.eSignalInfoResponse, - signalInfoResponse: { - requestId: 2, - name: ["CPULoad", "MemUsed", "CDPSignal"], - id: [1, 2, 3], - type: [], - path: [ - "loggerApp.CPULoad", - "loggerApp.MemUsed", - "loggerApp.CDPSignal" - ] - } - }; + // Simulate a logged nodes response that does not include "Outputt" + const response = fakeData.createLoggedNodesResponse(2); client._parseMessage(response); }); @@ -235,32 +218,4 @@ describe('ClientTester', () => { const response = fakeData.createErrorResponse(); client._parseMessage(response); }); - - // Added test for events - test('test_events_request', done => { - client.isOpen = true; - client._sendTimeRequest = jest.fn(); - client._sendEventsRequest = jest.fn(); - client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) - .then(events => { - expect(events).toBeDefined(); - expect(events.length).toBe(1); - expect(events[0].sender).toBe("TestSender"); - expect(events[0].data.key).toBe("value"); - expect(events[0].timestampSec).toBeCloseTo(1500); - done(); - }) - .catch(done.fail); - // Simulate an events response. - const response = { - messageType: fakeData.Container.Type.eEventsResponse, - eventsResponse: { - requestId: 1, - events: [ - { sender: "TestSender", data: { key: "value" }, timestampSec: 1500, id: 42, code: 100, status: 1, logstampSec: 1500 } - ] - } - }; - client._parseMessage(response); - }); }); diff --git a/test/testTimeSync.js b/test/testTimeSync.js deleted file mode 100644 index d587a3b..0000000 --- a/test/testTimeSync.js +++ /dev/null @@ -1,134 +0,0 @@ -// testTimeSync.js -const Client = require('../client'); -const fakeData = require('./fakeData'); - -// Override WebSocket with a dummy that provides a send() method. -global.WebSocket = class { - constructor(url) { - this._url = url; - } - send(data) { - // For our test we simply ignore the sent data. - } -}; - -/** - * Helper function to run an API method with time sync enabled and then disabled. - * It forces an update (by setting lastTimeRequest to an old value) before each call. - * The simulateResponse callback simulates the corresponding response by calling _parseMessage. - */ -async function runThrough(methodName, callFunc, simulateResponse) { - console.log(`\n=== Running ${methodName} with time sync ENABLED ===`); - // Force a time update by setting lastTimeRequest to an old value. - client.lastTimeRequest = Date.now() / 1000 - 20; - // Call the API method. - callFunc(); - // Simulate a response if needed. - if (simulateResponse) simulateResponse(); - // Wait longer for the time sync update to complete. - await new Promise(resolve => setTimeout(resolve, 300)); - console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec`); - - // Now disable time sync. - // Clear any pending time requests so they don't update timeDiff later. - client.storedPromises = {}; - client.setEnableTimeSync(false); - console.log(`\n=== Running ${methodName} with time sync DISABLED ===`); - const previousTimeDiff = client.timeDiff; - client.lastTimeRequest = Date.now() / 1000 - 20; - callFunc(); - // When time sync is disabled, do NOT simulate a response. - await new Promise(resolve => setTimeout(resolve, 300)); - console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)`); - // Re-enable time sync for subsequent tests. - client.setEnableTimeSync(true); -} - -async function runTest() { - // Create a new client instance with only endpoint and autoReconnect. - client = new Client('127.0.0.1:17000', true); - - // Override _sendTimeRequest to simulate an immediate server time response with variable delay. - client._sendTimeRequest = function (requestId) { - console.log(`_sendTimeRequest called with requestId: ${requestId}`); - // Simulate variable network delay (e.g., 50 to 300ms) - const delay = Math.floor(Math.random() * 250) + 50; - setTimeout(() => { - // Simulate a server timestamp in nanoseconds. - const simulatedTimestamp = Date.now() * 1e6; - console.log(`Simulated timestamp for request ${requestId} after ${delay}ms: ${simulatedTimestamp}`); - if (client.storedPromises[requestId]) { - client.storedPromises[requestId].resolve(simulatedTimestamp); - delete client.storedPromises[requestId]; - } - }, delay); - }; - - // Override _updateTimeDiff to perform one measurement and log its details. - client._updateTimeDiff = function () { - if (!this.enableTimeSync) return; - const requestId = this._getRequestId(); - const timeSent = Date.now() / 1000; - // Call _requestTime (which now calls our overridden _sendTimeRequest). - this._requestTime(requestId) - .then(timestamp => { - // Simulate a time response arriving. - this.timeReceived = Date.now() / 1000; - const roundTripTime = this.timeReceived - timeSent; - const serverTime = (timestamp / 1e9) + roundTripTime / 2; - const computedTimeDiff = this.timeReceived - serverTime; - this.timeDiff = computedTimeDiff; - console.log("=== Time Sync Measurement ==="); - console.log(`Time Sent: ${timeSent.toFixed(6)} sec`); - console.log(`Time Received: ${this.timeReceived.toFixed(6)} sec`); - console.log(`Round Trip Time: ${roundTripTime.toFixed(6)} sec`); - console.log(`Simulated Server Time: ${serverTime.toFixed(6)} sec`); - console.log(`Computed timeDiff: ${computedTimeDiff.toFixed(6)} sec`); - }) - .catch(err => console.error(err)); - }; - - // Use the production _requestTime (which already checks enableTimeSync). - // No override needed here. - - // Now run through several public API methods. - await runThrough( - "requestApiVersion", - () => client.requestApiVersion(), - () => { - // Simulate a valid API version response. - const response = fakeData.createApiVersionResponse(); - client._parseMessage(response); - } - ); - - await runThrough( - "requestLogLimits", - () => client.requestLogLimits(), - () => { - const response = fakeData.createLogLimitsResponse(); - client._parseMessage(response); - } - ); - - await runThrough( - "requestLoggedNodes", - () => client.requestLoggedNodes(), - () => { - const response = fakeData.createLoggedNodesResponse(1); - client._parseMessage(response); - } - ); - - await runThrough( - "requestDataPoints", - () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500), - () => { - const response = fakeData.createDataPointResponse(); - client._parseMessage(response); - } - ); -} - -let client; -runTest().catch(console.error); From 9d1035593ccbf56e775042e458f894aa86bdc1f1 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Sun, 23 Mar 2025 15:42:33 +0200 Subject: [PATCH 06/37] Added support for Events and a test --- .gitignore | 3 +- README.md | 14 ++- client.js | 224 +++++++++++++++++++++++++++++++++++-------- event.js | 117 ++++++++++++++++++++++ index.js | 121 ++++++++++++++++------- package-lock.json | 2 +- test/client.test.js | 91 +++++++++++++----- test/testTimeSync.js | 134 ++++++++++++++++++++++++++ 8 files changed, 605 insertions(+), 101 deletions(-) create mode 100644 event.js create mode 100644 test/testTimeSync.js diff --git a/.gitignore b/.gitignore index 9e99588..909f568 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ -protos/ \ No newline at end of file +protos/ +helpers/ \ No newline at end of file diff --git a/README.md b/README.md index 933c90e..ad458c1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # CDPLogger Client for JavaScript -A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. +A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. +For more information about CDP Studio see https://cdpstudio.com/. ## Installation @@ -13,20 +14,29 @@ npm install ## Running Tests + To run the automatic tests with fake data, execute: ```bash npm test ``` + ## Usage + The index.js file contains a simple logger built for the CDP Studio example case. 1. Set up and run the Logger in CDP Studio. (Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) +https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html 2. Run the index.js file from the command line: ```bash node index.js -``` \ No newline at end of file +``` + + +## Contact + +Email: support@cdptech.com \ No newline at end of file diff --git a/client.js b/client.js index c2c4945..e0df47b 100644 --- a/client.js +++ b/client.js @@ -1,22 +1,59 @@ -// Example: client.js +const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; +const CDPValueType = root.ICD.Protobuf.CDPValueType; class Client { - constructor(host, port = 17000, autoReconnect = true) { + /** + * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000") + * @param {boolean} [autoReconnect=true] - Automatically reconnect if the connection is lost + */ + constructor(endpoint, autoReconnect = true) { + // If endpoint does not start with "ws://" or "wss://", prepend "ws://" + let url = endpoint; + if (!/^wss?:\/\//.test(url)) { + url = `ws://${url}`; + } + this.reqId = -1; this.autoReconnect = autoReconnect; + + // Time synchronization is enabled by default. + this.enableTimeSync = true; + this.isOpen = false; this.queuedRequests = {}; this.storedPromises = {}; this.nameToId = {}; this.idToName = {}; + + // New mapping for signal types. + this.nameToType = {}; + + // Time-diff related this.timeDiff = 0; this.timeReceived = null; this.lastTimeRequest = Date.now() / 1000; this.haveSentQueuedReq = false; this.roundTripTimes = {}; - this.ws = this._connect(`ws://${host}:${port}`); + + // Create the WebSocket connection + this.ws = this._connect(url); + } + + /** + * Enable or disable time synchronization. + * @param {boolean} enable - If true, time sync is enabled; if false, time sync is disabled. + */ + setEnableTimeSync(enable) { + this.enableTimeSync = enable; + if (!enable) { + // Cancel any pending time sync requests so they won’t update timeDiff later. + for (const key in this.storedPromises) { + this.storedPromises[key].reject(new Error("Time sync disabled")); + } + this.storedPromises = {}; + } } _connect(url) { @@ -32,7 +69,9 @@ class Client { _onOpen(ws) { this.isOpen = true; - this._updateTimeDiff(); + if (this.enableTimeSync) { + this._updateTimeDiff(); + } this.lastTimeRequest = Date.now() / 1000; } @@ -133,9 +172,42 @@ class Client { return promise; } + /** + * Request events based on the provided query parameters. + * @param {Object} query - An object matching the EventQuery schema. + * For example: + * { + * timeRangeBegin: 1620000000, + * timeRangeEnd: 1620003600, + * codeMask: 0, + * limit: 100, + * offset: 0, + * flags: 1 // Numeric flags as defined in your protocol + * } + * @returns {Promise} Resolves with an array of events. + */ + requestEvents(query) { + this._timeRequest(); + const requestId = this._getRequestId(); + if (!this.isOpen) { + this.queuedRequests[requestId] = { type: "events", query: query }; + } else { + this._sendEventsRequest(requestId, query); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }); + } + + _sendEventsRequest(requestId, query) { + const container = Container.create(); + container.messageType = Container.Type.eEventsRequest; + container.eventsRequest = { requestId: requestId, query: query }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } _handleMessage(ws, message) { - // console.log("Raw data:", message); const data = Container.decode(new Uint8Array(message)); this._parseMessage(data); } @@ -149,6 +221,7 @@ class Client { reject(new Error(data.error.errorMessage)); } break; + case Container.Type.eTimeResponse: this.timeReceived = Date.now() / 1000; if (this.storedPromises[data.timeResponse.requestId]) { @@ -157,7 +230,8 @@ class Client { resolve(data.timeResponse.timestamp); } break; - case Container.Type.eSignalInfoResponse: + + case Container.Type.eSignalInfoResponse: { const nodes = []; this.nameToId = {}; this.idToName = {}; @@ -166,6 +240,9 @@ class Client { name: data.signalInfoResponse.name[i], routing: data.signalInfoResponse.path[i] }; + if (data.signalInfoResponse.tagMap && data.signalInfoResponse.tagMap[i]) { + node.tags = this._convertTagMap(data.signalInfoResponse.tagMap[i]); + } this.nameToId[data.signalInfoResponse.name[i]] = data.signalInfoResponse.id[i]; this.idToName[data.signalInfoResponse.id[i]] = data.signalInfoResponse.name[i]; nodes.push(node); @@ -176,26 +253,33 @@ class Client { resolve(nodes); } break; + } + case Container.Type.eCriterionLimitsResponse: - data.criterionLimitsResponse.criterionMin += this.timeDiff; - data.criterionLimitsResponse.criterionMax += this.timeDiff; - const limits = { - start_s: data.criterionLimitsResponse.criterionMin, - end_s: data.criterionLimitsResponse.criterionMax - }; - if (this.storedPromises[data.criterionLimitsResponse.requestId]) { - const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; - delete this.storedPromises[data.criterionLimitsResponse.requestId]; - resolve(limits); + if (this.enableTimeSync) { + data.criterionLimitsResponse.criterionMin += this.timeDiff; + data.criterionLimitsResponse.criterionMax += this.timeDiff; + } + { + const limits = { + startS: data.criterionLimitsResponse.criterionMin, + endS: data.criterionLimitsResponse.criterionMax + }; + if (this.storedPromises[data.criterionLimitsResponse.requestId]) { + const { resolve } = this.storedPromises[data.criterionLimitsResponse.requestId]; + delete this.storedPromises[data.criterionLimitsResponse.requestId]; + resolve(limits); + } } break; - case Container.Type.eVersionResponse: + + case Container.Type.eVersionResponse: { const version = parseFloat(data.versionResponse.version); if (version < 3.0) { if (this.storedPromises[data.versionResponse.requestId]) { const { reject } = this.storedPromises[data.versionResponse.requestId]; delete this.storedPromises[data.versionResponse.requestId]; - reject(new Error("CDP version needs to be 3.0 or newer.")); + reject(new Error("CDP version needs to be 4.3 or newer.")); } } else { if (this.storedPromises[data.versionResponse.requestId]) { @@ -205,11 +289,15 @@ class Client { } } break; - case Container.Type.eSignalDataResponse: + } + + case Container.Type.eSignalDataResponse: { let dataPoints = []; let index = 0; for (const row of data.signalDataResponse.row) { - data.signalDataResponse.criterion[index] += this.timeDiff; + if (this.enableTimeSync) { + data.signalDataResponse.criterion[index] += this.timeDiff; + } let signalNames = []; for (const signalId of row.signalId) { signalNames.push(this.idToName[signalId]); @@ -232,37 +320,79 @@ class Client { resolve(dataPoints); } break; + } + + case Container.Type.eEventsResponse: { + if (this.storedPromises[data.eventsResponse.requestId]) { + const { resolve } = this.storedPromises[data.eventsResponse.requestId]; + delete this.storedPromises[data.eventsResponse.requestId]; + resolve(data.eventsResponse.events); + } + break; + } + default: console.error("Unknown message type", data.messageType); } } + _convertTagMap(tagMapObj) { + const result = {}; + if (!tagMapObj || !tagMapObj.tags) { + return result; + } + for (const [tagKey, tagInfo] of Object.entries(tagMapObj.tags)) { + result[tagKey] = { + value: tagInfo.value, + source: tagInfo.source + }; + } + return result; + } + _createValue(signalNames, minValues, maxValues, lastValues) { const value = {}; for (let i = 0; i < signalNames.length; i++) { + const signalType = this.nameToType[signalNames[i]] || CDPValueType.eDOUBLE; value[signalNames[i]] = { - min: this._valueFromVariant(minValues[i]), - max: this._valueFromVariant(maxValues[i]), - last: this._valueFromVariant(lastValues[i]) + min: this._valueFromVariant(minValues[i], signalType), + max: this._valueFromVariant(maxValues[i], signalType), + last: this._valueFromVariant(lastValues[i], signalType) }; } return value; } - _valueFromVariant(value) { - if (value.dValue !== undefined) return value.dValue; - if (value.fValue !== undefined) return value.fValue; - if (value.ui64Value !== undefined) return value.ui64Value; - if (value.i64Value !== undefined) return value.i64Value; - if (value.uiValue !== undefined) return value.uiValue; - if (value.iValue !== undefined) return value.iValue; - if (value.usValue !== undefined) return value.usValue; - if (value.sValue !== undefined) return value.sValue; - if (value.ucValue !== undefined) return value.ucValue; - if (value.cValue !== undefined) return value.cValue; - if (value.bValue !== undefined) return value.bValue; - if (value.strValue !== undefined) return value.strValue; - return null; + _valueFromVariant(variant, type) { + if (!variant) return null; + switch (type) { + case CDPValueType.eDOUBLE: + return variant.dValue; + case CDPValueType.eFLOAT: + return variant.fValue; + case CDPValueType.eUINT64: + return variant.ui64Value; + case CDPValueType.eINT64: + return variant.i64Value; + case CDPValueType.eUINT: + return variant.uiValue; + case CDPValueType.eINT: + return variant.iValue; + case CDPValueType.eUSHORT: + return variant.usValue; + case CDPValueType.eSHORT: + return variant.sValue; + case CDPValueType.eUCHAR: + return variant.ucValue; + case CDPValueType.eCHAR: + return variant.cValue; + case CDPValueType.eBOOL: + return variant.bValue; + case CDPValueType.eSTRING: + return variant.strValue; + default: + return null; + } } _sendQueuedRequests() { @@ -276,6 +406,8 @@ class Client { this._reqDataPoints(req[1], req[2], req[3], req[4], requestId); } else if (req === "api_version") { this._sendApiVersionRequest(requestId); + } else if (req && req.type === "events") { + this._sendEventsRequest(requestId, req.query); } } this.queuedRequests = {}; @@ -287,12 +419,14 @@ class Client { } _timeRequest() { + if (!this.enableTimeSync) return; if ((Date.now() / 1000) > this.lastTimeRequest + 10) { this._updateTimeDiff(); } } _updateTimeDiff() { + if (!this.enableTimeSync) return; const requestId = this._getRequestId(); const timeSent = Date.now() / 1000; this._requestTime(requestId) @@ -305,16 +439,21 @@ class Client { } _requestTime(reqId) { + if (!this.enableTimeSync) { + return Promise.resolve(0); + } const requestId = reqId; this.lastTimeRequest = Date.now() / 1000; + // Always send the time request. this._sendTimeRequest(requestId); - return new Promise((resolve, reject) => { + // Create the promise and store the callbacks. + const promise = new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); + return promise; } - + _sendTimeRequest(requestId) { - // Create a Container message for time request const container = Container.create(); container.messageType = Container.Type.eTimeRequest; container.timeRequest = { requestId: requestId }; @@ -323,6 +462,7 @@ class Client { } _setTimeDiff(timestamp, timeSent) { + if (!this.enableTimeSync) return; const clientTime = this.timeReceived; const roundTripTime = clientTime - timeSent; const serverTime = (timestamp / 1e9) + roundTripTime / 2; @@ -408,8 +548,8 @@ class Client { requestId: requestId, signalId: nodeIds, numOfDatapoints: noOfDataPoints, - criterionMin: startS - this.timeDiff, - criterionMax: endS - this.timeDiff + criterionMin: this.enableTimeSync ? (startS - this.timeDiff) : startS, + criterionMax: this.enableTimeSync ? (endS - this.timeDiff) : endS }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); diff --git a/event.js b/event.js new file mode 100644 index 0000000..9bc1602 --- /dev/null +++ b/event.js @@ -0,0 +1,117 @@ +// event.js +global.WebSocket = require('ws'); +const Client = require('./client'); + +/** + * Recursively normalizes an object/value. + * If the value is a string, it trims whitespace. + * If it's an object (or array), it normalizes each property. + * This helps ensure that logically identical values produce the same string. + * + * @param {*} val - The value to normalize. + * @returns {*} - The normalized value. + */ +function normalizeValue(val) { + if (typeof val === 'string') { + return val.trim(); + } else if (typeof val === 'object' && val !== null) { + if (Array.isArray(val)) { + return val.map(normalizeValue); + } else { + const keys = Object.keys(val).sort(); + const normalized = {}; + for (const key of keys) { + normalized[key.trim()] = normalizeValue(val[key]); + } + return normalized; + } + } + return val; +} + +/** + * Recursively returns a canonical JSON string for the given object. + * Keys are sorted so that two objects with the same properties produce the same string. + * + * @param {*} obj - The object/value to canonicalize. + * @returns {string} - The canonical JSON string. + */ +function canonicalize(obj) { + if (typeof obj !== 'object' || obj === null) { + return JSON.stringify(obj); + } + if (Array.isArray(obj)) { + return '[' + obj.map(canonicalize).join(',') + ']'; + } + const keys = Object.keys(obj).sort(); + const result = keys + .map(key => JSON.stringify(key) + ':' + canonicalize(obj[key])) + .join(','); + return '{' + result + '}'; +} + +(async function main() { + const client = new Client('ws://127.0.0.1:17000', false); + try { + // Example query: adjust the time range, etc., as needed: + const query = { + timeRangeBegin: 1742540000, + timeRangeEnd: 1742550000, + codeMask: 0xFFFFFFFF, + limit: 100, + offset: 0, + flags: 1 // 'NewestFirst' from your enum + }; + + const events = await client.requestEvents(query); + + // De-duplicate events using a composite key built from normalized fields. + // We'll canonicalize e.data to handle reordered JSON keys. + const seen = new Set(); + const uniqueEvents = []; + + for (const e of events) { + const tsPart = (typeof e.timestampSec !== 'undefined' && e.timestampSec !== null) + ? String(e.timestampSec) + : ''; + + const codePart = (typeof e.code !== 'undefined' && e.code !== null) + ? String(e.code) + : ''; + + const senderPart = (typeof e.sender !== 'undefined' && e.sender !== null) + ? String(e.sender) + : ''; + + // Canonicalize the data so that JSON field order does not matter + const dataPart = e.data + ? canonicalize(normalizeValue(e.data)) + : ''; + + const compositeKey = `${tsPart}-${codePart}-${senderPart}-${dataPart}`; + + if (!seen.has(compositeKey)) { + seen.add(compositeKey); + uniqueEvents.push(e); + } + } + + // Print the unique events + if (uniqueEvents.length === 0) { + console.log("No events found."); + } else { + for (const evt of uniqueEvents) { + console.log(`Timestamp: ${evt.timestampSec}`); + console.log(`Code: ${evt.code}`); + console.log(`Sender: ${evt.sender}`); + console.log(`Data: ${JSON.stringify(evt.data)}`); + console.log('--------------------'); + } + } + } catch (err) { + console.error("Error retrieving events:", err); + } finally { + client.disconnect(); + process.exit(0); + } +})(); diff --git a/index.js b/index.js index 28d1487..e76f24f 100644 --- a/index.js +++ b/index.js @@ -1,56 +1,113 @@ // index.js +// Example demonstration including an events query for a specific time range (UTC 9:40) + global.WebSocket = require('ws'); const Client = require('./client'); -const client = new Client('127.0.0.1', 17000, false); - -// Print the node information (name and routing) +// Print the node information (name, routing, and tags) function printLoggedNodes() { client.requestLoggedNodes() .then(nodes => { console.log("Connected nodes:"); nodes.forEach(node => { console.log(`Name: ${node.name}, Routing: ${node.routing}`); + if (node.tags) { + console.log("Tags:"); + Object.entries(node.tags).forEach(([key, tagInfo]) => { + console.log(` ${key}: value=${tagInfo.value}, source=${tagInfo.source}`); + }); + } + console.log('--------------------'); }); - console.log('--------------------'); }) .catch(err => { console.error("Error retrieving logged nodes:", err); }); } -function onDataPointsReceived(dataPoints) { - dataPoints.forEach(point => { - console.log(`Timestamp: ${point.timestamp}`); - if (point.value && point.value["Output"]) { - const val = point.value["Output"]; - console.log(`Min: ${val.min}`); - console.log(`Max: ${val.max}`); - console.log(`Last: ${val.last}`); +// Print data points for the "Output" node. +async function printDataPoints() { + try { + const limits = await client.requestLogLimits(); + console.log("Log limits received:", limits); + + const dataPoints = await client.requestDataPoints(["Output"], limits.startS, limits.endS, 25); + console.log("Data Points retrieved:"); + dataPoints.forEach(point => { + console.log(`Timestamp: ${point.timestamp}`); + if (point.value && point.value["Output"]) { + const val = point.value["Output"]; + console.log(`Min: ${val.min}`); + console.log(`Max: ${val.max}`); + console.log(`Last: ${val.last}`); + } else { + console.log("No data for 'Output':", point); + } + console.log('--------------------'); + }); + } catch (err) { + console.error("Error retrieving data points:", err); + } +} + +// Print events retrieved within a time range corresponding to UTC 9:40. +// In this example, we use a 5-minute window starting at UTC 9:40. +async function printEvents() { + try { + // Specify the target time for events in UTC. + // Adjust the date as needed; here we assume a specific date. + const targetDate = new Date("2025-03-21T09:38:00Z"); + const targetTime = targetDate.getTime() / 1000; + // Define a window of 5 minutes (300 seconds) + const timeWindow = 5 * 60; + + const eventQuery = { + timeRangeBegin: targetTime, + timeRangeEnd: targetTime + timeWindow, + codeMask: 0, + limit: 100, + offset: 0, + flags: 0, + // Optionally, add senderConditions or dataConditions if desired. + }; + + const events = await client.requestEvents(eventQuery); + console.log("Events retrieved:"); + if (!events || events.length === 0) { + console.log("No events found with the current query."); } else { - console.log("No data for 'Output':", point); + events.forEach(evt => { + console.log(`Timestamp: ${evt.timestampSec}`); + console.log(` Code: ${evt.data && evt.data.Code ? evt.data.Code : "N/A"}`); + console.log(` Source: ${evt.data && evt.data.Source ? evt.data.Source : "N/A"}`); + console.log(` Text: ${evt.data && evt.data.Text ? evt.data.Text : "N/A"}`); + console.log('--------------------'); + }); } - console.log('--------------------'); - }); - // When finished processing, disconnect and exit - setTimeout(() => { - client.disconnect(); - process.exit(0); - }, 5000); + } catch (err) { + console.error("Error retrieving events:", err); + } } -function requestDataPoints(limits) { - console.log("Log limits received:", limits); - return client.requestDataPoints(["Output"], limits.start_s, limits.end_s, 25); +async function main() { + try { + printLoggedNodes(); + await printDataPoints(); + await printEvents(); + } catch (error) { + console.error("Error in main:", error); + } finally { + client.disconnect(); + process.exit(0); + } } -function onError(error) { - console.error("Error:", error); -} +// Create a new client instance. (In this example, autoReconnect is disabled.) +const client = new Client('ws://127.0.0.1:17000', false); -// Kick off both the nodes request and data points request: -printLoggedNodes(); -client.requestLogLimits() - .then(requestDataPoints) - .then(onDataPointsReceived) - .catch(onError); +// Instead of overriding ws.onopen (which may cancel internal logic), +// add an event listener so that _onOpen is still called. +client.ws.addEventListener("open", () => { + console.log("WebSocket connection established."); + main(); +}); diff --git a/package-lock.json b/package-lock.json index edf340a..cdbd936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "cdplogger-js", + "name": "JavascriptCDPLoggerClient", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test/client.test.js b/test/client.test.js index 98024cb..b53da15 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -1,22 +1,21 @@ -// client.test.js +/*global WebSocket*/ global.WebSocket = require('ws'); const Client = require('../client'); const fakeData = require('./fakeData'); - describe('ClientTester', () => { let client; beforeEach(() => { - // Override _connect to return a fake ws object that doesn't try to connect. - Client.prototype._connect = function(url) { - return { - _url: url, - close: jest.fn(), - // You can add any other dummy methods as needed. + // Override _connect to return a fake ws object that doesn't try to connect. + Client.prototype._connect = function(url) { + return { + _url: url, + close: jest.fn(), + send: jest.fn() + }; }; - }; - // Create a new client instance. - client = new Client('127.0.0.1', 17000, true); + // Create a new client instance using two parameters: endpoint and autoReconnect. + client = new Client('127.0.0.1:17000', true); // Adjust the client’s lastTimeRequest so that a new time request will be triggered. client.lastTimeRequest = Date.now() / 1000 - 11; // Prepopulate the lookup maps. @@ -33,15 +32,12 @@ describe('ClientTester', () => { }); test('test_run_event_loop', () => { - // In our JS version we might not have a runEventLoop, - // so we simulate it by adding a dummy method. client.runEventLoop = jest.fn(); client.runEventLoop(); expect(client.runEventLoop).toHaveBeenCalled(); }); test('test_disconnect', () => { - // Replace ws and _cleanupQueuedRequests with mocks. client.ws = { close: jest.fn() }; client._cleanupQueuedRequests = jest.fn(); client.disconnect(); @@ -95,7 +91,6 @@ describe('ClientTester', () => { done(); }); }); - test('test_version_request', done => { client.isOpen = true; @@ -133,8 +128,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.start_s).toBeCloseTo(1529497537.61); - expect(limits.end_s).toBeCloseTo(1531389483.02); + expect(limits.startS).toBeCloseTo(1529497537.61); + expect(limits.endS).toBeCloseTo(1531389483.02); done(); }) .catch(done.fail); @@ -149,8 +144,8 @@ describe('ClientTester', () => { client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { - expect(limits.start_s).toBeCloseTo(1529497537.61 + 10); - expect(limits.end_s).toBeCloseTo(1531389483.02 + 10); + expect(limits.startS).toBeCloseTo(1529497537.61 + 10); + expect(limits.endS).toBeCloseTo(1531389483.02 + 10); done(); }) .catch(done.fail); @@ -194,14 +189,36 @@ describe('ClientTester', () => { client.isOpen = true; client._sendTimeRequest = jest.fn(); client._sendLoggedNodesRequest = jest.fn(); - client.requestDataPoints(["Outputt", "CPULoad"], 1531313250.0, 1531461231.0, 500) + + // Remove "Output" so that the lookup fails. + delete client.nameToId["Output"]; + for (const id in client.idToName) { + if (client.idToName[id] === "Output") { + delete client.idToName[id]; + } + } + + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) .catch(error => { expect(error).toBeInstanceOf(Error); - expect(error.message).toMatch(/Outputt/); + expect(error.message).toMatch(/Output/); done(); }); - // Simulate a logged nodes response that does not include "Outputt" - const response = fakeData.createLoggedNodesResponse(2); + // Simulate a logged nodes response that does NOT include "Output". + const response = { + messageType: fakeData.Container.Type.eSignalInfoResponse, + signalInfoResponse: { + requestId: 2, + name: ["CPULoad", "MemUsed", "CDPSignal"], + id: [1, 2, 3], + type: [], + path: [ + "loggerApp.CPULoad", + "loggerApp.MemUsed", + "loggerApp.CDPSignal" + ] + } + }; client._parseMessage(response); }); @@ -218,4 +235,32 @@ describe('ClientTester', () => { const response = fakeData.createErrorResponse(); client._parseMessage(response); }); + + // Added test for events + test('test_events_request', done => { + client.isOpen = true; + client._sendTimeRequest = jest.fn(); + client._sendEventsRequest = jest.fn(); + client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) + .then(events => { + expect(events).toBeDefined(); + expect(events.length).toBe(1); + expect(events[0].sender).toBe("TestSender"); + expect(events[0].data.key).toBe("value"); + expect(events[0].timestampSec).toBeCloseTo(1500); + done(); + }) + .catch(done.fail); + // Simulate an events response. + const response = { + messageType: fakeData.Container.Type.eEventsResponse, + eventsResponse: { + requestId: 1, + events: [ + { sender: "TestSender", data: { key: "value" }, timestampSec: 1500, id: 42, code: 100, status: 1, logstampSec: 1500 } + ] + } + }; + client._parseMessage(response); + }); }); diff --git a/test/testTimeSync.js b/test/testTimeSync.js new file mode 100644 index 0000000..d587a3b --- /dev/null +++ b/test/testTimeSync.js @@ -0,0 +1,134 @@ +// testTimeSync.js +const Client = require('../client'); +const fakeData = require('./fakeData'); + +// Override WebSocket with a dummy that provides a send() method. +global.WebSocket = class { + constructor(url) { + this._url = url; + } + send(data) { + // For our test we simply ignore the sent data. + } +}; + +/** + * Helper function to run an API method with time sync enabled and then disabled. + * It forces an update (by setting lastTimeRequest to an old value) before each call. + * The simulateResponse callback simulates the corresponding response by calling _parseMessage. + */ +async function runThrough(methodName, callFunc, simulateResponse) { + console.log(`\n=== Running ${methodName} with time sync ENABLED ===`); + // Force a time update by setting lastTimeRequest to an old value. + client.lastTimeRequest = Date.now() / 1000 - 20; + // Call the API method. + callFunc(); + // Simulate a response if needed. + if (simulateResponse) simulateResponse(); + // Wait longer for the time sync update to complete. + await new Promise(resolve => setTimeout(resolve, 300)); + console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec`); + + // Now disable time sync. + // Clear any pending time requests so they don't update timeDiff later. + client.storedPromises = {}; + client.setEnableTimeSync(false); + console.log(`\n=== Running ${methodName} with time sync DISABLED ===`); + const previousTimeDiff = client.timeDiff; + client.lastTimeRequest = Date.now() / 1000 - 20; + callFunc(); + // When time sync is disabled, do NOT simulate a response. + await new Promise(resolve => setTimeout(resolve, 300)); + console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)`); + // Re-enable time sync for subsequent tests. + client.setEnableTimeSync(true); +} + +async function runTest() { + // Create a new client instance with only endpoint and autoReconnect. + client = new Client('127.0.0.1:17000', true); + + // Override _sendTimeRequest to simulate an immediate server time response with variable delay. + client._sendTimeRequest = function (requestId) { + console.log(`_sendTimeRequest called with requestId: ${requestId}`); + // Simulate variable network delay (e.g., 50 to 300ms) + const delay = Math.floor(Math.random() * 250) + 50; + setTimeout(() => { + // Simulate a server timestamp in nanoseconds. + const simulatedTimestamp = Date.now() * 1e6; + console.log(`Simulated timestamp for request ${requestId} after ${delay}ms: ${simulatedTimestamp}`); + if (client.storedPromises[requestId]) { + client.storedPromises[requestId].resolve(simulatedTimestamp); + delete client.storedPromises[requestId]; + } + }, delay); + }; + + // Override _updateTimeDiff to perform one measurement and log its details. + client._updateTimeDiff = function () { + if (!this.enableTimeSync) return; + const requestId = this._getRequestId(); + const timeSent = Date.now() / 1000; + // Call _requestTime (which now calls our overridden _sendTimeRequest). + this._requestTime(requestId) + .then(timestamp => { + // Simulate a time response arriving. + this.timeReceived = Date.now() / 1000; + const roundTripTime = this.timeReceived - timeSent; + const serverTime = (timestamp / 1e9) + roundTripTime / 2; + const computedTimeDiff = this.timeReceived - serverTime; + this.timeDiff = computedTimeDiff; + console.log("=== Time Sync Measurement ==="); + console.log(`Time Sent: ${timeSent.toFixed(6)} sec`); + console.log(`Time Received: ${this.timeReceived.toFixed(6)} sec`); + console.log(`Round Trip Time: ${roundTripTime.toFixed(6)} sec`); + console.log(`Simulated Server Time: ${serverTime.toFixed(6)} sec`); + console.log(`Computed timeDiff: ${computedTimeDiff.toFixed(6)} sec`); + }) + .catch(err => console.error(err)); + }; + + // Use the production _requestTime (which already checks enableTimeSync). + // No override needed here. + + // Now run through several public API methods. + await runThrough( + "requestApiVersion", + () => client.requestApiVersion(), + () => { + // Simulate a valid API version response. + const response = fakeData.createApiVersionResponse(); + client._parseMessage(response); + } + ); + + await runThrough( + "requestLogLimits", + () => client.requestLogLimits(), + () => { + const response = fakeData.createLogLimitsResponse(); + client._parseMessage(response); + } + ); + + await runThrough( + "requestLoggedNodes", + () => client.requestLoggedNodes(), + () => { + const response = fakeData.createLoggedNodesResponse(1); + client._parseMessage(response); + } + ); + + await runThrough( + "requestDataPoints", + () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500), + () => { + const response = fakeData.createDataPointResponse(); + client._parseMessage(response); + } + ); +} + +let client; +runTest().catch(console.error); From 7853884e0c9798a89da6afe347aa507b20a8246c Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Sun, 23 Mar 2025 16:52:20 +0200 Subject: [PATCH 07/37] Refactored event into a seperate example file --- client.js | 2 +- event.js | 1 + index.js | 39 -------------- test/testTimeSync.js | 118 ++++++++++++++++++++++++++++++------------- 4 files changed, 85 insertions(+), 75 deletions(-) diff --git a/client.js b/client.js index e0df47b..5fdd632 100644 --- a/client.js +++ b/client.js @@ -182,7 +182,7 @@ class Client { * codeMask: 0, * limit: 100, * offset: 0, - * flags: 1 // Numeric flags as defined in your protocol + * flags: 1 * } * @returns {Promise} Resolves with an array of events. */ diff --git a/event.js b/event.js index 9bc1602..c596d61 100644 --- a/event.js +++ b/event.js @@ -1,6 +1,7 @@ // event.js global.WebSocket = require('ws'); const Client = require('./client'); +// NOTE: Event support is only on API version 4.0.0+ /** * Recursively normalizes an object/value. diff --git a/index.js b/index.js index e76f24f..80c5b09 100644 --- a/index.js +++ b/index.js @@ -50,50 +50,11 @@ async function printDataPoints() { } } -// Print events retrieved within a time range corresponding to UTC 9:40. -// In this example, we use a 5-minute window starting at UTC 9:40. -async function printEvents() { - try { - // Specify the target time for events in UTC. - // Adjust the date as needed; here we assume a specific date. - const targetDate = new Date("2025-03-21T09:38:00Z"); - const targetTime = targetDate.getTime() / 1000; - // Define a window of 5 minutes (300 seconds) - const timeWindow = 5 * 60; - - const eventQuery = { - timeRangeBegin: targetTime, - timeRangeEnd: targetTime + timeWindow, - codeMask: 0, - limit: 100, - offset: 0, - flags: 0, - // Optionally, add senderConditions or dataConditions if desired. - }; - - const events = await client.requestEvents(eventQuery); - console.log("Events retrieved:"); - if (!events || events.length === 0) { - console.log("No events found with the current query."); - } else { - events.forEach(evt => { - console.log(`Timestamp: ${evt.timestampSec}`); - console.log(` Code: ${evt.data && evt.data.Code ? evt.data.Code : "N/A"}`); - console.log(` Source: ${evt.data && evt.data.Source ? evt.data.Source : "N/A"}`); - console.log(` Text: ${evt.data && evt.data.Text ? evt.data.Text : "N/A"}`); - console.log('--------------------'); - }); - } - } catch (err) { - console.error("Error retrieving events:", err); - } -} async function main() { try { printLoggedNodes(); await printDataPoints(); - await printEvents(); } catch (error) { console.error("Error in main:", error); } finally { diff --git a/test/testTimeSync.js b/test/testTimeSync.js index d587a3b..c075338 100644 --- a/test/testTimeSync.js +++ b/test/testTimeSync.js @@ -12,32 +12,57 @@ global.WebSocket = class { } }; +// --- Capture Request IDs for time sync vs. API calls --- +// We override _getRequestId so that for each API call the first call is used for +// the time sync update and the second call is used for the actual API request. +let capturedTimeSyncRequestId = null; +let capturedApiRequestId = null; +const originalGetRequestId = Client.prototype._getRequestId; +Client.prototype._getRequestId = function() { + const id = originalGetRequestId.call(this); + if (capturedTimeSyncRequestId === null) { + capturedTimeSyncRequestId = id; + } else if (capturedApiRequestId === null) { + capturedApiRequestId = id; + } + return id; +}; + /** * Helper function to run an API method with time sync enabled and then disabled. - * It forces an update (by setting lastTimeRequest to an old value) before each call. - * The simulateResponse callback simulates the corresponding response by calling _parseMessage. + * It forces a time update (by setting lastTimeRequest to an old value) before each call. + * The simulateResponse callback simulates the corresponding responses by calling _parseMessage. + * The callback receives two parameters: timeSyncRequestId and apiRequestId. */ async function runThrough(methodName, callFunc, simulateResponse) { + // Reset captured IDs for this run. + capturedTimeSyncRequestId = null; + capturedApiRequestId = null; + console.log(`\n=== Running ${methodName} with time sync ENABLED ===`); - // Force a time update by setting lastTimeRequest to an old value. + // Force a time update. client.lastTimeRequest = Date.now() / 1000 - 20; // Call the API method. callFunc(); - // Simulate a response if needed. - if (simulateResponse) simulateResponse(); - // Wait longer for the time sync update to complete. + // Allow the _getRequestId calls to occur. + await new Promise(resolve => setTimeout(resolve, 50)); + // Simulate two responses: first for the time sync update, then for the API response. + if (simulateResponse) simulateResponse(capturedTimeSyncRequestId, capturedApiRequestId); + // Wait for responses to be processed. await new Promise(resolve => setTimeout(resolve, 300)); console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec`); // Now disable time sync. - // Clear any pending time requests so they don't update timeDiff later. client.storedPromises = {}; client.setEnableTimeSync(false); console.log(`\n=== Running ${methodName} with time sync DISABLED ===`); const previousTimeDiff = client.timeDiff; client.lastTimeRequest = Date.now() / 1000 - 20; + // Reset captured IDs for the disabled run. + capturedTimeSyncRequestId = null; + capturedApiRequestId = null; callFunc(); - // When time sync is disabled, do NOT simulate a response. + // When time sync is disabled, do NOT simulate a time sync response. await new Promise(resolve => setTimeout(resolve, 300)); console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)`); // Re-enable time sync for subsequent tests. @@ -45,34 +70,30 @@ async function runThrough(methodName, callFunc, simulateResponse) { } async function runTest() { - // Create a new client instance with only endpoint and autoReconnect. + // Create a new client instance. client = new Client('127.0.0.1:17000', true); - // Override _sendTimeRequest to simulate an immediate server time response with variable delay. + // Override _sendTimeRequest to simulate a server time response with variable delay. client._sendTimeRequest = function (requestId) { console.log(`_sendTimeRequest called with requestId: ${requestId}`); - // Simulate variable network delay (e.g., 50 to 300ms) const delay = Math.floor(Math.random() * 250) + 50; setTimeout(() => { - // Simulate a server timestamp in nanoseconds. const simulatedTimestamp = Date.now() * 1e6; console.log(`Simulated timestamp for request ${requestId} after ${delay}ms: ${simulatedTimestamp}`); - if (client.storedPromises[requestId]) { - client.storedPromises[requestId].resolve(simulatedTimestamp); - delete client.storedPromises[requestId]; + if (this.storedPromises[requestId]) { + this.storedPromises[requestId].resolve(simulatedTimestamp); + delete this.storedPromises[requestId]; } }, delay); }; - // Override _updateTimeDiff to perform one measurement and log its details. + // Override _updateTimeDiff to log the measurement. client._updateTimeDiff = function () { if (!this.enableTimeSync) return; const requestId = this._getRequestId(); const timeSent = Date.now() / 1000; - // Call _requestTime (which now calls our overridden _sendTimeRequest). this._requestTime(requestId) .then(timestamp => { - // Simulate a time response arriving. this.timeReceived = Date.now() / 1000; const roundTripTime = this.timeReceived - timeSent; const serverTime = (timestamp / 1e9) + roundTripTime / 2; @@ -88,46 +109,73 @@ async function runTest() { .catch(err => console.error(err)); }; - // Use the production _requestTime (which already checks enableTimeSync). - // No override needed here. - - // Now run through several public API methods. + // Run tests for each public API method. await runThrough( "requestApiVersion", () => client.requestApiVersion(), - () => { - // Simulate a valid API version response. - const response = fakeData.createApiVersionResponse(); - client._parseMessage(response); + (timeSyncId, apiId) => { + // Simulate time sync response. + const timeResponse = { + messageType: fakeData.Container.Type.eTimeResponse, + timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } + }; + client._parseMessage(timeResponse); + // Simulate API version response. + const apiResponse = fakeData.createApiVersionResponse(apiId); + client._parseMessage(apiResponse); } ); await runThrough( "requestLogLimits", () => client.requestLogLimits(), - () => { - const response = fakeData.createLogLimitsResponse(); - client._parseMessage(response); + (timeSyncId, apiId) => { + const timeResponse = { + messageType: fakeData.Container.Type.eTimeResponse, + timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } + }; + client._parseMessage(timeResponse); + const apiResponse = fakeData.createLogLimitsResponse(apiId); + client._parseMessage(apiResponse); } ); await runThrough( "requestLoggedNodes", () => client.requestLoggedNodes(), - () => { - const response = fakeData.createLoggedNodesResponse(1); - client._parseMessage(response); + (timeSyncId, apiId) => { + const timeResponse = { + messageType: fakeData.Container.Type.eTimeResponse, + timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } + }; + client._parseMessage(timeResponse); + const apiResponse = fakeData.createLoggedNodesResponse(apiId); + client._parseMessage(apiResponse); } ); + // Ensure that the node mapping includes "CPULoad" before calling requestDataPoints. + if (!("CPULoad" in client.nameToId)) { + console.log("Mapping missing CPULoad. Simulating logged nodes response to update mapping."); + client._parseMessage(fakeData.createLoggedNodesResponse(999)); + } + await runThrough( "requestDataPoints", () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500), - () => { - const response = fakeData.createDataPointResponse(); - client._parseMessage(response); + (timeSyncId, apiId) => { + const timeResponse = { + messageType: fakeData.Container.Type.eTimeResponse, + timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } + }; + client._parseMessage(timeResponse); + const apiResponse = fakeData.createDataPointResponse(apiId); + client._parseMessage(apiResponse); } ); + + // Disconnect the client to close the open WebSocket and allow the process to exit. + client.disconnect(); } let client; From f3a7845c99b50fcbdd54839adbf6e16889915acd Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Sun, 23 Mar 2025 16:57:57 +0200 Subject: [PATCH 08/37] Updated README.md --- README.md | 12 ++++++++++++ test/{testTimeSync.js => timeSync.test.js} | 0 2 files changed, 12 insertions(+) rename test/{testTimeSync.js => timeSync.test.js} (100%) diff --git a/README.md b/README.md index ad458c1..9d21531 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,12 @@ To run the automatic tests with fake data, execute: npm test ``` +To test the time sync functionality using simulated response: + +```bash +node test/timeSync.test.js +``` + ## Usage @@ -36,6 +42,12 @@ https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html node index.js ``` +For usage related to events run: + +```bash +node event.js +``` + ## Contact diff --git a/test/testTimeSync.js b/test/timeSync.test.js similarity index 100% rename from test/testTimeSync.js rename to test/timeSync.test.js From d30440c054b574cf11f695f51c250d8c845f82e9 Mon Sep 17 00:00:00 2001 From: stefanrammo <86823284+stefanrammo@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:39:43 +0200 Subject: [PATCH 09/37] Fixed bugs --- README.md | 2 +- event.js | 95 +++++++++++++++------- test/{timeSync.test.js => testTimeSync.js} | 0 3 files changed, 67 insertions(+), 30 deletions(-) rename test/{timeSync.test.js => testTimeSync.js} (100%) diff --git a/README.md b/README.md index 9d21531..16ca345 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ npm test To test the time sync functionality using simulated response: ```bash -node test/timeSync.test.js +node test/testTimeSync.js ``` diff --git a/event.js b/event.js index c596d61..3c8fcdf 100644 --- a/event.js +++ b/event.js @@ -5,7 +5,7 @@ const Client = require('./client'); /** * Recursively normalizes an object/value. - * If the value is a string, it trims whitespace. + * If the value is a string, it trims whitespace and compresses internal whitespace. * If it's an object (or array), it normalizes each property. * This helps ensure that logically identical values produce the same string. * @@ -14,7 +14,7 @@ const Client = require('./client'); */ function normalizeValue(val) { if (typeof val === 'string') { - return val.trim(); + return val.trim().replace(/\s+/g, ' '); } else if (typeof val === 'object' && val !== null) { if (Array.isArray(val)) { return val.map(normalizeValue); @@ -51,45 +51,77 @@ function canonicalize(obj) { return '{' + result + '}'; } +/** + * Orders the keys of an object based on a desired order. + * Keys in the desiredOrder array appear first (in that order) and any remaining keys + * are appended in alphabetical order. + * + * @param {Object} obj - The object whose keys are to be ordered. + * @returns {Object} - A new object with keys in the desired order. + */ +function orderObjectKeys(obj) { + if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { + return obj; + } + // Define your desired key order + const desiredOrder = ["Level", "Group", "Description", "Text"]; + const ordered = {}; + + // Add keys in the desired order if they exist in the object + for (const key of desiredOrder) { + if (key in obj) { + ordered[key] = obj[key]; + } + } + + // Get any keys not in the desired order and sort them alphabetically + const remainingKeys = Object.keys(obj) + .filter(key => !desiredOrder.includes(key)) + .sort(); + + for (const key of remainingKeys) { + ordered[key] = obj[key]; + } + return ordered; +} + (async function main() { const client = new Client('ws://127.0.0.1:17000', false); try { - // Example query: adjust the time range, etc., as needed: + // Wide time range and large limit const query = { - timeRangeBegin: 1742540000, - timeRangeEnd: 1742550000, - codeMask: 0xFFFFFFFF, - limit: 100, + timeRangeBegin: 0, // start from the epoch + timeRangeEnd: 2147483647, // far in the future + codeMask: 0xFFFFFFFF, // all codes + limit: 1000, // max number of events to retrieve offset: 0, - flags: 1 // 'NewestFirst' from your enum + flags: 1 // e.g. 'NewestFirst' }; const events = await client.requestEvents(query); - // De-duplicate events using a composite key built from normalized fields. - // We'll canonicalize e.data to handle reordered JSON keys. + // ----------------------------------------------------------------------- + // Deduplicate events: + // Use only the sender and the event's data (after normalizing and ordering) + // to build a composite key. This ignores differences in timestamp, code, + // or JSON key order. + // ----------------------------------------------------------------------- const seen = new Set(); const uniqueEvents = []; for (const e of events) { - const tsPart = (typeof e.timestampSec !== 'undefined' && e.timestampSec !== null) - ? String(e.timestampSec) - : ''; + const senderPart = (typeof e.sender === 'string') ? e.sender : ''; - const codePart = (typeof e.code !== 'undefined' && e.code !== null) - ? String(e.code) - : ''; - - const senderPart = (typeof e.sender !== 'undefined' && e.sender !== null) - ? String(e.sender) - : ''; - - // Canonicalize the data so that JSON field order does not matter - const dataPart = e.data - ? canonicalize(normalizeValue(e.data)) - : ''; + // Process the data: normalize, then order the keys + let dataPart = ''; + if (e.data) { + const normalizedData = normalizeValue(e.data); + const orderedData = orderObjectKeys(normalizedData); + dataPart = canonicalize(orderedData); + } - const compositeKey = `${tsPart}-${codePart}-${senderPart}-${dataPart}`; + // Build composite key from sender and data only + const compositeKey = `${senderPart}-${dataPart}`; if (!seen.has(compositeKey)) { seen.add(compositeKey); @@ -97,15 +129,20 @@ function canonicalize(obj) { } } - // Print the unique events + // Print the final unique events, with data keys ordered for display if (uniqueEvents.length === 0) { - console.log("No events found."); + console.log("No events found (after dedup)."); } else { + console.log(`Showing ${uniqueEvents.length} unique events:\n`); for (const evt of uniqueEvents) { console.log(`Timestamp: ${evt.timestampSec}`); console.log(`Code: ${evt.code}`); console.log(`Sender: ${evt.sender}`); - console.log(`Data: ${JSON.stringify(evt.data)}`); + let orderedData = evt.data; + if (typeof evt.data === 'object' && evt.data !== null && !Array.isArray(evt.data)) { + orderedData = orderObjectKeys(evt.data); + } + console.log(`Data: ${JSON.stringify(orderedData)}`); console.log('--------------------'); } } diff --git a/test/timeSync.test.js b/test/testTimeSync.js similarity index 100% rename from test/timeSync.test.js rename to test/testTimeSync.js From 0d8b2f0a7ed84ff8d9487e43e7a81d09e446580d Mon Sep 17 00:00:00 2001 From: stefanrammo <86823284+stefanrammo@users.noreply.github.com> Date: Mon, 24 Mar 2025 15:28:33 +0200 Subject: [PATCH 10/37] Fixed pull request issues --- .gitignore | 3 +- README.md | 4 +- client.js | 118 +++++++++++++++++++++----- event.js | 155 ---------------------------------- examples/event.js | 41 +++++++++ index.js => examples/index.js | 2 +- package-lock.json | 2 +- test/client.test.js | 86 ++++++++++++++++--- test/fakeData.js | 2 + test/testTimeSync.js | 31 +++++-- 10 files changed, 248 insertions(+), 196 deletions(-) delete mode 100644 event.js create mode 100644 examples/event.js rename index.js => examples/index.js (98%) diff --git a/.gitignore b/.gitignore index 909f568..9e99588 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ node_modules/ -protos/ -helpers/ \ No newline at end of file +protos/ \ No newline at end of file diff --git a/README.md b/README.md index 16ca345..74a985c 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,13 @@ https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html 2. Run the index.js file from the command line: ```bash -node index.js +node examples/index.js ``` For usage related to events run: ```bash -node event.js +node examples/event.js ``` diff --git a/client.js b/client.js index 5fdd632..9978c8a 100644 --- a/client.js +++ b/client.js @@ -1,8 +1,12 @@ +/* client.js */ const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; const CDPValueType = root.ICD.Protobuf.CDPValueType; +/** + * A client for interacting with CDP Logger or LogServer via WebSocket. + */ class Client { /** * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000") @@ -27,7 +31,7 @@ class Client { this.nameToId = {}; this.idToName = {}; - // New mapping for signal types. + // Mapping for signal types (in case we need to interpret values). this.nameToType = {}; // Time-diff related @@ -43,7 +47,13 @@ class Client { /** * Enable or disable time synchronization. - * @param {boolean} enable - If true, time sync is enabled; if false, time sync is disabled. + * + * Note: + * Time sync is triggered on-demand (e.g., with the next request) or after a timeout. + * Re-enabling time sync will automatically sync on the next operation. + * For immediate sync, call `_updateTimeDiff()` explicitly. + * + * @param {boolean} enable - True to enable, false to disable time sync. */ setEnableTimeSync(enable) { this.enableTimeSync = enable; @@ -174,17 +184,50 @@ class Client { /** * Request events based on the provided query parameters. + * + * The `query.flags` field uses bitmask values similar to an enum: + * 0 = None + * 1 = NewestFirst + * 2 = TimeRangeBeginExclusive + * 4 = TimeRangeEndExclusive + * 8 = UseLogStampForTimeRange + * + * The `query.senderConditions` field can be used to filter by event sender (Source). + * The `query.dataConditions` field can be used to filter by data fields (key-value patterns). + * + * For additional information: + * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#Flags-enum + * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#cdp-event-code-flags + * + * We also support mapping the `evt.code` field to a human-readable string + * with `getEventCodeDescription()`. + * * @param {Object} query - An object matching the EventQuery schema. - * For example: + * Example: * { * timeRangeBegin: 1620000000, - * timeRangeEnd: 1620003600, - * codeMask: 0, - * limit: 100, - * offset: 0, - * flags: 1 + * timeRangeEnd: 1620003600, + * codeMask: 0xFFFFFFFF, + * limit: 100, + * offset: 0, + * flags: 1, // e.g. 'NewestFirst' + * + * // Example conditions: + * senderConditions: { + * conditions: [ + * { value: "*TemperatureSensor*", type: 1 } // 1 = Wildcard + * ] + * }, + * dataConditions: { + * pressure: { + * conditions: [ + * { value: "high", type: 0 } // 0 = Exact + * ] + * } + * } * } - * @returns {Promise} Resolves with an array of events. + * + * @returns {Promise} Resolves with an array of events (each event includes a 'codeDescription'). */ requestEvents(query) { this._timeRequest(); @@ -202,11 +245,41 @@ class Client { _sendEventsRequest(requestId, query) { const container = Container.create(); container.messageType = Container.Type.eEventsRequest; - container.eventsRequest = { requestId: requestId, query: query }; + container.eventsRequest = { requestId, query }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); } + /** + * Converts a numeric CDP event code into a descriptive string. + * Multiple flags can be set simultaneously, so we combine them. + * + * Common codes (from the docs): + * 0x1 = AlarmSet + * 0x2 = AlarmClr + * 0x4 = AlarmAck + * 0x40 = AlarmReprise + * 0x100 = SourceObjectUnavailable + * 0x40000000 = NodeBoot + * + * @param {number} code - The event code from an eEventsResponse + * @returns {string} - A human-readable combination of flags + */ + getEventCodeDescription(code) { + const flags = []; + if (code & 0x1) flags.push("AlarmSet"); + if (code & 0x2) flags.push("AlarmClr"); + if (code & 0x4) flags.push("AlarmAck"); + if (code & 0x40) flags.push("AlarmReprise"); + if (code & 0x100) flags.push("SourceObjectUnavailable"); + if (code & 0x40000000) flags.push("NodeBoot"); + + if (flags.length === 0) { + flags.push("None"); + } + return flags.join(" + "); + } + _handleMessage(ws, message) { const data = Container.decode(new Uint8Array(message)); this._parseMessage(data); @@ -292,13 +365,13 @@ class Client { } case Container.Type.eSignalDataResponse: { - let dataPoints = []; + const dataPoints = []; let index = 0; for (const row of data.signalDataResponse.row) { if (this.enableTimeSync) { data.signalDataResponse.criterion[index] += this.timeDiff; } - let signalNames = []; + const signalNames = []; for (const signalId of row.signalId) { signalNames.push(this.idToName[signalId]); } @@ -310,7 +383,7 @@ class Client { ); dataPoints.push({ timestamp: data.signalDataResponse.criterion[index], - value: value + value }); index++; } @@ -323,6 +396,13 @@ class Client { } case Container.Type.eEventsResponse: { + // Optionally enrich each event with a human-readable code description: + if (data.eventsResponse.events && data.eventsResponse.events.length > 0) { + data.eventsResponse.events.forEach(evt => { + evt.codeDescription = this.getEventCodeDescription(evt.code); + }); + } + if (this.storedPromises[data.eventsResponse.requestId]) { const { resolve } = this.storedPromises[data.eventsResponse.requestId]; delete this.storedPromises[data.eventsResponse.requestId]; @@ -452,11 +532,11 @@ class Client { }); return promise; } - + _sendTimeRequest(requestId) { const container = Container.create(); container.messageType = Container.Type.eTimeRequest; - container.timeRequest = { requestId: requestId }; + container.timeRequest = { requestId }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); } @@ -484,7 +564,7 @@ class Client { _sendLoggedNodesRequest(requestId) { const container = Container.create(); container.messageType = Container.Type.eSignalInfoRequest; - container.signalInfoRequest = { requestId: requestId }; + container.signalInfoRequest = { requestId }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); } @@ -492,7 +572,7 @@ class Client { _sendLogLimitsRequest(requestId) { const container = Container.create(); container.messageType = Container.Type.eCriterionLimitsRequest; - container.criterionLimitsRequest = { requestId: requestId }; + container.criterionLimitsRequest = { requestId }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); } @@ -545,7 +625,7 @@ class Client { const container = Container.create(); container.messageType = Container.Type.eSignalDataRequest; container.signalDataRequest = { - requestId: requestId, + requestId, signalId: nodeIds, numOfDatapoints: noOfDataPoints, criterionMin: this.enableTimeSync ? (startS - this.timeDiff) : startS, @@ -558,7 +638,7 @@ class Client { _sendApiVersionRequest(requestId) { const container = Container.create(); container.messageType = Container.Type.eVersionRequest; - container.versionRequest = { requestId: requestId }; + container.versionRequest = { requestId }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); } diff --git a/event.js b/event.js deleted file mode 100644 index 3c8fcdf..0000000 --- a/event.js +++ /dev/null @@ -1,155 +0,0 @@ -// event.js -global.WebSocket = require('ws'); -const Client = require('./client'); -// NOTE: Event support is only on API version 4.0.0+ - -/** - * Recursively normalizes an object/value. - * If the value is a string, it trims whitespace and compresses internal whitespace. - * If it's an object (or array), it normalizes each property. - * This helps ensure that logically identical values produce the same string. - * - * @param {*} val - The value to normalize. - * @returns {*} - The normalized value. - */ -function normalizeValue(val) { - if (typeof val === 'string') { - return val.trim().replace(/\s+/g, ' '); - } else if (typeof val === 'object' && val !== null) { - if (Array.isArray(val)) { - return val.map(normalizeValue); - } else { - const keys = Object.keys(val).sort(); - const normalized = {}; - for (const key of keys) { - normalized[key.trim()] = normalizeValue(val[key]); - } - return normalized; - } - } - return val; -} - -/** - * Recursively returns a canonical JSON string for the given object. - * Keys are sorted so that two objects with the same properties produce the same string. - * - * @param {*} obj - The object/value to canonicalize. - * @returns {string} - The canonical JSON string. - */ -function canonicalize(obj) { - if (typeof obj !== 'object' || obj === null) { - return JSON.stringify(obj); - } - if (Array.isArray(obj)) { - return '[' + obj.map(canonicalize).join(',') + ']'; - } - const keys = Object.keys(obj).sort(); - const result = keys - .map(key => JSON.stringify(key) + ':' + canonicalize(obj[key])) - .join(','); - return '{' + result + '}'; -} - -/** - * Orders the keys of an object based on a desired order. - * Keys in the desiredOrder array appear first (in that order) and any remaining keys - * are appended in alphabetical order. - * - * @param {Object} obj - The object whose keys are to be ordered. - * @returns {Object} - A new object with keys in the desired order. - */ -function orderObjectKeys(obj) { - if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { - return obj; - } - // Define your desired key order - const desiredOrder = ["Level", "Group", "Description", "Text"]; - const ordered = {}; - - // Add keys in the desired order if they exist in the object - for (const key of desiredOrder) { - if (key in obj) { - ordered[key] = obj[key]; - } - } - - // Get any keys not in the desired order and sort them alphabetically - const remainingKeys = Object.keys(obj) - .filter(key => !desiredOrder.includes(key)) - .sort(); - - for (const key of remainingKeys) { - ordered[key] = obj[key]; - } - return ordered; -} - -(async function main() { - const client = new Client('ws://127.0.0.1:17000', false); - try { - // Wide time range and large limit - const query = { - timeRangeBegin: 0, // start from the epoch - timeRangeEnd: 2147483647, // far in the future - codeMask: 0xFFFFFFFF, // all codes - limit: 1000, // max number of events to retrieve - offset: 0, - flags: 1 // e.g. 'NewestFirst' - }; - - const events = await client.requestEvents(query); - - // ----------------------------------------------------------------------- - // Deduplicate events: - // Use only the sender and the event's data (after normalizing and ordering) - // to build a composite key. This ignores differences in timestamp, code, - // or JSON key order. - // ----------------------------------------------------------------------- - const seen = new Set(); - const uniqueEvents = []; - - for (const e of events) { - const senderPart = (typeof e.sender === 'string') ? e.sender : ''; - - // Process the data: normalize, then order the keys - let dataPart = ''; - if (e.data) { - const normalizedData = normalizeValue(e.data); - const orderedData = orderObjectKeys(normalizedData); - dataPart = canonicalize(orderedData); - } - - // Build composite key from sender and data only - const compositeKey = `${senderPart}-${dataPart}`; - - if (!seen.has(compositeKey)) { - seen.add(compositeKey); - uniqueEvents.push(e); - } - } - - // Print the final unique events, with data keys ordered for display - if (uniqueEvents.length === 0) { - console.log("No events found (after dedup)."); - } else { - console.log(`Showing ${uniqueEvents.length} unique events:\n`); - for (const evt of uniqueEvents) { - console.log(`Timestamp: ${evt.timestampSec}`); - console.log(`Code: ${evt.code}`); - console.log(`Sender: ${evt.sender}`); - let orderedData = evt.data; - if (typeof evt.data === 'object' && evt.data !== null && !Array.isArray(evt.data)) { - orderedData = orderObjectKeys(evt.data); - } - console.log(`Data: ${JSON.stringify(orderedData)}`); - console.log('--------------------'); - } - } - } catch (err) { - console.error("Error retrieving events:", err); - } finally { - client.disconnect(); - process.exit(0); - } -})(); diff --git a/examples/event.js b/examples/event.js new file mode 100644 index 0000000..d24ee4b --- /dev/null +++ b/examples/event.js @@ -0,0 +1,41 @@ +// event.js +global.WebSocket = require('ws'); +const Client = require('../client'); +// NOTE: Event support is only on API version 4.0.0+ + +(async function main() { + const client = new Client('ws://127.0.0.1:17000', false); + try { + // Wide time range and large limit + const query = { + timeRangeBegin: 0, // start from the epoch + timeRangeEnd: 2147483647, // far in the future + codeMask: 0xFFFFFFFF, // all codes + limit: 50, // max number of events to retrieve + offset: 0, + flags: 1 // e.g. 'NewestFirst' + }; + + const events = await client.requestEvents(query); + + // Print events directly (no deduplication or normalization) + if (events.length === 0) { + console.log("No events found."); + } else { + console.log(`Showing ${events.length} events:\n`); + for (const evt of events) { + console.log(`Timestamp: ${evt.timestampSec}`); + // Now we show the numeric code and the human-readable description: + console.log(`Code: ${evt.code} (${evt.codeDescription})`); + console.log(`Sender: ${evt.sender}`); + console.log(`Data: ${JSON.stringify(evt.data)}`); + console.log('--------------------'); + } + } + } catch (err) { + console.error("Error retrieving events:", err); + } finally { + client.disconnect(); + process.exit(0); + } +})(); diff --git a/index.js b/examples/index.js similarity index 98% rename from index.js rename to examples/index.js index 80c5b09..f1965cc 100644 --- a/index.js +++ b/examples/index.js @@ -2,7 +2,7 @@ // Example demonstration including an events query for a specific time range (UTC 9:40) global.WebSocket = require('ws'); -const Client = require('./client'); +const Client = require('../client'); // Print the node information (name, routing, and tags) function printLoggedNodes() { diff --git a/package-lock.json b/package-lock.json index cdbd936..edf340a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "JavascriptCDPLoggerClient", + "name": "cdplogger-js", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/test/client.test.js b/test/client.test.js index b53da15..a326aaa 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -236,31 +236,97 @@ describe('ClientTester', () => { client._parseMessage(response); }); - // Added test for events - test('test_events_request', done => { + // Updated test for events with conditions + test('test_events_request_with_conditions', () => { client.isOpen = true; client._sendTimeRequest = jest.fn(); client._sendEventsRequest = jest.fn(); + + const queryWithConditions = { + timeRangeBegin: 1000, + timeRangeEnd: 2000, + codeMask: 0, + limit: 10, + offset: 0, + flags: 0, + senderConditions: { + conditions: [ + { value: "*TemperatureSensor*", type: 1 } // Wildcard + ] + }, + dataConditions: { + pressure: { + conditions: [ + { value: "high", type: 0 } // Exact + ] + } + } + }; + + client.requestEvents(queryWithConditions); + // Expect the _updateTimeDiff from _timeRequest to have been called first + // Then _sendEventsRequest should be called with request id 1 (not 0). + expect(client._sendTimeRequest).toHaveBeenCalled(); + expect(client._sendEventsRequest).toHaveBeenCalledWith( + 1, // adjusted expectation + queryWithConditions + ); + }); + + // Updated test for events with no known flags (code=0 should yield codeDescription "None") + test('test_event_code_description_none', done => { + client.isOpen = true; + client.requestEvents({}) + .then(events => { + expect(events).toHaveLength(1); + expect(events[0].code).toBe(0); + expect(events[0].codeDescription).toBe("None"); + done(); + }) + .catch(done.fail); + + // Adjust the response requestId to match the expected request id (should be 1) + const response = { + messageType: fakeData.Container.Type.eEventsResponse, + eventsResponse: { + requestId: 1, // updated from 0 to 1 + events: [ + { + sender: "Test", + data: {}, + timestampSec: 1234, + id: 999, + code: 0, + status: 0, + logstampSec: 1234 + } + ] + } + }; + client._parseMessage(response); + }); + + test('test_event_code_description_multiple_flags', done => { + client.isOpen = true; client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) .then(events => { - expect(events).toBeDefined(); - expect(events.length).toBe(1); - expect(events[0].sender).toBe("TestSender"); - expect(events[0].data.key).toBe("value"); - expect(events[0].timestampSec).toBeCloseTo(1500); + expect(events).toHaveLength(1); + // code = 0x5 => (AlarmSet + AlarmAck) + expect(events[0].code).toBe(0x5); + expect(events[0].codeDescription).toBe("AlarmSet + AlarmAck"); done(); }) .catch(done.fail); - // Simulate an events response. + // Simulate a multi-flag code: 0x5 => AlarmSet (0x1) + AlarmAck (0x4). const response = { messageType: fakeData.Container.Type.eEventsResponse, eventsResponse: { requestId: 1, events: [ - { sender: "TestSender", data: { key: "value" }, timestampSec: 1500, id: 42, code: 100, status: 1, logstampSec: 1500 } + { sender: "MultiFlagSensor", data: { key: "value" }, timestampSec: 1500, id: 42, code: 0x5, status: 1, logstampSec: 1500 } ] } }; client._parseMessage(response); }); -}); +}); \ No newline at end of file diff --git a/test/fakeData.js b/test/fakeData.js index 74f9fdc..eb666d0 100644 --- a/test/fakeData.js +++ b/test/fakeData.js @@ -1,3 +1,5 @@ +// fakeData.js + // Define a simple Container object to simulate our protobuf types. const Container = { Type: { diff --git a/test/testTimeSync.js b/test/testTimeSync.js index c075338..d3047b7 100644 --- a/test/testTimeSync.js +++ b/test/testTimeSync.js @@ -13,8 +13,6 @@ global.WebSocket = class { }; // --- Capture Request IDs for time sync vs. API calls --- -// We override _getRequestId so that for each API call the first call is used for -// the time sync update and the second call is used for the actual API request. let capturedTimeSyncRequestId = null; let capturedApiRequestId = null; const originalGetRequestId = Client.prototype._getRequestId; @@ -46,12 +44,16 @@ async function runThrough(methodName, callFunc, simulateResponse) { callFunc(); // Allow the _getRequestId calls to occur. await new Promise(resolve => setTimeout(resolve, 50)); + // Simulate two responses: first for the time sync update, then for the API response. - if (simulateResponse) simulateResponse(capturedTimeSyncRequestId, capturedApiRequestId); + if (simulateResponse) { + simulateResponse(capturedTimeSyncRequestId, capturedApiRequestId); + } + // Wait for responses to be processed. await new Promise(resolve => setTimeout(resolve, 300)); console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec`); - + // Now disable time sync. client.storedPromises = {}; client.setEnableTimeSync(false); @@ -62,9 +64,13 @@ async function runThrough(methodName, callFunc, simulateResponse) { capturedTimeSyncRequestId = null; capturedApiRequestId = null; callFunc(); + // When time sync is disabled, do NOT simulate a time sync response. await new Promise(resolve => setTimeout(resolve, 300)); - console.log(`${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)`); + console.log( + `${methodName} -> timeDiff: ${client.timeDiff.toFixed(6)} sec (should remain ${previousTimeDiff.toFixed(6)} sec)` + ); + // Re-enable time sync for subsequent tests. client.setEnableTimeSync(true); } @@ -120,6 +126,7 @@ async function runTest() { timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } }; client._parseMessage(timeResponse); + // Simulate API version response. const apiResponse = fakeData.createApiVersionResponse(apiId); client._parseMessage(apiResponse); @@ -135,6 +142,7 @@ async function runTest() { timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } }; client._parseMessage(timeResponse); + const apiResponse = fakeData.createLogLimitsResponse(apiId); client._parseMessage(apiResponse); } @@ -149,6 +157,7 @@ async function runTest() { timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } }; client._parseMessage(timeResponse); + const apiResponse = fakeData.createLoggedNodesResponse(apiId); client._parseMessage(apiResponse); } @@ -169,6 +178,7 @@ async function runTest() { timeResponse: { requestId: timeSyncId, timestamp: Date.now() * 1e6 } }; client._parseMessage(timeResponse); + const apiResponse = fakeData.createDataPointResponse(apiId); client._parseMessage(apiResponse); } @@ -179,4 +189,13 @@ async function runTest() { } let client; -runTest().catch(console.error); + +runTest() + .then(() => { + console.log("All tests passed successfully."); + process.exit(0); + }) + .catch(err => { + console.error("Test run failed with error:", err); + process.exit(1); + }); From 2cf2c24070b31c7d2f139bdae1223acf6b2c46db Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Tue, 25 Mar 2025 13:19:59 +0200 Subject: [PATCH 11/37] Added sender and data conditions to event example --- examples/event.js | 153 ++++++++++++++++++++++++++++++++++++++-------- package-lock.json | 2 +- 2 files changed, 129 insertions(+), 26 deletions(-) diff --git a/examples/event.js b/examples/event.js index d24ee4b..0a07855 100644 --- a/examples/event.js +++ b/examples/event.js @@ -3,35 +3,138 @@ global.WebSocket = require('ws'); const Client = require('../client'); // NOTE: Event support is only on API version 4.0.0+ +const { DBMessaging } = require('../generated/containerPb'); + +/** + * Helper: Create an exact match condition for filtering. + * Uses the EventQuery.Condition message. + */ +function createExactCondition(value) { + return DBMessaging.Protobuf.EventQuery.Condition.create({ + value: value, + type: DBMessaging.Protobuf.EventQuery.MatchType.Exact // 0 + }); +} + +/** + * Helper: Create a ConditionList from an array of conditions. + */ +function createConditionList(conditions) { + return DBMessaging.Protobuf.EventQuery.ConditionList.create({ + conditions: conditions + }); +} + +/** + * Helper: Create sender conditions. + * @param {Array} senders - Array of exact-match sender names. + * @param {Array} senderPatterns - Array of wildcard patterns. + * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} + */ +function createSenderConditions(senders = [], senderPatterns = []) { + const conditions = [ + ...senders.map(sender => createExactCondition(sender)), + ...senderPatterns.map(pattern => + DBMessaging.Protobuf.EventQuery.Condition.create({ + value: pattern, + type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard // 1 + }) + ) + ]; + return createConditionList(conditions); +} + +/** + * Helper: Create data conditions. + * @param {Object} dataConditions - Map of data field keys to values (or arrays of values) + * @returns {Object} - Map of field name to ConditionList + */ +function createDataConditions(dataConditions = {}) { + const result = {}; + for (const [key, value] of Object.entries(dataConditions)) { + let conditions; + if (Array.isArray(value)) { + conditions = value.map(v => { + if (typeof v === "string" && (v.includes("*") || v.includes("?"))) { + return DBMessaging.Protobuf.EventQuery.Condition.create({ + value: v, + type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard + }); + } else { + return createExactCondition(String(v)); + } + }); + } else { + if (typeof value === "string" && (value.includes("*") || value.includes("?"))) { + conditions = [ + DBMessaging.Protobuf.EventQuery.Condition.create({ + value: value, + type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard + }) + ]; + } else { + conditions = [createExactCondition(String(value))]; + } + } + result[key] = createConditionList(conditions); + } + return result; +} + +/** + * Create an EventQuery message. + * @param {Object} options - Options for filtering. + * @returns {DBMessaging.Protobuf.EventQuery} + */ +function createEventQuery(options = {}) { + const queryObj = { + timeRangeBegin: options.timeRangeBegin || 0, + timeRangeEnd: options.timeRangeEnd || 2147483647, + codeMask: options.codeMask !== undefined ? options.codeMask : 0xFFFFFFFF, + limit: options.limit || 20, + offset: options.offset || 0, + flags: options.flags || 1 + }; + + if ((options.senders && options.senders.length) || (options.senderPatterns && options.senderPatterns.length)) { + queryObj.senderConditions = createSenderConditions(options.senders || [], options.senderPatterns || []); + } + if (options.dataConditions && Object.keys(options.dataConditions).length > 0) { + queryObj.dataConditions = createDataConditions(options.dataConditions); + } + return DBMessaging.Protobuf.EventQuery.create(queryObj); +} + +/** + * Format an event for display. + */ +function formatEvent(evt) { + return ` +Timestamp: ${evt.timestampSec} +Code: ${evt.code} (${evt.codeDescription}) +Sender: ${evt.sender} +Data: ${JSON.stringify(evt.data)} +--------------------`; +} + (async function main() { const client = new Client('ws://127.0.0.1:17000', false); try { - // Wide time range and large limit - const query = { - timeRangeBegin: 0, // start from the epoch - timeRangeEnd: 2147483647, // far in the future - codeMask: 0xFFFFFFFF, // all codes - limit: 50, // max number of events to retrieve - offset: 0, - flags: 1 // e.g. 'NewestFirst' - }; - - const events = await client.requestEvents(query); - - // Print events directly (no deduplication or normalization) - if (events.length === 0) { - console.log("No events found."); - } else { - console.log(`Showing ${events.length} events:\n`); - for (const evt of events) { - console.log(`Timestamp: ${evt.timestampSec}`); - // Now we show the numeric code and the human-readable description: - console.log(`Code: ${evt.code} (${evt.codeDescription})`); - console.log(`Sender: ${evt.sender}`); - console.log(`Data: ${JSON.stringify(evt.data)}`); - console.log('--------------------'); + // Wait a moment for the connection to establish. + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log("----- Example: Combined Server‑Side Filtering (Sender + Data) -----"); + // Build a query that combines both conditions. + const combinedQuery = createEventQuery({ + senders: ["CDPLoggerDemoApp.InvalidLicense"], + dataConditions: { + "Text": "Invalid or missing feature license detected." } - } + }); + const combinedEvents = await client.requestEvents(combinedQuery); + console.log(`Showing ${combinedEvents.length} events matching both conditions:`); + combinedEvents.forEach(evt => console.log(formatEvent(evt))); + } catch (err) { console.error("Error retrieving events:", err); } finally { diff --git a/package-lock.json b/package-lock.json index edf340a..cdbd936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "cdplogger-js", + "name": "JavascriptCDPLoggerClient", "lockfileVersion": 3, "requires": true, "packages": { From b51959b354fedf4b8dd9be1d1c8d8ba98f066764 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Wed, 26 Mar 2025 12:43:47 +0200 Subject: [PATCH 12/37] Pull review #5 issues fixed --- client.js | 174 +++++++++++++++++++++++++++++++------------ examples/event.js | 176 +++++++++++--------------------------------- test/client.test.js | 86 ++++++++++++++++------ test/fakeData.js | 59 ++++++++++++++- 4 files changed, 291 insertions(+), 204 deletions(-) diff --git a/client.js b/client.js index 9978c8a..9278e76 100644 --- a/client.js +++ b/client.js @@ -1,4 +1,4 @@ -/* client.js */ +// client.js const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; @@ -21,9 +21,7 @@ class Client { this.reqId = -1; this.autoReconnect = autoReconnect; - - // Time synchronization is enabled by default. - this.enableTimeSync = true; + this.enableTimeSync = true; // Time synchronization is enabled by default. this.isOpen = false; this.queuedRequests = {}; @@ -129,6 +127,9 @@ class Client { // --- Public API methods --- + /** + * Request the API version. + */ requestApiVersion() { this._timeRequest(); const requestId = this._getRequestId(); @@ -142,6 +143,9 @@ class Client { }); } + /** + * Request the list of logged nodes. + */ requestLoggedNodes() { this._timeRequest(); const requestId = this._getRequestId(); @@ -155,6 +159,9 @@ class Client { }); } + /** + * Request the log limits. + */ requestLogLimits() { this._timeRequest(); const requestId = this._getRequestId(); @@ -168,6 +175,14 @@ class Client { }); } + /** + * Request data points for given node names and time range. + * @param {Array} nodeNames + * @param {number} startS + * @param {number} endS + * @param {number} noOfDataPoints + * @returns {Promise} + */ requestDataPoints(nodeNames, startS, endS, noOfDataPoints) { this._timeRequest(); const requestId = this._getRequestId(); @@ -186,62 +201,62 @@ class Client { * Request events based on the provided query parameters. * * The `query.flags` field uses bitmask values similar to an enum: - * 0 = None - * 1 = NewestFirst - * 2 = TimeRangeBeginExclusive - * 4 = TimeRangeEndExclusive - * 8 = UseLogStampForTimeRange * - * The `query.senderConditions` field can be used to filter by event sender (Source). - * The `query.dataConditions` field can be used to filter by data fields (key-value patterns). + * 0 = None + * 1 = NewestFirst + * 2 = TimeRangeBeginExclusive + * 4 = TimeRangeEndExclusive + * 8 = UseLogStampForTimeRange + * + * In addition, the user can simply supply the following properties in the query object: * - * For additional information: - * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#Flags-enum - * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#cdp-event-code-flags + * - **senderConditions**: An array of sender strings (exact matches by default). + * - **dataConditions**: An object where each key is a data field name and the value can be: + * - A string (defaults to an exact match), + * - An array of strings, + * - An object (or array of objects) with properties: + * - `value`: the string value to match, + * - `matchType`: either `"exact"` (default) or `"wildcard"`. * - * We also support mapping the `evt.code` field to a human-readable string - * with `getEventCodeDescription()`. + * The helper method `_buildEventQuery(query)` converts this simple plain object into a proper + * `DBMessaging.Protobuf.EventQuery` message. * - * @param {Object} query - An object matching the EventQuery schema. - * Example: - * { - * timeRangeBegin: 1620000000, - * timeRangeEnd: 1620003600, - * codeMask: 0xFFFFFFFF, - * limit: 100, - * offset: 0, - * flags: 1, // e.g. 'NewestFirst' + * enum EventQuery::MatchType: + * - Exact (0): The string must match exactly. + * - Wildcard (1): The string may contain wildcards. * - * // Example conditions: - * senderConditions: { - * conditions: [ - * { value: "*TemperatureSensor*", type: 1 } // 1 = Wildcard - * ] - * }, - * dataConditions: { - * pressure: { - * conditions: [ - * { value: "high", type: 0 } // 0 = Exact - * ] - * } - * } - * } + * Example usage: * + * // Filter for events with sender exactly "CDPLoggerDemoApp.InvalidLicense": + * { senderConditions: ["CDPLoggerDemoApp.InvalidLicense"] } + * + * // Filter for events where the "Text" data field equals "Invalid or missing feature license detected.": + * { dataConditions: { "Text": "Invalid or missing feature license detected." } } + * + * + * @param {Object} query - A simple plain object representing the EventQuery. * @returns {Promise} Resolves with an array of events (each event includes a 'codeDescription'). */ requestEvents(query) { this._timeRequest(); const requestId = this._getRequestId(); + // Convert the simple query into a proper EventQuery message. + const eventQuery = this._buildEventQuery(query); + + + if (!this.isOpen) { - this.queuedRequests[requestId] = { type: "events", query: query }; + this.queuedRequests[requestId] = { type: "events", query: eventQuery }; } else { - this._sendEventsRequest(requestId, query); + this._sendEventsRequest(requestId, eventQuery); } return new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); } + // --- Internal methods --- + _sendEventsRequest(requestId, query) { const container = Container.create(); container.messageType = Container.Type.eEventsRequest; @@ -250,6 +265,74 @@ class Client { this.ws.send(buffer); } + /** + * Helper method to build a proper EventQuery message from a simple plain object. + * + * + * + * + * @param {Object} query - The simple plain object query. + * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. + */ + _buildEventQuery(query) { + const root = require('./generated/containerPb.js'); + const { EventQuery } = root.DBMessaging.Protobuf; + const { MatchType } = EventQuery; + + // Create base query with primitive fields + const baseQuery = { + timeRangeBegin: query.timeRangeBegin || 0, + timeRangeEnd: query.timeRangeEnd || Math.floor(Date.now() / 1000), + codeMask: query.codeMask !== undefined ? query.codeMask : 0xFFFFFFFF, + limit: query.limit || 50, + offset: query.offset || 0, + flags: query.flags || 0 + }; + + // Build sender conditions if present + if (query.senders && query.senders.length > 0) { + baseQuery.senderConditions = { + conditions: query.senders.map(sender => ({ + value: sender, + type: MatchType.Exact + })) + }; + } + + // Build data conditions if present + if (query.dataConditions) { + const dataConds = {}; + for (const key in query.dataConditions) { + const val = query.dataConditions[key]; + const conditions = []; + + if (Array.isArray(val)) { + for (const item of val) { + conditions.push({ + value: String(item), + type: MatchType.Exact + }); + } + } else { + conditions.push({ + value: String(val), + type: MatchType.Exact + }); + } + + // Store without any table qualification + dataConds[key] = { conditions }; + } + baseQuery.dataConditions = dataConds; + } + + return EventQuery.create(baseQuery); + } + + + + + /** * Converts a numeric CDP event code into a descriptive string. * Multiple flags can be set simultaneously, so we combine them. @@ -262,8 +345,8 @@ class Client { * 0x100 = SourceObjectUnavailable * 0x40000000 = NodeBoot * - * @param {number} code - The event code from an eEventsResponse - * @returns {string} - A human-readable combination of flags + * @param {number} code - The event code from an eEventsResponse. + * @returns {string} - A human-readable combination of flags. */ getEventCodeDescription(code) { const flags = []; @@ -396,13 +479,12 @@ class Client { } case Container.Type.eEventsResponse: { - // Optionally enrich each event with a human-readable code description: + // Enrich events with a human-readable code description. if (data.eventsResponse.events && data.eventsResponse.events.length > 0) { data.eventsResponse.events.forEach(evt => { evt.codeDescription = this.getEventCodeDescription(evt.code); }); } - if (this.storedPromises[data.eventsResponse.requestId]) { const { resolve } = this.storedPromises[data.eventsResponse.requestId]; delete this.storedPromises[data.eventsResponse.requestId]; @@ -524,9 +606,7 @@ class Client { } const requestId = reqId; this.lastTimeRequest = Date.now() / 1000; - // Always send the time request. this._sendTimeRequest(requestId); - // Create the promise and store the callbacks. const promise = new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); diff --git a/examples/event.js b/examples/event.js index 0a07855..4802edd 100644 --- a/examples/event.js +++ b/examples/event.js @@ -1,144 +1,56 @@ // event.js -global.WebSocket = require('ws'); -const Client = require('../client'); -// NOTE: Event support is only on API version 4.0.0+ - -const { DBMessaging } = require('../generated/containerPb'); - -/** - * Helper: Create an exact match condition for filtering. - * Uses the EventQuery.Condition message. - */ -function createExactCondition(value) { - return DBMessaging.Protobuf.EventQuery.Condition.create({ - value: value, - type: DBMessaging.Protobuf.EventQuery.MatchType.Exact // 0 - }); -} - -/** - * Helper: Create a ConditionList from an array of conditions. - */ -function createConditionList(conditions) { - return DBMessaging.Protobuf.EventQuery.ConditionList.create({ - conditions: conditions - }); -} - -/** - * Helper: Create sender conditions. - * @param {Array} senders - Array of exact-match sender names. - * @param {Array} senderPatterns - Array of wildcard patterns. - * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} - */ -function createSenderConditions(senders = [], senderPatterns = []) { - const conditions = [ - ...senders.map(sender => createExactCondition(sender)), - ...senderPatterns.map(pattern => - DBMessaging.Protobuf.EventQuery.Condition.create({ - value: pattern, - type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard // 1 - }) - ) - ]; - return createConditionList(conditions); -} - -/** - * Helper: Create data conditions. - * @param {Object} dataConditions - Map of data field keys to values (or arrays of values) - * @returns {Object} - Map of field name to ConditionList - */ -function createDataConditions(dataConditions = {}) { - const result = {}; - for (const [key, value] of Object.entries(dataConditions)) { - let conditions; - if (Array.isArray(value)) { - conditions = value.map(v => { - if (typeof v === "string" && (v.includes("*") || v.includes("?"))) { - return DBMessaging.Protobuf.EventQuery.Condition.create({ - value: v, - type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard - }); - } else { - return createExactCondition(String(v)); - } - }); - } else { - if (typeof value === "string" && (value.includes("*") || value.includes("?"))) { - conditions = [ - DBMessaging.Protobuf.EventQuery.Condition.create({ - value: value, - type: DBMessaging.Protobuf.EventQuery.MatchType.Wildcard - }) - ]; - } else { - conditions = [createExactCondition(String(value))]; - } - } - result[key] = createConditionList(conditions); - } - return result; -} - -/** - * Create an EventQuery message. - * @param {Object} options - Options for filtering. - * @returns {DBMessaging.Protobuf.EventQuery} - */ -function createEventQuery(options = {}) { - const queryObj = { - timeRangeBegin: options.timeRangeBegin || 0, - timeRangeEnd: options.timeRangeEnd || 2147483647, - codeMask: options.codeMask !== undefined ? options.codeMask : 0xFFFFFFFF, - limit: options.limit || 20, - offset: options.offset || 0, - flags: options.flags || 1 - }; +// An example script to see filtered events - if ((options.senders && options.senders.length) || (options.senderPatterns && options.senderPatterns.length)) { - queryObj.senderConditions = createSenderConditions(options.senders || [], options.senderPatterns || []); - } - if (options.dataConditions && Object.keys(options.dataConditions).length > 0) { - queryObj.dataConditions = createDataConditions(options.dataConditions); - } - return DBMessaging.Protobuf.EventQuery.create(queryObj); -} - -/** - * Format an event for display. - */ -function formatEvent(evt) { - return ` -Timestamp: ${evt.timestampSec} -Code: ${evt.code} (${evt.codeDescription}) -Sender: ${evt.sender} -Data: ${JSON.stringify(evt.data)} ---------------------`; -} +const Client = require('../client'); +const root = require('../generated/containerPb'); -(async function main() { +async function main() { const client = new Client('ws://127.0.0.1:17000', false); + try { - // Wait a moment for the connection to establish. - await new Promise(resolve => setTimeout(resolve, 1000)); - - console.log("----- Example: Combined Server‑Side Filtering (Sender + Data) -----"); - // Build a query that combines both conditions. - const combinedQuery = createEventQuery({ - senders: ["CDPLoggerDemoApp.InvalidLicense"], + console.log("Waiting for connection to establish..."); + await new Promise(resolve => setTimeout(resolve, 2000)); + + const query = { + timeRangeBegin: Math.floor(Date.now() / 1000) - (24 * 60 * 60), // Last 24 hours + timeRangeEnd: Math.floor(Date.now() / 1000), + limit: 50, + offset: 0, + senderConditions: ["CDPLoggerDemoApp.CDP.CDPEngine"], dataConditions: { - "Text": "Invalid or missing feature license detected." + "Text": "Component CDPLoggerDemoApp.Sine has been suspended" } - }); - const combinedEvents = await client.requestEvents(combinedQuery); - console.log(`Showing ${combinedEvents.length} events matching both conditions:`); - combinedEvents.forEach(evt => console.log(formatEvent(evt))); + }; + + console.log("Sending event query..."); + console.log("Query:", JSON.stringify(query, null, 2)); + + const events = await client.requestEvents(query); + console.log(`Received ${events.length} events`); + + if (events.length > 0) { + console.log('\nEvents:'); + events.forEach(event => { + const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data; + console.log(JSON.stringify({ + timestamp: event.timestampSec, + sender: event.sender, + data: data + }, null, 2)); + }); + } - } catch (err) { - console.error("Error retrieving events:", err); + } catch (error) { + console.error('Error:', error); + console.error('Stack:', error.stack); } finally { + console.log("Disconnecting from CDP Logger..."); client.disconnect(); process.exit(0); } -})(); +} + +main().catch(error => { + console.error("Unhandled error:", error); + process.exit(1); +}); diff --git a/test/client.test.js b/test/client.test.js index a326aaa..5c879c5 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -236,7 +236,7 @@ describe('ClientTester', () => { client._parseMessage(response); }); - // Updated test for events with conditions + // Updated test for events with conditions using expected query structure. test('test_events_request_with_conditions', () => { client.isOpen = true; client._sendTimeRequest = jest.fn(); @@ -249,31 +249,21 @@ describe('ClientTester', () => { limit: 10, offset: 0, flags: 0, - senderConditions: { - conditions: [ - { value: "*TemperatureSensor*", type: 1 } // Wildcard - ] - }, + senderConditions: ["*CDPLoggerDemoApp.Sine*"], dataConditions: { - pressure: { - conditions: [ - { value: "high", type: 0 } // Exact - ] - } + "Text": "Component was suspended!" } }; client.requestEvents(queryWithConditions); - // Expect the _updateTimeDiff from _timeRequest to have been called first - // Then _sendEventsRequest should be called with request id 1 (not 0). - expect(client._sendTimeRequest).toHaveBeenCalled(); - expect(client._sendEventsRequest).toHaveBeenCalledWith( - 1, // adjusted expectation - queryWithConditions - ); + // Expect _sendTimeRequest to have been called first with id 0. + expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + // Build the expected query using _buildEventQuery. + const builtQuery = client._buildEventQuery(queryWithConditions); + expect(client._sendEventsRequest).toHaveBeenCalledWith(1, builtQuery); }); - // Updated test for events with no known flags (code=0 should yield codeDescription "None") + // Updated test for events with no known flags (code=0 => "None") test('test_event_code_description_none', done => { client.isOpen = true; client.requestEvents({}) @@ -285,11 +275,10 @@ describe('ClientTester', () => { }) .catch(done.fail); - // Adjust the response requestId to match the expected request id (should be 1) const response = { messageType: fakeData.Container.Type.eEventsResponse, eventsResponse: { - requestId: 1, // updated from 0 to 1 + requestId: 1, events: [ { sender: "Test", @@ -311,13 +300,13 @@ describe('ClientTester', () => { client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) .then(events => { expect(events).toHaveLength(1); - // code = 0x5 => (AlarmSet + AlarmAck) + // code = 0x5 => (AlarmSet (0x1) + AlarmAck (0x4)) expect(events[0].code).toBe(0x5); expect(events[0].codeDescription).toBe("AlarmSet + AlarmAck"); done(); }) .catch(done.fail); - // Simulate a multi-flag code: 0x5 => AlarmSet (0x1) + AlarmAck (0x4). + // Simulate a multi-flag event response. const response = { messageType: fakeData.Container.Type.eEventsResponse, eventsResponse: { @@ -329,4 +318,53 @@ describe('ClientTester', () => { }; client._parseMessage(response); }); -}); \ No newline at end of file + + test('test_realistic_events', done => { + client.isOpen = true; + + // Request events in a time window covering the sample timestamps (08:34:50..08:37:21) + client.requestEvents({ + timeRangeBegin: 1740284000, + timeRangeEnd: 1740284300, + codeMask: 0xFFFFFFFF, + limit: 10, + offset: 0, + flags: 0 + }) + .then(events => { + // We expect to receive 4 events total + expect(events).toHaveLength(4); + + // 1) InvalidLicense alarm + expect(events[0].sender).toBe("CPDLoggerDemoApp.InvalidLicense"); + expect(events[0].data["Text"]).toBe("Invalid or missing feature license detected."); + expect(events[0].codeDescription).toBe("AlarmSet"); + expect(events[0].status).toBe(1); // "Error" + + // 2) CPDEventNotification + expect(events[1].sender).toBe("CDPLoggerDemoApp.CPDEventNotification"); + expect(events[1].data["Text"]).toBe("CDP event notice"); + expect(events[1].codeDescription).toBe("None"); + expect(events[1].status).toBe(3); // "Notify" + + // 3) A component is suspended + expect(events[2].sender).toBe("CPDLoggerDemoApp"); + expect(events[2].data["Text"]).toContain("A component is suspended"); + expect(events[2].codeDescription).toBe("AlarmSet"); + expect(events[2].status).toBe(1); // "Error" + + // 4) Another suspended warning + expect(events[3].sender).toBe("CPDLoggerDemoApp"); + expect(events[3].data["Text"]).toBe("Component was suspended"); + expect(events[3].codeDescription).toBe("None"); + expect(events[3].status).toBe(2); // "Warning" + + done(); + }) + .catch(done.fail); + + // Simulate the server responding with these "realistic" events + const response = fakeData.createRealisticEventsResponse(1); + client._parseMessage(response); + }); +}); diff --git a/test/fakeData.js b/test/fakeData.js index eb666d0..eab99db 100644 --- a/test/fakeData.js +++ b/test/fakeData.js @@ -39,7 +39,7 @@ function createApiVersionErrorResponse() { function createLogLimitsResponse() { return { - messageType: Container.Type.eCriterionLimitsResponse, // value 6 + messageType: Container.Type.eCriterionLimitsResponse, criterionLimitsResponse: { requestId: 1, criterionMin: 1529497537.61, @@ -101,6 +101,62 @@ function createErrorResponse() { }; } + +function createRealisticEventsResponse(requestId = 1) { + return { + messageType: Container.Type.eEventsResponse, + eventsResponse: { + requestId, + events: [ + { + sender: "CPDLoggerDemoApp.InvalidLicense", + data: { + Text: "Invalid or missing feature license detected." + }, + timestampSec: 1740284241, // ~2025-03-26 08:37:21 UTC + id: 101, + code: 0x1, // AlarmSet + status: 1, // Error + logstampSec: 1740284241 + }, + { + sender: "CDPLoggerDemoApp.CPDEventNotification", + data: { + Text: "CDP event notice" + }, + timestampSec: 1740284167, // ~2025-03-26 08:36:07 + id: 102, + code: 0, // None + status: 3, // Notify + logstampSec: 1740284167 + }, + { + sender: "CPDLoggerDemoApp", + data: { + Text: "A component is suspended" + }, + timestampSec: 1740284145, // ~2025-03-26 08:35:45 + id: 103, + code: 0x1, // AlarmSet + status: 1, // Error + logstampSec: 1740284145 + }, + { + sender: "CPDLoggerDemoApp", + data: { + Text: "Component was suspended" + }, + timestampSec: 1740284090, // ~2025-03-26 08:34:50 + id: 104, + code: 0, // None + status: 2, // Warning + logstampSec: 1740284090 + } + ] + } + }; +} + module.exports = { createApiVersionResponse, createApiVersionErrorResponse, @@ -108,5 +164,6 @@ module.exports = { createLoggedNodesResponse, createDataPointResponse, createErrorResponse, + createRealisticEventsResponse, // Export our new function Container }; From a6746e32d6475e64004a2a20089c38a11bcb1f8e Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Wed, 26 Mar 2025 13:04:45 +0200 Subject: [PATCH 13/37] Added getEventCodeString method --- client.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/client.js b/client.js index 9278e76..e470f53 100644 --- a/client.js +++ b/client.js @@ -242,9 +242,9 @@ class Client { const requestId = this._getRequestId(); // Convert the simple query into a proper EventQuery message. const eventQuery = this._buildEventQuery(query); - - + + if (!this.isOpen) { this.queuedRequests[requestId] = { type: "events", query: eventQuery }; } else { @@ -305,7 +305,7 @@ class Client { for (const key in query.dataConditions) { const val = query.dataConditions[key]; const conditions = []; - + if (Array.isArray(val)) { for (const item of val) { conditions.push({ @@ -319,7 +319,7 @@ class Client { type: MatchType.Exact }); } - + // Store without any table qualification dataConds[key] = { conditions }; } @@ -328,10 +328,10 @@ class Client { return EventQuery.create(baseQuery); } - - - + + + /** * Converts a numeric CDP event code into a descriptive string. @@ -363,6 +363,51 @@ class Client { return flags.join(" + "); } + /** + * Returns a human‐readable string for a given event code. + * + * @param {number} code - The numeric event code. + * @returns {string} - The corresponding event code string. + */ + getEventCodeString(code) { + // Return empty string if eventCode is zero + if (code === 0) return ""; + + // Define the flag values (adjust these constants if needed) + const EventCodeFlags = { + AlarmSet: 0x1, + AlarmClr: 0x2, + AlarmAck: 0x4, + AlarmReprise: 0x40 + }; + + // Check for specific combinations first + if (code === EventCodeFlags.AlarmSet) return "AlarmSet"; + if (code === EventCodeFlags.AlarmClr) return "AlarmClear"; + if (code === EventCodeFlags.AlarmAck) return "Ack"; + if (code === EventCodeFlags.AlarmReprise) return "Reprise"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmSet)) + return "RepriseAlarmSet"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmClr)) + return "RepriseAlarmClear"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmAck)) + return "RepriseAck"; + + // Otherwise, combine the flag strings based on which bits are set. + let s = ""; + if (code & EventCodeFlags.AlarmReprise) + s += (s ? "+" : "") + "Reprise"; + if (code & EventCodeFlags.AlarmSet) + s += (s ? "+" : "") + "AlarmSet"; + if (code & EventCodeFlags.AlarmClr) + s += (s ? "+" : "") + "AlarmClear"; + if (code & EventCodeFlags.AlarmAck) + s += (s ? "+" : "") + "Ack"; + + return s; + } + + _handleMessage(ws, message) { const data = Container.decode(new Uint8Array(message)); this._parseMessage(data); From 44133d497cbaf4c17fa1afbbf1b126926138a798 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Wed, 26 Mar 2025 13:13:23 +0200 Subject: [PATCH 14/37] Fixed comments --- client.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client.js b/client.js index e470f53..c2ab1fb 100644 --- a/client.js +++ b/client.js @@ -207,6 +207,10 @@ class Client { * 2 = TimeRangeBeginExclusive * 4 = TimeRangeEndExclusive * 8 = UseLogStampForTimeRange + * + * For additional information: + * https://cdpstudio.com/manual/cdp/cdp2sql/logmanager-eventquery.html#Flags-enum + * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#cdp-event-code-flags * * In addition, the user can simply supply the following properties in the query object: * @@ -218,9 +222,6 @@ class Client { * - `value`: the string value to match, * - `matchType`: either `"exact"` (default) or `"wildcard"`. * - * The helper method `_buildEventQuery(query)` converts this simple plain object into a proper - * `DBMessaging.Protobuf.EventQuery` message. - * * enum EventQuery::MatchType: * - Exact (0): The string must match exactly. * - Wildcard (1): The string may contain wildcards. From e912ad4984387f413324cc41c3527936558a92bd Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 27 Mar 2025 09:58:53 +0200 Subject: [PATCH 15/37] Match type added and restructuring client.js --- client.js | 558 +++++++++++++++++++++++++++++----------------- examples/event.js | 21 +- 2 files changed, 364 insertions(+), 215 deletions(-) diff --git a/client.js b/client.js index c2ab1fb..0060aac 100644 --- a/client.js +++ b/client.js @@ -1,16 +1,22 @@ -// client.js const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; const CDPValueType = root.ICD.Protobuf.CDPValueType; /** - * A client for interacting with CDP Logger or LogServer via WebSocket. + * A client for interacting with a CDP Logger or LogServer via WebSocket. + * + * This client handles: + * - Automatic reconnection (if enabled) + * - Requesting and parsing responses for version, logged nodes, log limits, data points, and events + * - Time synchronization between the client and the server */ class Client { /** - * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000") - * @param {boolean} [autoReconnect=true] - Automatically reconnect if the connection is lost + * Create a new Client instance to communicate with the logger. + * + * @param {string} endpoint - The logger endpoint (e.g. "127.0.0.1:17000" or "ws://127.0.0.1:17000"). + * @param {boolean} [autoReconnect=true] - Whether to automatically reconnect if the connection is lost. */ constructor(endpoint, autoReconnect = true) { // If endpoint does not start with "ws://" or "wss://", prepend "ws://" @@ -44,12 +50,14 @@ class Client { } /** - * Enable or disable time synchronization. + * Enable or disable time synchronization with the server. * - * Note: - * Time sync is triggered on-demand (e.g., with the next request) or after a timeout. - * Re-enabling time sync will automatically sync on the next operation. - * For immediate sync, call `_updateTimeDiff()` explicitly. + * When enabled, the client automatically requests and calculates the time offset + * (`timeDiff`) between the client and server to align timestamps. This can help + * ensure data queries (e.g., requestDataPoints, requestEvents) are aligned with + * the server's notion of time. Re-enabling time sync triggers a new offset + * calculation on the next request or after a timeout. For an immediate sync, + * call `_updateTimeDiff()` explicitly. * * @param {boolean} enable - True to enable, false to disable time sync. */ @@ -64,50 +72,13 @@ class Client { } } - _connect(url) { - const ws = new WebSocket(url); - ws._url = url; - ws.binaryType = 'arraybuffer'; - ws.onopen = () => this._onOpen(ws); - ws.onmessage = (event) => this._handleMessage(ws, event.data); - ws.onerror = (error) => this._onError(ws, error); - ws.onclose = () => this._onClose(ws); - return ws; - } - - _onOpen(ws) { - this.isOpen = true; - if (this.enableTimeSync) { - this._updateTimeDiff(); - } - this.lastTimeRequest = Date.now() / 1000; - } - - _onError(ws, error) { - if (!error) { - error = new Error("Something went wrong"); - } - if (!this.autoReconnect) { - for (const key in this.storedPromises) { - this.storedPromises[key].reject(error); - } - this.storedPromises = {}; - this.queuedRequests = {}; - } - } - - _onClose(ws) { - this.isOpen = false; - if (!this.autoReconnect) { - this._onError(ws, new Error("Connection was closed")); - } else { - // Try to reconnect after a delay - setTimeout(() => { - this.ws = this._connect(ws._url); - }, 1000); - } - } - + /** + * Disconnect from the server, closing the WebSocket connection. + * + * This also disables auto-reconnect and clears any queued or pending requests. + * After calling `disconnect()`, you can create a new Client instance to + * re-establish a connection. + */ disconnect() { this.autoReconnect = false; this._cleanupQueuedRequests(); @@ -117,18 +88,18 @@ class Client { } } - _cleanupQueuedRequests() { - for (const key in this.storedPromises) { - this.storedPromises[key].reject(new Error("Connection was closed")); - } - this.storedPromises = {}; - this.queuedRequests = {}; - } - // --- Public API methods --- /** - * Request the API version. + * Request the API version from the connected CDP Logger or LogServer. + * + * In CDP Studio, this corresponds to the version of the CDP runtime + * or the logger server that you are connecting to. The version can be used + * to ensure compatibility with certain features. + * + * @returns {Promise} A promise that resolves with the version string + * (e.g., "4.5.2"). If the version is below 3.0, the promise is rejected with + * an error indicating an incompatible version. */ requestApiVersion() { this._timeRequest(); @@ -145,6 +116,18 @@ class Client { /** * Request the list of logged nodes. + * + * In CDP Studio, this corresponds to the "LoggedValues" table of the + * CDPLogger (or LogServer) component. The returned list includes node + * names, paths, and any associated tags that might be assigned to + * those nodes. + * + * @returns {Promise} A promise that resolves with an array of + * node objects. Each object includes: + * - `name` (string): The node name + * - `routing` (string): The node path + * - `tags` (object): Optional key/value pairs providing additional + * node metadata */ requestLoggedNodes() { this._timeRequest(); @@ -160,7 +143,15 @@ class Client { } /** - * Request the log limits. + * Request the log limits (start and end times of available data). + * + * In CDP Studio, this corresponds to the earliest and latest times + * for which log data is available in the CDPLogger (or LogServer). + * + * @returns {Promise} A promise that resolves with an object + * containing: + * - `startS` (number): The earliest available timestamp (in seconds). + * - `endS` (number): The latest available timestamp (in seconds). */ requestLogLimits() { this._timeRequest(); @@ -176,12 +167,22 @@ class Client { } /** - * Request data points for given node names and time range. - * @param {Array} nodeNames - * @param {number} startS - * @param {number} endS - * @param {number} noOfDataPoints - * @returns {Promise} + * Request data points for the specified node names over a given time range. + * + * In CDP Studio, this retrieves time-series data from the logged nodes + * (CDP signals) in the specified range. The number of data points is + * adjustable, allowing for either raw or decimated data. + * + * @param {Array} nodeNames - The names of the nodes/signals to retrieve. + * @param {number} startS - The start time (in seconds since epoch). + * @param {number} endS - The end time (in seconds since epoch). + * @param {number} noOfDataPoints - The maximum number of data points to retrieve. + * @returns {Promise} A promise that resolves with an array of objects, + * where each object has: + * - `timestamp` (number): The time (in seconds) for the data row. + * - `value` (object): A key-value mapping of node names to an object with + * `min`, `max`, and `last` properties representing the node's values + * at that timestamp. */ requestDataPoints(nodeNames, startS, endS, noOfDataPoints) { this._timeRequest(); @@ -200,43 +201,32 @@ class Client { /** * Request events based on the provided query parameters. * - * The `query.flags` field uses bitmask values similar to an enum: + * In CDP Studio, this corresponds to event log queries for the + * CDPLogger (or LogServer). The query parameters allow filtering by + * sender, data fields, code masks, and time ranges, among others. * + * The `query.flags` field uses bitmask values similar to an enum: * 0 = None * 1 = NewestFirst * 2 = TimeRangeBeginExclusive * 4 = TimeRangeEndExclusive * 8 = UseLogStampForTimeRange * - * For additional information: + * For additional information: * https://cdpstudio.com/manual/cdp/cdp2sql/logmanager-eventquery.html#Flags-enum * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#cdp-event-code-flags * - * In addition, the user can simply supply the following properties in the query object: - * - * - **senderConditions**: An array of sender strings (exact matches by default). - * - **dataConditions**: An object where each key is a data field name and the value can be: - * - A string (defaults to an exact match), - * - An array of strings, - * - An object (or array of objects) with properties: - * - `value`: the string value to match, - * - `matchType`: either `"exact"` (default) or `"wildcard"`. - * - * enum EventQuery::MatchType: - * - Exact (0): The string must match exactly. - * - Wildcard (1): The string may contain wildcards. - * * Example usage: - * * // Filter for events with sender exactly "CDPLoggerDemoApp.InvalidLicense": * { senderConditions: ["CDPLoggerDemoApp.InvalidLicense"] } * * // Filter for events where the "Text" data field equals "Invalid or missing feature license detected.": * { dataConditions: { "Text": "Invalid or missing feature license detected." } } * - * * @param {Object} query - A simple plain object representing the EventQuery. - * @returns {Promise} Resolves with an array of events (each event includes a 'codeDescription'). + * @returns {Promise} Resolves with an array of events (each event + * includes a `codeDescription` which provides a textual representation + * of the event code). */ requestEvents(query) { this._timeRequest(); @@ -244,8 +234,6 @@ class Client { // Convert the simple query into a proper EventQuery message. const eventQuery = this._buildEventQuery(query); - - if (!this.isOpen) { this.queuedRequests[requestId] = { type: "events", query: eventQuery }; } else { @@ -256,87 +244,9 @@ class Client { }); } - // --- Internal methods --- - - _sendEventsRequest(requestId, query) { - const container = Container.create(); - container.messageType = Container.Type.eEventsRequest; - container.eventsRequest = { requestId, query }; - const buffer = Container.encode(container).finish(); - this.ws.send(buffer); - } - - /** - * Helper method to build a proper EventQuery message from a simple plain object. - * - * - * - * - * @param {Object} query - The simple plain object query. - * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. - */ - _buildEventQuery(query) { - const root = require('./generated/containerPb.js'); - const { EventQuery } = root.DBMessaging.Protobuf; - const { MatchType } = EventQuery; - - // Create base query with primitive fields - const baseQuery = { - timeRangeBegin: query.timeRangeBegin || 0, - timeRangeEnd: query.timeRangeEnd || Math.floor(Date.now() / 1000), - codeMask: query.codeMask !== undefined ? query.codeMask : 0xFFFFFFFF, - limit: query.limit || 50, - offset: query.offset || 0, - flags: query.flags || 0 - }; - - // Build sender conditions if present - if (query.senders && query.senders.length > 0) { - baseQuery.senderConditions = { - conditions: query.senders.map(sender => ({ - value: sender, - type: MatchType.Exact - })) - }; - } - - // Build data conditions if present - if (query.dataConditions) { - const dataConds = {}; - for (const key in query.dataConditions) { - const val = query.dataConditions[key]; - const conditions = []; - - if (Array.isArray(val)) { - for (const item of val) { - conditions.push({ - value: String(item), - type: MatchType.Exact - }); - } - } else { - conditions.push({ - value: String(val), - type: MatchType.Exact - }); - } - - // Store without any table qualification - dataConds[key] = { conditions }; - } - baseQuery.dataConditions = dataConds; - } - - return EventQuery.create(baseQuery); - } - - - - - /** - * Converts a numeric CDP event code into a descriptive string. - * Multiple flags can be set simultaneously, so we combine them. + * Converts a numeric CDP event code into a descriptive string, + * combining multiple flags if needed. * * Common codes (from the docs): * 0x1 = AlarmSet @@ -347,7 +257,8 @@ class Client { * 0x40000000 = NodeBoot * * @param {number} code - The event code from an eEventsResponse. - * @returns {string} - A human-readable combination of flags. + * @returns {string} - A human-readable combination of flags, + * such as "AlarmSet + SourceObjectUnavailable". */ getEventCodeDescription(code) { const flags = []; @@ -364,50 +275,112 @@ class Client { return flags.join(" + "); } - /** +/** * Returns a human‐readable string for a given event code. + * If multiple flags are set, it attempts to identify known + * combinations; otherwise, it combines them with a plus sign. * * @param {number} code - The numeric event code. * @returns {string} - The corresponding event code string. */ - getEventCodeString(code) { - // Return empty string if eventCode is zero - if (code === 0) return ""; - - // Define the flag values (adjust these constants if needed) - const EventCodeFlags = { - AlarmSet: 0x1, - AlarmClr: 0x2, - AlarmAck: 0x4, - AlarmReprise: 0x40 - }; +getEventCodeString(code) { + // Return empty string if eventCode is zero + if (code === 0) return ""; + + // Define the flag values + const EventCodeFlags = { + AlarmSet: 0x1, + AlarmClr: 0x2, + AlarmAck: 0x4, + AlarmReprise: 0x40, + SourceObjectUnavailable: 0x100, + NodeBoot: 0x40000000 + }; + + // Check for specific single-flag codes or two-flag combos + if (code === EventCodeFlags.AlarmSet) return "AlarmSet"; + if (code === EventCodeFlags.AlarmClr) return "AlarmClear"; + if (code === EventCodeFlags.AlarmAck) return "Ack"; + if (code === EventCodeFlags.AlarmReprise) return "Reprise"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmSet)) + return "RepriseAlarmSet"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmClr)) + return "RepriseAlarmClear"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmAck)) + return "RepriseAck"; + + // Otherwise, combine the flag strings based on which bits are set + let s = ""; + if (code & EventCodeFlags.AlarmReprise) + s += (s ? "+" : "") + "Reprise"; + if (code & EventCodeFlags.AlarmSet) + s += (s ? "+" : "") + "AlarmSet"; + if (code & EventCodeFlags.AlarmClr) + s += (s ? "+" : "") + "AlarmClear"; + if (code & EventCodeFlags.AlarmAck) + s += (s ? "+" : "") + "Ack"; + if (code & EventCodeFlags.NodeBoot) + s += (s ? "+" : "") + "EventNodeBoot"; + if (code & EventCodeFlags.SourceObjectUnavailable) + s += (s ? "+" : "") + "SourceObjectUnavailable"; + + return s; +} - // Check for specific combinations first - if (code === EventCodeFlags.AlarmSet) return "AlarmSet"; - if (code === EventCodeFlags.AlarmClr) return "AlarmClear"; - if (code === EventCodeFlags.AlarmAck) return "Ack"; - if (code === EventCodeFlags.AlarmReprise) return "Reprise"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmSet)) - return "RepriseAlarmSet"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmClr)) - return "RepriseAlarmClear"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmAck)) - return "RepriseAck"; - - // Otherwise, combine the flag strings based on which bits are set. - let s = ""; - if (code & EventCodeFlags.AlarmReprise) - s += (s ? "+" : "") + "Reprise"; - if (code & EventCodeFlags.AlarmSet) - s += (s ? "+" : "") + "AlarmSet"; - if (code & EventCodeFlags.AlarmClr) - s += (s ? "+" : "") + "AlarmClear"; - if (code & EventCodeFlags.AlarmAck) - s += (s ? "+" : "") + "Ack"; - - return s; + + // --- Internal methods --- + + _connect(url) { + const ws = new WebSocket(url); + ws._url = url; + ws.binaryType = 'arraybuffer'; + ws.onopen = () => this._onOpen(ws); + ws.onmessage = (event) => this._handleMessage(ws, event.data); + ws.onerror = (error) => this._onError(ws, error); + ws.onclose = () => this._onClose(ws); + return ws; } + _onOpen(ws) { + this.isOpen = true; + if (this.enableTimeSync) { + this._updateTimeDiff(); + } + this.lastTimeRequest = Date.now() / 1000; + } + + _onError(ws, error) { + if (!error) { + error = new Error("Something went wrong"); + } + if (!this.autoReconnect) { + for (const key in this.storedPromises) { + this.storedPromises[key].reject(error); + } + this.storedPromises = {}; + this.queuedRequests = {}; + } + } + + _onClose(ws) { + this.isOpen = false; + if (!this.autoReconnect) { + this._onError(ws, new Error("Connection was closed")); + } else { + // Try to reconnect after a delay + setTimeout(() => { + this.ws = this._connect(ws._url); + }, 1000); + } + } + + _cleanupQueuedRequests() { + for (const key in this.storedPromises) { + this.storedPromises[key].reject(new Error("Connection was closed")); + } + this.storedPromises = {}; + this.queuedRequests = {}; + } _handleMessage(ws, message) { const data = Container.decode(new Uint8Array(message)); @@ -768,6 +741,177 @@ class Client { const buffer = Container.encode(container).finish(); this.ws.send(buffer); } + + _sendEventsRequest(requestId, query) { + const container = Container.create(); + container.messageType = Container.Type.eEventsRequest; + container.eventsRequest = { requestId, query }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + +/** + * Helper method to validate the event query object. + * + * Allowed keys: + * - timeRangeBegin (number) + * - timeRangeEnd (number) + * - limit (number) + * - offset (number) + * - codeMask (number) + * - flags (number) + * - senderConditions (array) + * - dataConditions (object) + * + * @param {Object} query - The event query object provided by the user. + * @throws {Error} If the query contains invalid property names or incorrect types. + */ +_validateEventQuery(query) { + const allowedKeys = { + timeRangeBegin: 'number', + timeRangeEnd: 'number', + limit: 'number', + offset: 'number', + codeMask: 'number', + flags: 'number', + senderConditions: 'array', + dataConditions: 'object' + }; + + Object.keys(query).forEach(key => { + if (!allowedKeys.hasOwnProperty(key)) { + throw new Error( + `Invalid property "${key}" in event query. Allowed properties are: ${Object.keys(allowedKeys).join(', ')}.` + ); + } + const expectedType = allowedKeys[key]; + if (expectedType === 'number' && typeof query[key] !== 'number') { + throw new Error(`Property "${key}" must be a number.`); + } + if (expectedType === 'array' && !Array.isArray(query[key])) { + throw new Error(`Property "${key}" must be an array.`); + } + if (expectedType === 'object' && (typeof query[key] !== 'object' || query[key] === null || Array.isArray(query[key]))) { + throw new Error(`Property "${key}" must be an object.`); + } + }); +} + +/** + * Helper method to build a proper EventQuery message from a simple plain object. + * + * The returned `EventQuery` is used by `requestEvents()` to query + * the CDPLogger or LogServer for matching events. + * + * @param {Object} query - The simple plain object query. + * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. + * @throws {Error} If a condition object is missing required properties. + */ +_buildEventQuery(query) { + // Validate the query object before building the EventQuery. + this._validateEventQuery(query); + + const root = require('./generated/containerPb.js'); + const { EventQuery } = root.DBMessaging.Protobuf; + const { MatchType } = EventQuery; + + // Conditionally include these fields only if the user has set them + const optionalFields = [ + "timeRangeBegin", + "timeRangeEnd", + "codeMask", + "limit", + "offset", + "flags" + ]; + + // Build a base query object that includes only the fields provided + const baseQuery = {}; + optionalFields.forEach(field => { + if (query[field] !== undefined) { + baseQuery[field] = query[field]; + } + }); + + // Build senderConditions if present + if (query.senderConditions && query.senderConditions.length > 0) { + baseQuery.senderConditions = { + conditions: query.senderConditions.map(condition => { + // Validate that condition is either a plain string or an object with a "value" property. + if (typeof condition === 'object' && condition !== null) { + if (!('value' in condition)) { + throw new Error( + `Sender condition object must include a 'value' property. Received: ${JSON.stringify(condition)}` + ); + } + return { + value: String(condition.value), + type: condition.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact + }; + } else { + return { + value: condition, + type: MatchType.Exact + }; + } + }) + }; + } + + // Build data conditions if present + if (query.dataConditions) { + const dataConds = {}; + for (const key in query.dataConditions) { + const val = query.dataConditions[key]; + const conditions = []; + + if (Array.isArray(val)) { + for (const item of val) { + if (typeof item === 'object' && item !== null) { + if (!('value' in item)) { + throw new Error( + `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(item)}` + ); + } + conditions.push({ + value: String(item.value), + type: item.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact + }); + } else { + conditions.push({ + value: String(item), + type: MatchType.Exact + }); + } + } + } else if (typeof val === 'object' && val !== null) { + if (!('value' in val)) { + throw new Error( + `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(val)}` + ); + } + conditions.push({ + value: String(val.value), + type: val.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact + }); + } else { + conditions.push({ + value: String(val), + type: MatchType.Exact + }); + } + + dataConds[key] = { conditions }; + } + baseQuery.dataConditions = dataConds; + } + + return EventQuery.create(baseQuery); +} + + + } module.exports = Client; diff --git a/examples/event.js b/examples/event.js index 4802edd..fe1ce28 100644 --- a/examples/event.js +++ b/examples/event.js @@ -1,8 +1,6 @@ // event.js // An example script to see filtered events - const Client = require('../client'); -const root = require('../generated/containerPb'); async function main() { const client = new Client('ws://127.0.0.1:17000', false); @@ -12,15 +10,22 @@ async function main() { await new Promise(resolve => setTimeout(resolve, 2000)); const query = { - timeRangeBegin: Math.floor(Date.now() / 1000) - (24 * 60 * 60), // Last 24 hours - timeRangeEnd: Math.floor(Date.now() / 1000), - limit: 50, - offset: 0, - senderConditions: ["CDPLoggerDemoApp.CDP.CDPEngine"], + senderConditions: [ + { + value: "CDPLoggerDemoApp.I*", // Wildcard pattern for sender + matchType: "wildcard" + } + ], dataConditions: { - "Text": "Component CDPLoggerDemoApp.Sine has been suspended" + "Text": { + value: "*", + matchType: "wildcard" + } } }; + + + console.log("Sending event query..."); console.log("Query:", JSON.stringify(query, null, 2)); From bdd29eef691ae981f079f0238eecc766872b8dd9 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Mon, 31 Mar 2025 12:07:36 +0300 Subject: [PATCH 16/37] Changed documentation and added objects: EventQueryFlags and MatchType --- client.js | 482 ++++++++++++++++++++++++++-------------------- examples/event.js | 10 +- 2 files changed, 276 insertions(+), 216 deletions(-) diff --git a/client.js b/client.js index 0060aac..c51effa 100644 --- a/client.js +++ b/client.js @@ -12,6 +12,20 @@ const CDPValueType = root.ICD.Protobuf.CDPValueType; * - Time synchronization between the client and the server */ class Client { + // Defined property names to use instead of ambiguous numbers. + static EventQueryFlags = Object.freeze({ + None: 0, // Client.EventQueryFlags.None === 0 + NewestFirst: 1, + TimeRangeBeginExclusive: 2, + TimeRangeEndExclusive: 4, + UseLogStampForTimeRange: 8 + }); + + static MatchType = Object.freeze({ + Exact: 0, + Wildcard: 1 + }); + /** * Create a new Client instance to communicate with the logger. * @@ -97,6 +111,22 @@ class Client { * or the logger server that you are connecting to. The version can be used * to ensure compatibility with certain features. * + * Version History: + * - 3.0 (2017-08, CDP 4.3): Minimum supported version. + * - 3.1 (2020-08, CDP 4.9): + * - Support for reading full resolution data by setting num_of_datapoints to 0. + * - Added a limit argument to SignalDataRequest (behaves like SQL LIMIT, where 0 means no limit). + * - The server now notifies of dropped queries by returning a TooManyRequests error + * when too many pending requests exist. + * - 3.2 (2022-11, CDP 4.11): Limits queries to 50,000 rows to avoid overloading the logger app; + * larger data sets should be downloaded in patches. + * - 4.0 (2024-01, CDP 4.12): + * - Added NodeTag support to save custom tags for logged values (e.g. Unit or Description), + * accessible through the NodeInfo struct and TagMap protobuf message. + * - Reduced network usage on the built-in server by having SignalDataResponse + * only include changes instead of repeating unchanged values. + * - Added support for string values and events. + * * @returns {Promise} A promise that resolves with the version string * (e.g., "4.5.2"). If the version is below 3.0, the promise is rejected with * an error indicating an incompatible version. @@ -118,7 +148,7 @@ class Client { * Request the list of logged nodes. * * In CDP Studio, this corresponds to the "LoggedValues" table of the - * CDPLogger (or LogServer) component. The returned list includes node + * CDPLogger component. The returned list includes node * names, paths, and any associated tags that might be assigned to * those nodes. * @@ -169,20 +199,27 @@ class Client { /** * Request data points for the specified node names over a given time range. * - * In CDP Studio, this retrieves time-series data from the logged nodes - * (CDP signals) in the specified range. The number of data points is + * This retrieves time-series data from the logged nodes + * (CDP signals, arguments, properties and other value nodes) in the specified range. The number of data points is * adjustable, allowing for either raw or decimated data. * * @param {Array} nodeNames - The names of the nodes/signals to retrieve. * @param {number} startS - The start time (in seconds since epoch). * @param {number} endS - The end time (in seconds since epoch). * @param {number} noOfDataPoints - The maximum number of data points to retrieve. + * - If you specify a nonzero value, the server will decimate or downsample + * the data to roughly that many points across [startS..endS]. + * - If you set it to 0, the server returns the data at full resolution + * (i.e., no decimation). * @returns {Promise} A promise that resolves with an array of objects, * where each object has: * - `timestamp` (number): The time (in seconds) for the data row. * - `value` (object): A key-value mapping of node names to an object with * `min`, `max`, and `last` properties representing the node's values * at that timestamp. + * @param {number} limit - Similar to SQL LIMIT. It allows to request data + * in batches by setting the maximum batch size (the number of samples). + * Note, reading data in larger batches will improve performance but also allocate more memory. */ requestDataPoints(nodeNames, startS, endS, noOfDataPoints) { this._timeRequest(); @@ -224,9 +261,20 @@ class Client { * { dataConditions: { "Text": "Invalid or missing feature license detected." } } * * @param {Object} query - A simple plain object representing the EventQuery. - * @returns {Promise} Resolves with an array of events (each event - * includes a `codeDescription` which provides a textual representation - * of the event code). + * @returns {Promise} Resolves with an array of event objects. + * + * Each event object typically includes the following fields: + * - `sender` (string): The event sender. + * - `data` (object): An object containing event-specific details: + * - `Text` (string): The event text message. + * - `Level` (string): The event level (e.g., "ERROR"). + * - `Description` (string): A detailed description of the event. + * - `Group` (string): A group identifier for the event. + * - `timestampSec` (number): The timestamp (in seconds) when the event occurred. + * - `id` (string): A unique identifier for the event. + * - `code` (number): The raw event code returned by the server. + * - `status` (number): The status code associated with the event. + * - `logstampSec` (number): The log timestamp (in seconds) when the event was logged. */ requestEvents(query) { this._timeRequest(); @@ -275,57 +323,57 @@ class Client { return flags.join(" + "); } -/** - * Returns a human‐readable string for a given event code. - * If multiple flags are set, it attempts to identify known - * combinations; otherwise, it combines them with a plus sign. - * - * @param {number} code - The numeric event code. - * @returns {string} - The corresponding event code string. - */ -getEventCodeString(code) { - // Return empty string if eventCode is zero - if (code === 0) return ""; - - // Define the flag values - const EventCodeFlags = { - AlarmSet: 0x1, - AlarmClr: 0x2, - AlarmAck: 0x4, - AlarmReprise: 0x40, - SourceObjectUnavailable: 0x100, - NodeBoot: 0x40000000 - }; - - // Check for specific single-flag codes or two-flag combos - if (code === EventCodeFlags.AlarmSet) return "AlarmSet"; - if (code === EventCodeFlags.AlarmClr) return "AlarmClear"; - if (code === EventCodeFlags.AlarmAck) return "Ack"; - if (code === EventCodeFlags.AlarmReprise) return "Reprise"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmSet)) - return "RepriseAlarmSet"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmClr)) - return "RepriseAlarmClear"; - if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmAck)) - return "RepriseAck"; - - // Otherwise, combine the flag strings based on which bits are set - let s = ""; - if (code & EventCodeFlags.AlarmReprise) - s += (s ? "+" : "") + "Reprise"; - if (code & EventCodeFlags.AlarmSet) - s += (s ? "+" : "") + "AlarmSet"; - if (code & EventCodeFlags.AlarmClr) - s += (s ? "+" : "") + "AlarmClear"; - if (code & EventCodeFlags.AlarmAck) - s += (s ? "+" : "") + "Ack"; - if (code & EventCodeFlags.NodeBoot) - s += (s ? "+" : "") + "EventNodeBoot"; - if (code & EventCodeFlags.SourceObjectUnavailable) - s += (s ? "+" : "") + "SourceObjectUnavailable"; - - return s; -} + /** + * Returns a human‐readable string for a given event code. + * If multiple flags are set, it attempts to identify known + * combinations; otherwise, it combines them with a plus sign. + * + * @param {number} code - The numeric event code. + * @returns {string} - The corresponding event code string. + */ + getEventCodeString(code) { + // Return empty string if eventCode is zero + if (code === 0) return ""; + + // Define the flag values + const EventCodeFlags = { + AlarmSet: 0x1, + AlarmClr: 0x2, + AlarmAck: 0x4, + AlarmReprise: 0x40, + SourceObjectUnavailable: 0x100, + NodeBoot: 0x40000000 + }; + + // Check for specific single-flag codes or two-flag combos + if (code === EventCodeFlags.AlarmSet) return "AlarmSet"; + if (code === EventCodeFlags.AlarmClr) return "AlarmClear"; + if (code === EventCodeFlags.AlarmAck) return "Ack"; + if (code === EventCodeFlags.AlarmReprise) return "Reprise"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmSet)) + return "RepriseAlarmSet"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmClr)) + return "RepriseAlarmClear"; + if (code === (EventCodeFlags.AlarmReprise | EventCodeFlags.AlarmAck)) + return "RepriseAck"; + + // Otherwise, combine the flag strings based on which bits are set + let s = ""; + if (code & EventCodeFlags.AlarmReprise) + s += (s ? "+" : "") + "Reprise"; + if (code & EventCodeFlags.AlarmSet) + s += (s ? "+" : "") + "AlarmSet"; + if (code & EventCodeFlags.AlarmClr) + s += (s ? "+" : "") + "AlarmClear"; + if (code & EventCodeFlags.AlarmAck) + s += (s ? "+" : "") + "Ack"; + if (code & EventCodeFlags.NodeBoot) + s += (s ? "+" : "") + "EventNodeBoot"; + if (code & EventCodeFlags.SourceObjectUnavailable) + s += (s ? "+" : "") + "SourceObjectUnavailable"; + + return s; + } // --- Internal methods --- @@ -535,15 +583,26 @@ getEventCodeString(code) { const value = {}; for (let i = 0; i < signalNames.length; i++) { const signalType = this.nameToType[signalNames[i]] || CDPValueType.eDOUBLE; - value[signalNames[i]] = { - min: this._valueFromVariant(minValues[i], signalType), - max: this._valueFromVariant(maxValues[i], signalType), - last: this._valueFromVariant(lastValues[i], signalType) - }; + if (minValues.length === 0 || maxValues.length === 0) { + // Server does not send min and max when they are equal to last + const last = this._valueFromVariant(lastValues[i], signalType); + value[signalNames[i]] = { + min: last, + max: last, + last: last + }; + } else { + value[signalNames[i]] = { + min: this._valueFromVariant(minValues[i], signalType), + max: this._valueFromVariant(maxValues[i], signalType), + last: this._valueFromVariant(lastValues[i], signalType) + }; + } } return value; } + _valueFromVariant(variant, type) { if (!variant) return null; switch (type) { @@ -751,167 +810,168 @@ getEventCodeString(code) { } -/** - * Helper method to validate the event query object. - * - * Allowed keys: - * - timeRangeBegin (number) - * - timeRangeEnd (number) - * - limit (number) - * - offset (number) - * - codeMask (number) - * - flags (number) - * - senderConditions (array) - * - dataConditions (object) - * - * @param {Object} query - The event query object provided by the user. - * @throws {Error} If the query contains invalid property names or incorrect types. - */ -_validateEventQuery(query) { - const allowedKeys = { - timeRangeBegin: 'number', - timeRangeEnd: 'number', - limit: 'number', - offset: 'number', - codeMask: 'number', - flags: 'number', - senderConditions: 'array', - dataConditions: 'object' - }; - - Object.keys(query).forEach(key => { - if (!allowedKeys.hasOwnProperty(key)) { - throw new Error( - `Invalid property "${key}" in event query. Allowed properties are: ${Object.keys(allowedKeys).join(', ')}.` - ); - } - const expectedType = allowedKeys[key]; - if (expectedType === 'number' && typeof query[key] !== 'number') { - throw new Error(`Property "${key}" must be a number.`); - } - if (expectedType === 'array' && !Array.isArray(query[key])) { - throw new Error(`Property "${key}" must be an array.`); - } - if (expectedType === 'object' && (typeof query[key] !== 'object' || query[key] === null || Array.isArray(query[key]))) { - throw new Error(`Property "${key}" must be an object.`); - } - }); -} - -/** - * Helper method to build a proper EventQuery message from a simple plain object. - * - * The returned `EventQuery` is used by `requestEvents()` to query - * the CDPLogger or LogServer for matching events. - * - * @param {Object} query - The simple plain object query. - * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. - * @throws {Error} If a condition object is missing required properties. - */ -_buildEventQuery(query) { - // Validate the query object before building the EventQuery. - this._validateEventQuery(query); - - const root = require('./generated/containerPb.js'); - const { EventQuery } = root.DBMessaging.Protobuf; - const { MatchType } = EventQuery; - - // Conditionally include these fields only if the user has set them - const optionalFields = [ - "timeRangeBegin", - "timeRangeEnd", - "codeMask", - "limit", - "offset", - "flags" - ]; - - // Build a base query object that includes only the fields provided - const baseQuery = {}; - optionalFields.forEach(field => { - if (query[field] !== undefined) { - baseQuery[field] = query[field]; - } - }); - - // Build senderConditions if present - if (query.senderConditions && query.senderConditions.length > 0) { - baseQuery.senderConditions = { - conditions: query.senderConditions.map(condition => { - // Validate that condition is either a plain string or an object with a "value" property. - if (typeof condition === 'object' && condition !== null) { - if (!('value' in condition)) { - throw new Error( - `Sender condition object must include a 'value' property. Received: ${JSON.stringify(condition)}` - ); - } - return { - value: String(condition.value), - type: condition.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact - }; - } else { - return { - value: condition, - type: MatchType.Exact - }; - } - }) + /** + * Helper method to validate the event query object. + * + * Allowed keys: + * - timeRangeBegin (number) + * - timeRangeEnd (number) + * - limit (number) + * - offset (number) + * - codeMask (number) + * - flags (number) + * - senderConditions (array) + * - dataConditions (object) + * + * @param {Object} query - The event query object provided by the user. + * @throws {Error} If the query contains invalid property names or incorrect types. + */ + _validateEventQuery(query) { + const allowedKeys = { + timeRangeBegin: 'number', + timeRangeEnd: 'number', + limit: 'number', + offset: 'number', + codeMask: 'number', + flags: 'number', + senderConditions: 'array', + dataConditions: 'object' }; - } - // Build data conditions if present - if (query.dataConditions) { - const dataConds = {}; - for (const key in query.dataConditions) { - const val = query.dataConditions[key]; - const conditions = []; + Object.keys(query).forEach(key => { + if (!allowedKeys.hasOwnProperty(key)) { + throw new Error( + `Invalid property "${key}" in event query. Allowed properties are: ${Object.keys(allowedKeys).join(', ')}.` + ); + } + const expectedType = allowedKeys[key]; + if (expectedType === 'number' && typeof query[key] !== 'number') { + throw new Error(`Property "${key}" must be a number.`); + } + if (expectedType === 'array' && !Array.isArray(query[key])) { + throw new Error(`Property "${key}" must be an array.`); + } + if (expectedType === 'object' && (typeof query[key] !== 'object' || query[key] === null || Array.isArray(query[key]))) { + throw new Error(`Property "${key}" must be an object.`); + } + }); + } - if (Array.isArray(val)) { - for (const item of val) { - if (typeof item === 'object' && item !== null) { - if (!('value' in item)) { + /** + * Helper method to build a proper EventQuery message from a simple plain object. + * + * The returned `EventQuery` is used by `requestEvents()` to query + * the CDPLogger or LogServer for matching events. + * + * @param {Object} query - The simple plain object query. + * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. + * @throws {Error} If a condition object is missing required properties. + */ + _buildEventQuery(query) { + // Validate the query object before building the EventQuery. + this._validateEventQuery(query); + + const root = require('./generated/containerPb.js'); + const { EventQuery } = root.DBMessaging.Protobuf; + + // Conditionally include these fields only if the user has set them + const optionalFields = [ + "timeRangeBegin", + "timeRangeEnd", + "codeMask", + "limit", + "offset", + "flags" + ]; + + // Build a base query object that includes only the fields provided + const baseQuery = {}; + optionalFields.forEach(field => { + if (query[field] !== undefined) { + baseQuery[field] = query[field]; + } + }); + + // Build senderConditions if present + if (query.senderConditions && query.senderConditions.length > 0) { + baseQuery.senderConditions = { + conditions: query.senderConditions.map(condition => { + if (typeof condition === 'object' && condition !== null) { + if (!('value' in condition)) { throw new Error( - `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(item)}` + `Sender condition object must include a 'value' property. Received: ${JSON.stringify(condition)}` ); } - conditions.push({ - value: String(item.value), - type: item.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact - }); + return { + value: String(condition.value), + type: condition.matchType !== undefined + ? condition.matchType + : Client.MatchType.Wildcard + }; } else { - conditions.push({ - value: String(item), - type: MatchType.Exact - }); + return { + value: condition, + type: Client.MatchType.Wildcard + }; } + }) + }; + } + + // Build data conditions if present + if (query.dataConditions) { + const dataConds = {}; + for (const key in query.dataConditions) { + const val = query.dataConditions[key]; + const conditions = []; + + if (Array.isArray(val)) { + for (const item of val) { + if (typeof item === 'object' && item !== null) { + if (!('value' in item)) { + throw new Error( + `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(item)}` + ); + } + conditions.push({ + value: String(item.value), + type: item.matchType !== undefined + ? item.matchType + : Client.MatchType.Wildcard + }); + } else { + conditions.push({ + value: String(item), + type: Client.MatchType.Wildcard + }); + } + } + } else if (typeof val === 'object' && val !== null) { + if (!('value' in val)) { + throw new Error( + `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(val)}` + ); + } + conditions.push({ + value: String(val.value), + type: val.matchType !== undefined + ? val.matchType + : Client.MatchType.Wildcard + }); + } else { + conditions.push({ + value: String(val), + type: Client.MatchType.Wildcard + }); } - } else if (typeof val === 'object' && val !== null) { - if (!('value' in val)) { - throw new Error( - `Data condition for key "${key}" must include a 'value' property. Received: ${JSON.stringify(val)}` - ); - } - conditions.push({ - value: String(val.value), - type: val.matchType === "wildcard" ? MatchType.Wildcard : MatchType.Exact - }); - } else { - conditions.push({ - value: String(val), - type: MatchType.Exact - }); + + dataConds[key] = { conditions }; } - - dataConds[key] = { conditions }; + baseQuery.dataConditions = dataConds; } - baseQuery.dataConditions = dataConds; + + return EventQuery.create(baseQuery); } - - return EventQuery.create(baseQuery); -} - - - } module.exports = Client; diff --git a/examples/event.js b/examples/event.js index fe1ce28..d09e7cc 100644 --- a/examples/event.js +++ b/examples/event.js @@ -12,16 +12,16 @@ async function main() { const query = { senderConditions: [ { - value: "CDPLoggerDemoApp.I*", // Wildcard pattern for sender - matchType: "wildcard" + value: "CDPLoggerDemoApp.InvalidLicense", + matchType: Client.MatchType.Exact } ], dataConditions: { "Text": { - value: "*", - matchType: "wildcard" + value: "*", // Default Wildcard } - } + }, + flags: Client.EventQueryFlags.NewestFirst | Client.EventQueryFlags.UseLogStampForTimeRange, }; From 0a7c4f1ec05d0003906af4d570cb0c01a61b556e Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Mon, 31 Mar 2025 12:08:55 +0300 Subject: [PATCH 17/37] Formatting --- client.js | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/client.js b/client.js index c51effa..b6e3dcf 100644 --- a/client.js +++ b/client.js @@ -112,21 +112,21 @@ class Client { * to ensure compatibility with certain features. * * Version History: - * - 3.0 (2017-08, CDP 4.3): Minimum supported version. - * - 3.1 (2020-08, CDP 4.9): - * - Support for reading full resolution data by setting num_of_datapoints to 0. - * - Added a limit argument to SignalDataRequest (behaves like SQL LIMIT, where 0 means no limit). - * - The server now notifies of dropped queries by returning a TooManyRequests error - * when too many pending requests exist. - * - 3.2 (2022-11, CDP 4.11): Limits queries to 50,000 rows to avoid overloading the logger app; - * larger data sets should be downloaded in patches. - * - 4.0 (2024-01, CDP 4.12): - * - Added NodeTag support to save custom tags for logged values (e.g. Unit or Description), - * accessible through the NodeInfo struct and TagMap protobuf message. - * - Reduced network usage on the built-in server by having SignalDataResponse - * only include changes instead of repeating unchanged values. - * - Added support for string values and events. - * + * - 3.0 (2017-08, CDP 4.3): Minimum supported version. + * - 3.1 (2020-08, CDP 4.9): + * - Support for reading full resolution data by setting num_of_datapoints to 0. + * - Added a limit argument to SignalDataRequest (behaves like SQL LIMIT, where 0 means no limit). + * - The server now notifies of dropped queries by returning a TooManyRequests error + * when too many pending requests exist. + * - 3.2 (2022-11, CDP 4.11): Limits queries to 50,000 rows to avoid overloading the logger app; + * larger data sets should be downloaded in patches. + * - 4.0 (2024-01, CDP 4.12): + * - Added NodeTag support to save custom tags for logged values (e.g. Unit or Description), + * accessible through the NodeInfo struct and TagMap protobuf message. + * - Reduced network usage on the built-in server by having SignalDataResponse + * only include changes instead of repeating unchanged values. + * - Added support for string values and events. + * * @returns {Promise} A promise that resolves with the version string * (e.g., "4.5.2"). If the version is below 3.0, the promise is rejected with * an error indicating an incompatible version. @@ -870,10 +870,10 @@ class Client { _buildEventQuery(query) { // Validate the query object before building the EventQuery. this._validateEventQuery(query); - + const root = require('./generated/containerPb.js'); const { EventQuery } = root.DBMessaging.Protobuf; - + // Conditionally include these fields only if the user has set them const optionalFields = [ "timeRangeBegin", @@ -883,7 +883,7 @@ class Client { "offset", "flags" ]; - + // Build a base query object that includes only the fields provided const baseQuery = {}; optionalFields.forEach(field => { @@ -891,7 +891,7 @@ class Client { baseQuery[field] = query[field]; } }); - + // Build senderConditions if present if (query.senderConditions && query.senderConditions.length > 0) { baseQuery.senderConditions = { @@ -917,14 +917,14 @@ class Client { }) }; } - + // Build data conditions if present if (query.dataConditions) { const dataConds = {}; for (const key in query.dataConditions) { const val = query.dataConditions[key]; const conditions = []; - + if (Array.isArray(val)) { for (const item of val) { if (typeof item === 'object' && item !== null) { @@ -964,12 +964,12 @@ class Client { type: Client.MatchType.Wildcard }); } - + dataConds[key] = { conditions }; } baseQuery.dataConditions = dataConds; } - + return EventQuery.create(baseQuery); } } From 65116302f696a36be288a1124b8184c6a7eca271 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Tue, 1 Apr 2025 11:08:11 +0300 Subject: [PATCH 18/37] Added Event Tags support and Count Events --- README.md | 1 - client.js | 238 +++++++++++++++++++++++++++++++++++++--------- examples/event.js | 21 ++-- 3 files changed, 207 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 74a985c..1041b51 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. For more information about CDP Studio see https://cdpstudio.com/. - ## Installation Clone the repository and install dependencies: diff --git a/client.js b/client.js index b6e3dcf..6c35154 100644 --- a/client.js +++ b/client.js @@ -38,30 +38,35 @@ class Client { if (!/^wss?:\/\//.test(url)) { url = `ws://${url}`; } - + this.reqId = -1; this.autoReconnect = autoReconnect; this.enableTimeSync = true; // Time synchronization is enabled by default. - + this.isOpen = false; this.queuedRequests = {}; this.storedPromises = {}; this.nameToId = {}; this.idToName = {}; - + // Mapping for signal types (in case we need to interpret values). this.nameToType = {}; - + // Time-diff related this.timeDiff = 0; this.timeReceived = null; this.lastTimeRequest = Date.now() / 1000; this.haveSentQueuedReq = false; this.roundTripTimes = {}; - + + // Initialize the cache for sender tags and pending tag requests. + this.senderTags = {}; // Cache for event sender tags (keyed by sender) + this.pendingSenderTags = {}; // Holds pending promises for sender tags + // Create the WebSocket connection this.ws = this._connect(url); } + /** * Enable or disable time synchronization with the server. @@ -114,17 +119,16 @@ class Client { * Version History: * - 3.0 (2017-08, CDP 4.3): Minimum supported version. * - 3.1 (2020-08, CDP 4.9): - * - Support for reading full resolution data by setting num_of_datapoints to 0. - * - Added a limit argument to SignalDataRequest (behaves like SQL LIMIT, where 0 means no limit). + * - Support for reading full resolution data by setting noOfDataPoints to 0. + * - Added a limit argument to data point requests (behaves like SQL LIMIT, where 0 means no limit). * - The server now notifies of dropped queries by returning a TooManyRequests error * when too many pending requests exist. * - 3.2 (2022-11, CDP 4.11): Limits queries to 50,000 rows to avoid overloading the logger app; * larger data sets should be downloaded in patches. * - 4.0 (2024-01, CDP 4.12): * - Added NodeTag support to save custom tags for logged values (e.g. Unit or Description), - * accessible through the NodeInfo struct and TagMap protobuf message. - * - Reduced network usage on the built-in server by having SignalDataResponse - * only include changes instead of repeating unchanged values. + * accessible via the client’s API. + * - Reduced network usage by having data responses only include changes instead of repeating unchanged values. * - Added support for string values and events. * * @returns {Promise} A promise that resolves with the version string @@ -211,26 +215,26 @@ class Client { * the data to roughly that many points across [startS..endS]. * - If you set it to 0, the server returns the data at full resolution * (i.e., no decimation). + * @param {number} limit - Similar to SQL LIMIT. It allows you to request data + * in batches by setting the maximum batch size (the number of samples). + * Note, reading data in larger batches will improve performance but also allocate more memory. * @returns {Promise} A promise that resolves with an array of objects, * where each object has: * - `timestamp` (number): The time (in seconds) for the data row. * - `value` (object): A key-value mapping of node names to an object with * `min`, `max`, and `last` properties representing the node's values * at that timestamp. - * @param {number} limit - Similar to SQL LIMIT. It allows to request data - * in batches by setting the maximum batch size (the number of samples). - * Note, reading data in larger batches will improve performance but also allocate more memory. */ - requestDataPoints(nodeNames, startS, endS, noOfDataPoints) { + requestDataPoints(nodeNames, startS, endS, noOfDataPoints, limit) { this._timeRequest(); const requestId = this._getRequestId(); const promise = new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; }); if (!this.isOpen) { - this.queuedRequests[requestId] = ["node_values", nodeNames, startS, endS, noOfDataPoints]; + this.queuedRequests[requestId] = ["node_values", nodeNames, startS, endS, noOfDataPoints, limit]; } else { - this._reqDataPoints(nodeNames, startS, endS, noOfDataPoints, requestId); + this._reqDataPoints(nodeNames, startS, endS, noOfDataPoints, limit, requestId); } return promise; } @@ -253,15 +257,15 @@ class Client { * https://cdpstudio.com/manual/cdp/cdp2sql/logmanager-eventquery.html#Flags-enum * https://cdpstudio.com/manual/cdp/cdplogger/eventlogreader.html#cdp-event-code-flags * - * Example usage: - * // Filter for events with sender exactly "CDPLoggerDemoApp.InvalidLicense": - * { senderConditions: ["CDPLoggerDemoApp.InvalidLicense"] } - * - * // Filter for events where the "Text" data field equals "Invalid or missing feature license detected.": - * { dataConditions: { "Text": "Invalid or missing feature license detected." } } - * - * @param {Object} query - A simple plain object representing the EventQuery. - * @returns {Promise} Resolves with an array of event objects. + * Allowed query keys: + * - timeRangeBegin (number) + * - timeRangeEnd (number) + * - limit (number) + * - offset (number) + * - codeMask (number) + * - flags (number) + * - senderConditions (array) + * - dataConditions (object) * * Each event object typically includes the following fields: * - `sender` (string): The event sender. @@ -275,17 +279,78 @@ class Client { * - `code` (number): The raw event code returned by the server. * - `status` (number): The status code associated with the event. * - `logstampSec` (number): The log timestamp (in seconds) when the event was logged. + * + * Example usage: + * client.requestEvents({ + * timeRangeBegin: 1609459200, + * timeRangeEnd: 1609545600, + * senderConditions: ["CDPLoggerDemoApp.InvalidLicense"], + * dataConditions: { + * Text: ["Invalid or missing feature license detected."], + * // Multiple data conditions can be specified: + * Level: { value: "ERROR", matchType: Client.MatchType.Exact } + * }, + * limit: 100, + * offset: 0, + * flags: Client.EventQueryFlags.NewestFirst + * }); + * + * @param {Object} query - A simple plain object representing the EventQuery. + * @returns {Promise} Resolves with an array of event objects. + */ +// Modified requestEvents() to wait for missing sender tag info. +requestEvents(query) { + this._timeRequest(); + const requestId = this._getRequestId(); + const eventQuery = this._buildEventQuery(query); + if (!this.isOpen) { + this.queuedRequests[requestId] = { type: "events", query: eventQuery }; + } else { + this._sendEventsRequest(requestId, eventQuery); + } + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }) + .then(events => { + // Collect the unique sender names from events that lack cached tags. + const missingSenders = Array.from(new Set( + events + .filter(evt => !this.senderTags[evt.sender]) + .map(evt => evt.sender) + )); + + if (missingSenders.length === 0) { + return events; + } + // Request tag info for all missing senders. + return Promise.all( + missingSenders.map(sender => this.getSenderTags(sender)) + ).then(() => { + // Attach tags to events after tag info is available. + events.forEach(evt => { + evt.tags = this.senderTags[evt.sender]; + }); + return events; + }); + }); +} + + /** + * Request a count of events that match the given query. + * + * The query object accepts the same keys as in requestEvents(). + * + * @param {Object} query - The event query object. + * @returns {Promise} A promise that resolves with the count of events. */ - requestEvents(query) { + countEvents(query) { this._timeRequest(); const requestId = this._getRequestId(); - // Convert the simple query into a proper EventQuery message. const eventQuery = this._buildEventQuery(query); - if (!this.isOpen) { - this.queuedRequests[requestId] = { type: "events", query: eventQuery }; + this.queuedRequests[requestId] = { type: "countEvents", query: eventQuery }; } else { - this._sendEventsRequest(requestId, eventQuery); + this._sendCountEventsRequest(requestId, eventQuery); } return new Promise((resolve, reject) => { this.storedPromises[requestId] = { resolve, reject }; @@ -304,7 +369,7 @@ class Client { * 0x100 = SourceObjectUnavailable * 0x40000000 = NodeBoot * - * @param {number} code - The event code from an eEventsResponse. + * @param {number} code - The event code from an events response. * @returns {string} - A human-readable combination of flags, * such as "AlarmSet + SourceObjectUnavailable". */ @@ -332,10 +397,7 @@ class Client { * @returns {string} - The corresponding event code string. */ getEventCodeString(code) { - // Return empty string if eventCode is zero if (code === 0) return ""; - - // Define the flag values const EventCodeFlags = { AlarmSet: 0x1, AlarmClr: 0x2, @@ -375,6 +437,40 @@ class Client { return s; } +/** + * Retrieves the tags associated with a given sender. + * + * This method checks if the tags for the specified sender are already cached. If so, it returns a + * resolved promise with the cached tags. Otherwise, it initializes a pending promise for the sender, + * sends a request for the sender's tags using `_sendEventSenderTagsRequest`, and returns a promise that + * resolves when the tags are received. If no response is received within 5000 ms, it falls back to resolving + * with an empty object. + * + * @param {string} sender - The identifier of the event sender. + * @returns {Promise} A promise that resolves with an object representing the tags for the sender. + */ + getSenderTags(sender) { + if (this.senderTags && this.senderTags[sender]) { + return Promise.resolve(this.senderTags[sender]); + } + // If no pending promise for this sender, initialize one and trigger a request. + if (!this.pendingSenderTags[sender]) { + this.pendingSenderTags[sender] = []; + this._sendEventSenderTagsRequest(sender); + } + return new Promise(resolve => { + this.pendingSenderTags[sender].push(resolve); + // Increase timeout to 5000 ms to wait longer for tag info. + setTimeout(() => { + if (this.pendingSenderTags[sender]) { + this.senderTags[sender] = {}; // Fallback to empty object. + this.pendingSenderTags[sender].forEach(fn => fn({})); + delete this.pendingSenderTags[sender]; + } + }, 5000); + }); + } + // --- Internal methods --- @@ -550,6 +646,14 @@ class Client { if (data.eventsResponse.events && data.eventsResponse.events.length > 0) { data.eventsResponse.events.forEach(evt => { evt.codeDescription = this.getEventCodeDescription(evt.code); + // If we already have cached tags for this sender, attach them; + // otherwise, request them. + if (this.senderTags && this.senderTags[evt.sender]) { + evt.tags = this.senderTags[evt.sender]; + } else { + // Request sender tags asynchronously. + this._sendEventSenderTagsRequest(evt.sender); + } }); } if (this.storedPromises[data.eventsResponse.requestId]) { @@ -559,7 +663,33 @@ class Client { } break; } + + case Container.Type.eCountEventsResponse: { + if (this.storedPromises[data.countEventsResponse.requestId]) { + const { resolve } = this.storedPromises[data.countEventsResponse.requestId]; + delete this.storedPromises[data.countEventsResponse.requestId]; + resolve(data.countEventsResponse.count); + } + break; + } + + case Container.Type.eEventSenderTagsResponse: { + // Get the mapping of sender names to TagMap objects. + const tagsMapping = data.eventSenderTagsResponse.senderTags; + // Iterate over each sender in the mapping. + for (const sender in tagsMapping) { + const tags = this._convertTagMap(tagsMapping[sender]); + this.senderTags[sender] = tags; + // Resolve any pending promises waiting for tags for this sender. + if (this.pendingSenderTags[sender]) { + this.pendingSenderTags[sender].forEach(resolveFn => resolveFn(tags)); + delete this.pendingSenderTags[sender]; + } + } + break; + } + default: console.error("Unknown message type", data.messageType); } @@ -567,10 +697,10 @@ class Client { _convertTagMap(tagMapObj) { const result = {}; - if (!tagMapObj || !tagMapObj.tags) { - return result; - } - for (const [tagKey, tagInfo] of Object.entries(tagMapObj.tags)) { + if (!tagMapObj) return result; + // If the tag map is nested under 'tags', use that; otherwise, use tagMapObj directly. + const entries = tagMapObj.tags || tagMapObj; + for (const [tagKey, tagInfo] of Object.entries(entries)) { result[tagKey] = { value: tagInfo.value, source: tagInfo.source @@ -602,7 +732,6 @@ class Client { return value; } - _valueFromVariant(variant, type) { if (!variant) return null; switch (type) { @@ -643,7 +772,7 @@ class Client { } else if (req === "log_limits") { this._sendLogLimitsRequest(requestId); } else if (Array.isArray(req) && req[0] === "node_values") { - this._reqDataPoints(req[1], req[2], req[3], req[4], requestId); + this._reqDataPoints(req[1], req[2], req[3], req[4], req[5], requestId); } else if (req === "api_version") { this._sendApiVersionRequest(requestId); } else if (req && req.type === "events") { @@ -735,9 +864,9 @@ class Client { this.ws.send(buffer); } - _reqDataPoints(nodeNames, startS, endS, noOfDataPoints, requestId) { + _reqDataPoints(nodeNames, startS, endS, noOfDataPoints, limit, requestId) { const _getDataPoints = (nodeIds) => { - this._sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints); + this._sendDataPointsRequest(nodeIds, startS, endS, requestId, limit, noOfDataPoints); }; const rejectRequest = (error) => { @@ -779,12 +908,13 @@ class Client { }); } - _sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints) { + _sendDataPointsRequest(nodeIds, startS, endS, requestId, limit, noOfDataPoints) { const container = Container.create(); container.messageType = Container.Type.eSignalDataRequest; container.signalDataRequest = { requestId, signalId: nodeIds, + limit, numOfDatapoints: noOfDataPoints, criterionMin: this.enableTimeSync ? (startS - this.timeDiff) : startS, criterionMax: this.enableTimeSync ? (endS - this.timeDiff) : endS @@ -809,6 +939,22 @@ class Client { this.ws.send(buffer); } + _sendCountEventsRequest(requestId, query) { + const container = Container.create(); + container.messageType = Container.Type.eCountEventsRequest; + container.countEventsRequest = { requestId, query }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } + + _sendEventSenderTagsRequest(sender) { + const container = Container.create(); + container.messageType = Container.Type.eEventSenderTagsRequest; + // Use a new requestId so the server can reply with a proper EventSenderTagsResponse. + container.eventSenderTagsRequest = { requestId: this._getRequestId(), sender }; + const buffer = Container.encode(container).finish(); + this.ws.send(buffer); + } /** * Helper method to validate the event query object. @@ -858,13 +1004,13 @@ class Client { } /** - * Helper method to build a proper EventQuery message from a simple plain object. + * Helper method to build a proper EventQuery object from a simple plain object. * - * The returned `EventQuery` is used by `requestEvents()` to query + * The returned query object is used by `requestEvents()` to query * the CDPLogger or LogServer for matching events. * * @param {Object} query - The simple plain object query. - * @returns {DBMessaging.Protobuf.EventQuery} - The built EventQuery message. + * @returns {DBMessaging.Protobuf.EventQuery} - The structured EventQuery. * @throws {Error} If a condition object is missing required properties. */ _buildEventQuery(query) { diff --git a/examples/event.js b/examples/event.js index d09e7cc..e3eda89 100644 --- a/examples/event.js +++ b/examples/event.js @@ -1,5 +1,6 @@ // event.js // An example script to see filtered events + const Client = require('../client'); async function main() { @@ -7,8 +8,10 @@ async function main() { try { console.log("Waiting for connection to establish..."); + // Wait a bit to allow the connection to be established await new Promise(resolve => setTimeout(resolve, 2000)); + // Build the query with a limit and offset const query = { senderConditions: [ { @@ -18,15 +21,18 @@ async function main() { ], dataConditions: { "Text": { - value: "*", // Default Wildcard + value: "*", // Wildcard condition for Text field } }, - flags: Client.EventQueryFlags.NewestFirst | Client.EventQueryFlags.UseLogStampForTimeRange, + flags: Client.EventQueryFlags.NewestFirst | Client.EventQueryFlags.UseLogStampForTimeRange, + limit: 10, // Request a maximum of 10 events + offset: 0 // Starting at the beginning }; - - - + console.log("Counting matching events..."); + const totalCount = await client.countEvents(query); + console.log(`Total matching events count: ${totalCount}`); + console.log("Sending event query..."); console.log("Query:", JSON.stringify(query, null, 2)); @@ -36,11 +42,14 @@ async function main() { if (events.length > 0) { console.log('\nEvents:'); events.forEach(event => { + // If event.data is a string, parse it; otherwise assume it's already an object. const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data; console.log(JSON.stringify({ timestamp: event.timestampSec, sender: event.sender, - data: data + data: data, + // The event tags will be attached (or requested if not yet available) + tags: event.tags }, null, 2)); }); } From 1b3465a3462add6da07e8803650671252691f17d Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Tue, 1 Apr 2025 15:13:14 +0300 Subject: [PATCH 19/37] Added tests and fake data related to Event Tags --- client.js | 147 ++++++++++++++-------------- test/client.test.js | 226 +++++++++++++++++++++++++++++++------------- test/fakeData.js | 41 +++++--- 3 files changed, 259 insertions(+), 155 deletions(-) diff --git a/client.js b/client.js index 6c35154..d275d71 100644 --- a/client.js +++ b/client.js @@ -38,35 +38,35 @@ class Client { if (!/^wss?:\/\//.test(url)) { url = `ws://${url}`; } - + this.reqId = -1; this.autoReconnect = autoReconnect; this.enableTimeSync = true; // Time synchronization is enabled by default. - + this.isOpen = false; this.queuedRequests = {}; this.storedPromises = {}; this.nameToId = {}; this.idToName = {}; - + // Mapping for signal types (in case we need to interpret values). this.nameToType = {}; - + // Time-diff related this.timeDiff = 0; this.timeReceived = null; this.lastTimeRequest = Date.now() / 1000; this.haveSentQueuedReq = false; this.roundTripTimes = {}; - + // Initialize the cache for sender tags and pending tag requests. this.senderTags = {}; // Cache for event sender tags (keyed by sender) this.pendingSenderTags = {}; // Holds pending promises for sender tags - + // Create the WebSocket connection this.ws = this._connect(url); } - + /** * Enable or disable time synchronization with the server. @@ -298,42 +298,42 @@ class Client { * @param {Object} query - A simple plain object representing the EventQuery. * @returns {Promise} Resolves with an array of event objects. */ -// Modified requestEvents() to wait for missing sender tag info. -requestEvents(query) { - this._timeRequest(); - const requestId = this._getRequestId(); - const eventQuery = this._buildEventQuery(query); - if (!this.isOpen) { - this.queuedRequests[requestId] = { type: "events", query: eventQuery }; - } else { - this._sendEventsRequest(requestId, eventQuery); - } - return new Promise((resolve, reject) => { - this.storedPromises[requestId] = { resolve, reject }; - }) - .then(events => { - // Collect the unique sender names from events that lack cached tags. - const missingSenders = Array.from(new Set( - events - .filter(evt => !this.senderTags[evt.sender]) - .map(evt => evt.sender) - )); - - if (missingSenders.length === 0) { - return events; + // Modified requestEvents() to wait for missing sender tag info. + requestEvents(query) { + this._timeRequest(); + const requestId = this._getRequestId(); + const eventQuery = this._buildEventQuery(query); + if (!this.isOpen) { + this.queuedRequests[requestId] = { type: "events", query: eventQuery }; + } else { + this._sendEventsRequest(requestId, eventQuery); } - // Request tag info for all missing senders. - return Promise.all( - missingSenders.map(sender => this.getSenderTags(sender)) - ).then(() => { - // Attach tags to events after tag info is available. - events.forEach(evt => { - evt.tags = this.senderTags[evt.sender]; + return new Promise((resolve, reject) => { + this.storedPromises[requestId] = { resolve, reject }; + }) + .then(events => { + // Collect the unique sender names from events that lack cached tags. + const missingSenders = Array.from(new Set( + events + .filter(evt => !this.senderTags[evt.sender]) + .map(evt => evt.sender) + )); + + if (missingSenders.length === 0) { + return events; + } + // Request tag info for all missing senders. + return Promise.all( + missingSenders.map(sender => this.getSenderTags(sender)) + ).then(() => { + // Attach tags to events after tag info is available. + events.forEach(evt => { + evt.tags = this.senderTags[evt.sender]; + }); + return events; + }); }); - return events; - }); - }); -} + } /** * Request a count of events that match the given query. @@ -437,18 +437,18 @@ requestEvents(query) { return s; } -/** - * Retrieves the tags associated with a given sender. - * - * This method checks if the tags for the specified sender are already cached. If so, it returns a - * resolved promise with the cached tags. Otherwise, it initializes a pending promise for the sender, - * sends a request for the sender's tags using `_sendEventSenderTagsRequest`, and returns a promise that - * resolves when the tags are received. If no response is received within 5000 ms, it falls back to resolving - * with an empty object. - * - * @param {string} sender - The identifier of the event sender. - * @returns {Promise} A promise that resolves with an object representing the tags for the sender. - */ + /** + * Retrieves the tags associated with a given sender. + * + * This method checks if the tags for the specified sender are already cached. If so, it returns a + * resolved promise with the cached tags. Otherwise, it initializes a pending promise for the sender, + * sends a request for the sender's tags using `_sendEventSenderTagsRequest`, and returns a promise that + * resolves when the tags are received. If no response is received within 5000 ms, it falls back to resolving + * with an empty object. + * + * @param {string} sender - The identifier of the event sender. + * @returns {Promise} A promise that resolves with an object representing the tags for the sender. + */ getSenderTags(sender) { if (this.senderTags && this.senderTags[sender]) { return Promise.resolve(this.senderTags[sender]); @@ -458,16 +458,8 @@ requestEvents(query) { this.pendingSenderTags[sender] = []; this._sendEventSenderTagsRequest(sender); } - return new Promise(resolve => { - this.pendingSenderTags[sender].push(resolve); - // Increase timeout to 5000 ms to wait longer for tag info. - setTimeout(() => { - if (this.pendingSenderTags[sender]) { - this.senderTags[sender] = {}; // Fallback to empty object. - this.pendingSenderTags[sender].forEach(fn => fn({})); - delete this.pendingSenderTags[sender]; - } - }, 5000); + return new Promise((resolve, reject) => { + this.pendingSenderTags[sender].push({ resolve, reject }); }); } @@ -497,14 +489,20 @@ requestEvents(query) { if (!error) { error = new Error("Something went wrong"); } - if (!this.autoReconnect) { - for (const key in this.storedPromises) { - this.storedPromises[key].reject(error); - } - this.storedPromises = {}; - this.queuedRequests = {}; + // Reject all stored promises. + for (const key in this.storedPromises) { + this.storedPromises[key].reject(error); + } + this.storedPromises = {}; + this.queuedRequests = {}; + + // Reject any pending sender tag promises. + for (const sender in this.pendingSenderTags) { + this.pendingSenderTags[sender].forEach(promiseObj => promiseObj.reject(error)); + delete this.pendingSenderTags[sender]; } } + _onClose(ws) { this.isOpen = false; @@ -663,7 +661,7 @@ requestEvents(query) { } break; } - + case Container.Type.eCountEventsResponse: { if (this.storedPromises[data.countEventsResponse.requestId]) { @@ -673,7 +671,7 @@ requestEvents(query) { } break; } - + case Container.Type.eEventSenderTagsResponse: { // Get the mapping of sender names to TagMap objects. const tagsMapping = data.eventSenderTagsResponse.senderTags; @@ -683,13 +681,14 @@ requestEvents(query) { this.senderTags[sender] = tags; // Resolve any pending promises waiting for tags for this sender. if (this.pendingSenderTags[sender]) { - this.pendingSenderTags[sender].forEach(resolveFn => resolveFn(tags)); + this.pendingSenderTags[sender].forEach(promiseObj => promiseObj.resolve(tags)); delete this.pendingSenderTags[sender]; } } break; } - + + default: console.error("Unknown message type", data.messageType); } @@ -945,7 +944,7 @@ requestEvents(query) { container.countEventsRequest = { requestId, query }; const buffer = Container.encode(container).finish(); this.ws.send(buffer); - } + } _sendEventSenderTagsRequest(sender) { const container = Container.create(); diff --git a/test/client.test.js b/test/client.test.js index 5c879c5..ad52133 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -6,7 +6,7 @@ const fakeData = require('./fakeData'); describe('ClientTester', () => { let client; beforeEach(() => { - // Override _connect to return a fake ws object that doesn't try to connect. + // Override _connect to return a fake ws object that doesn't actually connect. Client.prototype._connect = function(url) { return { _url: url, @@ -14,13 +14,17 @@ describe('ClientTester', () => { send: jest.fn() }; }; - // Create a new client instance using two parameters: endpoint and autoReconnect. + // Create a new client instance. client = new Client('127.0.0.1:17000', true); - // Adjust the client’s lastTimeRequest so that a new time request will be triggered. + // By default, disable time sync for most tests. + client.setEnableTimeSync(false); + // Adjust lastTimeRequest so that a new time request would normally be triggered. client.lastTimeRequest = Date.now() / 1000 - 11; - // Prepopulate the lookup maps. + // Prepopulate lookup maps. client.idToName = { 0: "Output", 1: "CPULoad" }; client.nameToId = { "Output": 0, "CPULoad": 1 }; + // Reset reqId so expected request IDs are predictable. + client.reqId = 0; }); afterEach(() => { @@ -46,55 +50,76 @@ describe('ClientTester', () => { }); test('test_time_request', () => { + // Enable time sync for this test. + client.setEnableTimeSync(true); client.isOpen = true; client._sendTimeRequest = jest.fn(); client._timeRequest(); - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + expect(client._sendTimeRequest).toHaveBeenCalledWith(expect.any(Number)); }); test('test_version_request_also_sends_time_request', () => { + client.reqId = 0; + client.setEnableTimeSync(false); client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendApiVersionRequest = jest.fn(); client.requestApiVersion(); - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); + // With time sync disabled, only _sendApiVersionRequest is called. expect(client._sendApiVersionRequest).toHaveBeenCalledWith(1); }); test('test_log_limits_request_also_sends_time_request', () => { + client.reqId = 0; + client.setEnableTimeSync(false); client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits(); - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); expect(client._sendLogLimitsRequest).toHaveBeenCalledWith(1); }); test('test_logged_nodes_request_also_sends_time_request', () => { + client.reqId = 0; + client.setEnableTimeSync(false); client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendLoggedNodesRequest = jest.fn(); client.requestLoggedNodes(); - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); expect(client._sendLoggedNodesRequest).toHaveBeenCalledWith(1); }); test('test_data_points_request_also_sends_time_request', done => { + // Enable time sync for this test. + client.setEnableTimeSync(true); + client.reqId = 0; client.isOpen = true; client._sendTimeRequest = jest.fn(); client._sendDataPointsRequest = jest.fn(); - client.requestDataPoints(["Output", "CPULoad"], 1530613239.0, 1530613270.0, 500); - // Wait a tick for the promise chain to complete. + // Call with five explicit parameters: nodeNames, startS, endS, noOfDataPoints, limit. + client.requestDataPoints(["Output", "CPULoad"], 1530613239.0, 1530613270.0, 0, 500); + // Simulate a time response for the time request. + const timeResponse = { + messageType: fakeData.Container.Type.eTimeResponse, + timeResponse: { requestId: 1, timestamp: 1e9 } + }; + client._parseMessage(timeResponse); + // Simulate a data points response. + client._parseMessage(fakeData.createDataPointResponse()); setImmediate(() => { - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); - expect(client._sendDataPointsRequest).toHaveBeenCalledWith([0, 1], 1530613239.0, 1530613270.0, 1, 500); + expect(client._sendTimeRequest).toHaveBeenCalledWith(1); + expect(client._sendDataPointsRequest).toHaveBeenCalledWith( + [0, 1], + 1530613239.0, + 1530613270.0, + 2, // The second call's requestId + 500, // limit + 0 // noOfDataPoints + ); done(); }); }); test('test_version_request', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendApiVersionRequest = jest.fn(); client.requestApiVersion() .then(version => { @@ -102,14 +127,13 @@ describe('ClientTester', () => { done(); }) .catch(done.fail); - // Simulate a valid API version response. const response = fakeData.createApiVersionResponse(); client._parseMessage(response); }); test('test_version_request_error', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendApiVersionRequest = jest.fn(); client.requestApiVersion() .then(() => done.fail("Promise should not resolve")) @@ -117,14 +141,13 @@ describe('ClientTester', () => { expect(err).toBeInstanceOf(Error); done(); }); - // Simulate an API version error (version too low). const response = fakeData.createApiVersionErrorResponse(); client._parseMessage(response); }); test('test_log_limits_request', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { @@ -138,9 +161,12 @@ describe('ClientTester', () => { }); test('test_log_limits_request_with_time_diff', done => { + // Enable time sync and override _timeRequest to avoid triggering an extra time request. + client.setEnableTimeSync(true); + client._timeRequest = jest.fn(); client.timeDiff = 10; + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .then(limits => { @@ -154,8 +180,8 @@ describe('ClientTester', () => { }); test('test_logged_nodes_request', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendLoggedNodesRequest = jest.fn(); client.requestLoggedNodes() .then(nodes => { @@ -169,10 +195,10 @@ describe('ClientTester', () => { }); test('test_data_points_request', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendDataPointsRequest = jest.fn(); - client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 0, 500) .then(dataPoints => { expect(dataPoints[0].timestamp).toBeCloseTo(1531313250.0); expect(dataPoints[0].value["Output"].min).toBeCloseTo(0.638855091434); @@ -186,25 +212,20 @@ describe('ClientTester', () => { }); test('test_data_points_request_error_on_names', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); - client._sendLoggedNodesRequest = jest.fn(); - - // Remove "Output" so that the lookup fails. delete client.nameToId["Output"]; for (const id in client.idToName) { if (client.idToName[id] === "Output") { delete client.idToName[id]; } } - - client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500) + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 0, 500) .catch(error => { expect(error).toBeInstanceOf(Error); expect(error.message).toMatch(/Output/); done(); }); - // Simulate a logged nodes response that does NOT include "Output". const response = { messageType: fakeData.Container.Type.eSignalInfoResponse, signalInfoResponse: { @@ -223,9 +244,8 @@ describe('ClientTester', () => { }); test('test_error_response_on_log_limits_request', done => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); - client._sendLogLimitsRequest = jest.fn(); client.requestLogLimits() .catch(error => { expect(error).toBeInstanceOf(Error); @@ -236,12 +256,10 @@ describe('ClientTester', () => { client._parseMessage(response); }); - // Updated test for events with conditions using expected query structure. test('test_events_request_with_conditions', () => { + client.reqId = 0; client.isOpen = true; - client._sendTimeRequest = jest.fn(); client._sendEventsRequest = jest.fn(); - const queryWithConditions = { timeRangeBegin: 1000, timeRangeEnd: 2000, @@ -254,18 +272,12 @@ describe('ClientTester', () => { "Text": "Component was suspended!" } }; - client.requestEvents(queryWithConditions); - // Expect _sendTimeRequest to have been called first with id 0. - expect(client._sendTimeRequest).toHaveBeenCalledWith(0); - // Build the expected query using _buildEventQuery. - const builtQuery = client._buildEventQuery(queryWithConditions); - expect(client._sendEventsRequest).toHaveBeenCalledWith(1, builtQuery); + expect(client._sendEventsRequest).toHaveBeenCalledWith(1, client._buildEventQuery(queryWithConditions)); }); - // Updated test for events with no known flags (code=0 => "None") test('test_event_code_description_none', done => { - client.isOpen = true; + client.reqId = 0; client.requestEvents({}) .then(events => { expect(events).toHaveLength(1); @@ -274,7 +286,6 @@ describe('ClientTester', () => { done(); }) .catch(done.fail); - const response = { messageType: fakeData.Container.Type.eEventsResponse, eventsResponse: { @@ -293,20 +304,20 @@ describe('ClientTester', () => { } }; client._parseMessage(response); + const tagResponse = fakeData.createEventSenderTagsResponse("Test", { tags: {} }); + client._parseMessage(tagResponse); }); test('test_event_code_description_multiple_flags', done => { - client.isOpen = true; + client.reqId = 0; client.requestEvents({ timeRangeBegin: 1000, timeRangeEnd: 2000, codeMask: 0, limit: 10, offset: 0, flags: 0 }) .then(events => { expect(events).toHaveLength(1); - // code = 0x5 => (AlarmSet (0x1) + AlarmAck (0x4)) expect(events[0].code).toBe(0x5); expect(events[0].codeDescription).toBe("AlarmSet + AlarmAck"); done(); }) .catch(done.fail); - // Simulate a multi-flag event response. const response = { messageType: fakeData.Container.Type.eEventsResponse, eventsResponse: { @@ -317,12 +328,17 @@ describe('ClientTester', () => { } }; client._parseMessage(response); + const tagResponse = fakeData.createEventSenderTagsResponse("MultiFlagSensor", { tags: {} }); + client._parseMessage(tagResponse); }); test('test_realistic_events', done => { + client.reqId = 0; client.isOpen = true; - - // Request events in a time window covering the sample timestamps (08:34:50..08:37:21) + // Prepopulate senderTags to avoid waiting for tag lookups. + client.senderTags["CPDLoggerDemoApp.InvalidLicense"] = {}; + client.senderTags["CDPLoggerDemoApp.CPDEventNotification"] = {}; + client.senderTags["CPDLoggerDemoApp"] = {}; client.requestEvents({ timeRangeBegin: 1740284000, timeRangeEnd: 1740284300, @@ -332,39 +348,117 @@ describe('ClientTester', () => { flags: 0 }) .then(events => { - // We expect to receive 4 events total expect(events).toHaveLength(4); - - // 1) InvalidLicense alarm expect(events[0].sender).toBe("CPDLoggerDemoApp.InvalidLicense"); expect(events[0].data["Text"]).toBe("Invalid or missing feature license detected."); expect(events[0].codeDescription).toBe("AlarmSet"); - expect(events[0].status).toBe(1); // "Error" - - // 2) CPDEventNotification + expect(events[0].status).toBe(1); expect(events[1].sender).toBe("CDPLoggerDemoApp.CPDEventNotification"); expect(events[1].data["Text"]).toBe("CDP event notice"); expect(events[1].codeDescription).toBe("None"); - expect(events[1].status).toBe(3); // "Notify" - - // 3) A component is suspended + expect(events[1].status).toBe(3); expect(events[2].sender).toBe("CPDLoggerDemoApp"); expect(events[2].data["Text"]).toContain("A component is suspended"); expect(events[2].codeDescription).toBe("AlarmSet"); - expect(events[2].status).toBe(1); // "Error" - - // 4) Another suspended warning + expect(events[2].status).toBe(1); expect(events[3].sender).toBe("CPDLoggerDemoApp"); expect(events[3].data["Text"]).toBe("Component was suspended"); expect(events[3].codeDescription).toBe("None"); - expect(events[3].status).toBe(2); // "Warning" - + expect(events[3].status).toBe(2); done(); }) .catch(done.fail); - - // Simulate the server responding with these "realistic" events const response = fakeData.createRealisticEventsResponse(1); client._parseMessage(response); }); + + test('test_getSenderTags_success', done => { + client.isOpen = true; + client._sendEventSenderTagsRequest = jest.fn(); + const sender = "TestSender"; + const tagPromise = client.getSenderTags(sender); + expect(client._sendEventSenderTagsRequest).toHaveBeenCalledWith(sender); + const response = fakeData.createEventSenderTagsResponse(sender, { tags: { Tag1: { value: "Value1", source: "Source1" } } }); + client._parseMessage(response); + tagPromise.then(tags => { + expect(tags).toEqual({ Tag1: { value: "Value1", source: "Source1" } }); + done(); + }).catch(done.fail); + }); + + test('test_getSenderTags_rejects_on_ws_error', done => { + client.isOpen = true; + const sender = "TestSender"; + const tagPromise = client.getSenderTags(sender); + const error = new Error("WS error"); + client._onError(client.ws, error); + tagPromise.then(() => done.fail("Promise should not resolve")) + .catch(err => { + expect(err).toBe(error); + done(); + }); + }); + + test('test_events_request_attaches_sender_tags', done => { + client.reqId = 0; + // Disable time sync interference. + client._timeRequest = jest.fn(); + client.isOpen = true; + // Override _buildEventQuery to bypass generated code dependency. + client._buildEventQuery = query => query; + + // Capture the client reference locally. + const localClient = client; + + // Override _sendEventsRequest to simulate an asynchronous events response. + localClient._sendEventsRequest = (requestId, query) => { + setImmediate(() => { + const response = { + messageType: fakeData.Container.Type.eEventsResponse, + eventsResponse: { + requestId, + events: [ + { + sender: "TestSender", + data: { Text: "Test event" }, + timestampSec: 1234, + id: 1, + code: 0, + status: 0, + logstampSec: 1234 + } + ] + } + }; + localClient._parseMessage(response); + }); + }; + + // Clear any cached sender tags and pending promises. + localClient.senderTags = {}; + localClient.pendingSenderTags = {}; + + // Override _sendEventSenderTagsRequest to simulate an asynchronous immediate tag response. + localClient._sendEventSenderTagsRequest = sender => { + setImmediate(() => { + const tagResponse = fakeData.createEventSenderTagsResponse( + sender, + { tags: { Tag1: { value: "Value1", source: "Source1" } } } + ); + localClient._parseMessage(tagResponse); + }); + }; + + localClient.requestEvents({}) + .then(events => { + try { + expect(events).toHaveLength(1); + expect(events[0].tags).toEqual({ Tag1: { value: "Value1", source: "Source1" } }); + done(); + } catch (err) { + done(err); + } + }) + .catch(err => done(err)); + }); }); diff --git a/test/fakeData.js b/test/fakeData.js index eab99db..551a8b8 100644 --- a/test/fakeData.js +++ b/test/fakeData.js @@ -1,6 +1,5 @@ // fakeData.js -// Define a simple Container object to simulate our protobuf types. const Container = { Type: { eSignalInfoRequest: 1, @@ -101,7 +100,6 @@ function createErrorResponse() { }; } - function createRealisticEventsResponse(requestId = 1) { return { messageType: Container.Type.eEventsResponse, @@ -113,10 +111,10 @@ function createRealisticEventsResponse(requestId = 1) { data: { Text: "Invalid or missing feature license detected." }, - timestampSec: 1740284241, // ~2025-03-26 08:37:21 UTC + timestampSec: 1740284241, id: 101, - code: 0x1, // AlarmSet - status: 1, // Error + code: 0x1, + status: 1, logstampSec: 1740284241 }, { @@ -124,10 +122,10 @@ function createRealisticEventsResponse(requestId = 1) { data: { Text: "CDP event notice" }, - timestampSec: 1740284167, // ~2025-03-26 08:36:07 + timestampSec: 1740284167, id: 102, - code: 0, // None - status: 3, // Notify + code: 0, + status: 3, logstampSec: 1740284167 }, { @@ -135,10 +133,10 @@ function createRealisticEventsResponse(requestId = 1) { data: { Text: "A component is suspended" }, - timestampSec: 1740284145, // ~2025-03-26 08:35:45 + timestampSec: 1740284145, id: 103, - code: 0x1, // AlarmSet - status: 1, // Error + code: 0x1, + status: 1, logstampSec: 1740284145 }, { @@ -146,10 +144,10 @@ function createRealisticEventsResponse(requestId = 1) { data: { Text: "Component was suspended" }, - timestampSec: 1740284090, // ~2025-03-26 08:34:50 + timestampSec: 1740284090, id: 104, - code: 0, // None - status: 2, // Warning + code: 0, + status: 2, logstampSec: 1740284090 } ] @@ -157,6 +155,18 @@ function createRealisticEventsResponse(requestId = 1) { }; } +function createEventSenderTagsResponse(sender, tagMap) { + return { + messageType: Container.Type.eEventSenderTagsResponse, + eventSenderTagsResponse: { + senderTags: { + [sender]: tagMap + } + } + }; +} + + module.exports = { createApiVersionResponse, createApiVersionErrorResponse, @@ -164,6 +174,7 @@ module.exports = { createLoggedNodesResponse, createDataPointResponse, createErrorResponse, - createRealisticEventsResponse, // Export our new function + createRealisticEventsResponse, + createEventSenderTagsResponse, Container }; From bec060600dc8e6e2ba09635f106e412f7fb6c60a Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Wed, 2 Apr 2025 09:54:02 +0300 Subject: [PATCH 20/37] Wrapped Client in a namespace cdplogger.Client --- client.js | 16 +++++++++------- examples/event.js | 8 ++++---- examples/index.js | 4 ++-- test/client.test.js | 6 +++--- test/testTimeSync.js | 8 ++++---- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/client.js b/client.js index d275d71..184f4db 100644 --- a/client.js +++ b/client.js @@ -2,6 +2,8 @@ const WebSocket = require('ws'); const root = require('./generated/containerPb.js'); const Container = root.DBMessaging.Protobuf.Container; const CDPValueType = root.ICD.Protobuf.CDPValueType; +const EventQuery = root.DBMessaging.Protobuf.EventQuery; + /** * A client for interacting with a CDP Logger or LogServer via WebSocket. @@ -14,7 +16,7 @@ const CDPValueType = root.ICD.Protobuf.CDPValueType; class Client { // Defined property names to use instead of ambiguous numbers. static EventQueryFlags = Object.freeze({ - None: 0, // Client.EventQueryFlags.None === 0 + None: 0, // cdplogger.Client.EventQueryFlags.None === 0 NewestFirst: 1, TimeRangeBeginExclusive: 2, TimeRangeEndExclusive: 4, @@ -288,11 +290,11 @@ class Client { * dataConditions: { * Text: ["Invalid or missing feature license detected."], * // Multiple data conditions can be specified: - * Level: { value: "ERROR", matchType: Client.MatchType.Exact } + * Level: { value: "ERROR", matchType: cdplogger.Client.MatchType.Exact } * }, * limit: 100, * offset: 0, - * flags: Client.EventQueryFlags.NewestFirst + * flags: cdplogger.Client.EventQueryFlags.NewestFirst * }); * * @param {Object} query - A simple plain object representing the EventQuery. @@ -1016,9 +1018,6 @@ class Client { // Validate the query object before building the EventQuery. this._validateEventQuery(query); - const root = require('./generated/containerPb.js'); - const { EventQuery } = root.DBMessaging.Protobuf; - // Conditionally include these fields only if the user has set them const optionalFields = [ "timeRangeBegin", @@ -1119,4 +1118,7 @@ class Client { } } -module.exports = Client; +const cdplogger = {}; +cdplogger.Client = Client; + +module.exports = cdplogger; diff --git a/examples/event.js b/examples/event.js index e3eda89..ea940d2 100644 --- a/examples/event.js +++ b/examples/event.js @@ -1,10 +1,10 @@ // event.js // An example script to see filtered events -const Client = require('../client'); +const cdplogger = require('../client'); async function main() { - const client = new Client('ws://127.0.0.1:17000', false); + const client = new cdplogger.Client('ws://127.0.0.1:17000', false); try { console.log("Waiting for connection to establish..."); @@ -16,7 +16,7 @@ async function main() { senderConditions: [ { value: "CDPLoggerDemoApp.InvalidLicense", - matchType: Client.MatchType.Exact + matchType: cdplogger.Client.MatchType.Exact } ], dataConditions: { @@ -24,7 +24,7 @@ async function main() { value: "*", // Wildcard condition for Text field } }, - flags: Client.EventQueryFlags.NewestFirst | Client.EventQueryFlags.UseLogStampForTimeRange, + flags: cdplogger.Client.EventQueryFlags.NewestFirst | cdplogger.Client.EventQueryFlags.UseLogStampForTimeRange, limit: 10, // Request a maximum of 10 events offset: 0 // Starting at the beginning }; diff --git a/examples/index.js b/examples/index.js index f1965cc..a7a2aaa 100644 --- a/examples/index.js +++ b/examples/index.js @@ -2,7 +2,7 @@ // Example demonstration including an events query for a specific time range (UTC 9:40) global.WebSocket = require('ws'); -const Client = require('../client'); +const cdplogger = require('../client'); // Print the node information (name, routing, and tags) function printLoggedNodes() { @@ -64,7 +64,7 @@ async function main() { } // Create a new client instance. (In this example, autoReconnect is disabled.) -const client = new Client('ws://127.0.0.1:17000', false); +const client = new cdplogger.Client('ws://127.0.0.1:17000', false); // Instead of overriding ws.onopen (which may cancel internal logic), // add an event listener so that _onOpen is still called. diff --git a/test/client.test.js b/test/client.test.js index ad52133..b368a30 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -1,13 +1,13 @@ /*global WebSocket*/ global.WebSocket = require('ws'); -const Client = require('../client'); +const cdplogger = require('../client'); const fakeData = require('./fakeData'); describe('ClientTester', () => { let client; beforeEach(() => { // Override _connect to return a fake ws object that doesn't actually connect. - Client.prototype._connect = function(url) { + cdplogger.Client.prototype._connect = function(url) { return { _url: url, close: jest.fn(), @@ -15,7 +15,7 @@ describe('ClientTester', () => { }; }; // Create a new client instance. - client = new Client('127.0.0.1:17000', true); + client = new cdplogger.Client('127.0.0.1:17000', true); // By default, disable time sync for most tests. client.setEnableTimeSync(false); // Adjust lastTimeRequest so that a new time request would normally be triggered. diff --git a/test/testTimeSync.js b/test/testTimeSync.js index d3047b7..b984069 100644 --- a/test/testTimeSync.js +++ b/test/testTimeSync.js @@ -1,5 +1,5 @@ // testTimeSync.js -const Client = require('../client'); +const cdplogger = require('../client'); const fakeData = require('./fakeData'); // Override WebSocket with a dummy that provides a send() method. @@ -15,8 +15,8 @@ global.WebSocket = class { // --- Capture Request IDs for time sync vs. API calls --- let capturedTimeSyncRequestId = null; let capturedApiRequestId = null; -const originalGetRequestId = Client.prototype._getRequestId; -Client.prototype._getRequestId = function() { +const originalGetRequestId = cdplogger.Client.prototype._getRequestId; +cdplogger.Client.prototype._getRequestId = function() { const id = originalGetRequestId.call(this); if (capturedTimeSyncRequestId === null) { capturedTimeSyncRequestId = id; @@ -77,7 +77,7 @@ async function runThrough(methodName, callFunc, simulateResponse) { async function runTest() { // Create a new client instance. - client = new Client('127.0.0.1:17000', true); + client = new cdplogger.Client('127.0.0.1:17000', true); // Override _sendTimeRequest to simulate a server time response with variable delay. client._sendTimeRequest = function (requestId) { From 0512a8ac4da48688da764170d3e4ab0bf333f3f2 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 3 Apr 2025 13:47:44 +0300 Subject: [PATCH 21/37] Add GitHub Actions workflow for running tests --- .github/workflows/test.yml | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a4cf2a9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: Run Jest Tests + +on: + push: + branches: [ '**' ] # Run on all branches + pull_request: + branches: [ '**' ] # Run on PRs targeting any branch + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14, 16, 18] + + steps: + - uses: actions/checkout@v3 + + - name: Set up Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-results-${{ matrix.node-version }} + path: | + coverage/ + test-results/ \ No newline at end of file From 50d5262c44b4606ccb5967e6e45fc4673239e5b8 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 3 Apr 2025 13:54:24 +0300 Subject: [PATCH 22/37] Update workflow to handle missing test directories --- .github/workflows/test.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a4cf2a9..dd6a1e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,6 +26,11 @@ jobs: - name: Install dependencies run: npm ci + - name: Create test directories + run: | + mkdir -p coverage + mkdir -p test-results + - name: Run tests run: npm test @@ -36,4 +41,5 @@ jobs: name: test-results-${{ matrix.node-version }} path: | coverage/ - test-results/ \ No newline at end of file + test-results/ + if-no-files-found: ignore \ No newline at end of file From cc9d10cecd2b86b8c199b9912d80d10b3d70a6bc Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 3 Apr 2025 13:56:30 +0300 Subject: [PATCH 23/37] Simplify workflow to run on single Node.js version --- .github/workflows/test.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dd6a1e8..891fb0e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,27 +10,18 @@ jobs: test: runs-on: ubuntu-latest - strategy: - matrix: - node-version: [14, 16, 18] - steps: - uses: actions/checkout@v3 - - name: Set up Node.js ${{ matrix.node-version }} + - name: Set up Node.js uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} + node-version: '18' cache: 'npm' - name: Install dependencies run: npm ci - - name: Create test directories - run: | - mkdir -p coverage - mkdir -p test-results - - name: Run tests run: npm test @@ -38,7 +29,7 @@ jobs: if: always() uses: actions/upload-artifact@v3 with: - name: test-results-${{ matrix.node-version }} + name: test-results path: | coverage/ test-results/ From 4df8074efad63a3ec8091b659ce6926771868868 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 3 Apr 2025 14:14:37 +0300 Subject: [PATCH 24/37] Add working GitHub Actions workflow for running tests --- .github/workflows/test.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 891fb0e..52af724 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,12 +25,9 @@ jobs: - name: Run tests run: npm test - - name: Upload test results + - name: Cleanup if: always() - uses: actions/upload-artifact@v3 - with: - name: test-results - path: | - coverage/ - test-results/ - if-no-files-found: ignore \ No newline at end of file + run: | + echo "Cleaning up..." + rm -rf node_modules + rm -rf .npm \ No newline at end of file From 3ebf57d3e4082c7c8977082d467ee47499a1fc10 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 3 Apr 2025 14:29:57 +0300 Subject: [PATCH 25/37] Added automatic test workflow --- README.md | 6 +++--- client.js | 15 +++++++++------ examples/event.js | 26 +++++++++++++------------- examples/{index.js => value.js} | 0 generated/containerPb.js | 1 + test/client.test.js | 16 ++++++++-------- test/testTimeSync.js | 2 +- 7 files changed, 35 insertions(+), 31 deletions(-) rename examples/{index.js => value.js} (100%) diff --git a/README.md b/README.md index 1041b51..77265ce 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,16 @@ node test/testTimeSync.js ## Usage -The index.js file contains a simple logger built for the CDP Studio example case. +The value.js file contains a simple logger built for the CDP Studio example case. 1. Set up and run the Logger in CDP Studio. (Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html -2. Run the index.js file from the command line: +2. Run the value.js file from the command line: ```bash -node examples/index.js +node examples/value.js ``` For usage related to events run: diff --git a/client.js b/client.js index 184f4db..3a65f4d 100644 --- a/client.js +++ b/client.js @@ -40,6 +40,10 @@ class Client { if (!/^wss?:\/\//.test(url)) { url = `ws://${url}`; } + // Same for ":17000" + if (!/\:17000$/.test(url)) { + url += ':17000'; + } this.reqId = -1; this.autoReconnect = autoReconnect; @@ -85,7 +89,7 @@ class Client { setEnableTimeSync(enable) { this.enableTimeSync = enable; if (!enable) { - // Cancel any pending time sync requests so they won’t update timeDiff later. + // Cancel any pending time sync requests so they won't update timeDiff later. for (const key in this.storedPromises) { this.storedPromises[key].reject(new Error("Time sync disabled")); } @@ -129,7 +133,7 @@ class Client { * larger data sets should be downloaded in patches. * - 4.0 (2024-01, CDP 4.12): * - Added NodeTag support to save custom tags for logged values (e.g. Unit or Description), - * accessible via the client’s API. + * accessible via the client's API. * - Reduced network usage by having data responses only include changes instead of repeating unchanged values. * - Added support for string values and events. * @@ -445,8 +449,7 @@ class Client { * This method checks if the tags for the specified sender are already cached. If so, it returns a * resolved promise with the cached tags. Otherwise, it initializes a pending promise for the sender, * sends a request for the sender's tags using `_sendEventSenderTagsRequest`, and returns a promise that - * resolves when the tags are received. If no response is received within 5000 ms, it falls back to resolving - * with an empty object. + * resolves when the tags are received. * * @param {string} sender - The identifier of the event sender. * @returns {Promise} A promise that resolves with an object representing the tags for the sender. @@ -867,7 +870,7 @@ class Client { _reqDataPoints(nodeNames, startS, endS, noOfDataPoints, limit, requestId) { const _getDataPoints = (nodeIds) => { - this._sendDataPointsRequest(nodeIds, startS, endS, requestId, limit, noOfDataPoints); + this._sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints, limit); }; const rejectRequest = (error) => { @@ -909,7 +912,7 @@ class Client { }); } - _sendDataPointsRequest(nodeIds, startS, endS, requestId, limit, noOfDataPoints) { + _sendDataPointsRequest(nodeIds, startS, endS, requestId, noOfDataPoints, limit) { const container = Container.create(); container.messageType = Container.Type.eSignalDataRequest; container.signalDataRequest = { diff --git a/examples/event.js b/examples/event.js index ea940d2..7149d79 100644 --- a/examples/event.js +++ b/examples/event.js @@ -3,8 +3,11 @@ const cdplogger = require('../client'); +const { EventQueryFlags, MatchType } = cdplogger.Client; + + async function main() { - const client = new cdplogger.Client('ws://127.0.0.1:17000', false); + const client = new cdplogger.Client('127.0.0.1', true); try { console.log("Waiting for connection to establish..."); @@ -13,20 +16,17 @@ async function main() { // Build the query with a limit and offset const query = { - senderConditions: [ - { - value: "CDPLoggerDemoApp.InvalidLicense", - matchType: cdplogger.Client.MatchType.Exact - } - ], + senderConditions: [{ + value: "CDPLoggerDemoApp.InvalidLicense", + matchType: MatchType.Exact + }], dataConditions: { - "Text": { - value: "*", // Wildcard condition for Text field - } + Text: ["Invalid*"], //Wildcard is the default + // Multiple data conditions can be specified }, - flags: cdplogger.Client.EventQueryFlags.NewestFirst | cdplogger.Client.EventQueryFlags.UseLogStampForTimeRange, - limit: 10, // Request a maximum of 10 events - offset: 0 // Starting at the beginning + limit: 100, + offset: 0, + flags: EventQueryFlags.NewestFirst | EventQueryFlags.UseLogStampForTimeRange }; console.log("Counting matching events..."); diff --git a/examples/index.js b/examples/value.js similarity index 100% rename from examples/index.js rename to examples/value.js diff --git a/generated/containerPb.js b/generated/containerPb.js index db446d1..303b8b0 100644 --- a/generated/containerPb.js +++ b/generated/containerPb.js @@ -1,3 +1,4 @@ +// TODO Guide on how this file was generated /*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ "use strict"; diff --git a/test/client.test.js b/test/client.test.js index b368a30..9c484f0 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -106,12 +106,12 @@ describe('ClientTester', () => { setImmediate(() => { expect(client._sendTimeRequest).toHaveBeenCalledWith(1); expect(client._sendDataPointsRequest).toHaveBeenCalledWith( - [0, 1], - 1530613239.0, - 1530613270.0, - 2, // The second call's requestId - 500, // limit - 0 // noOfDataPoints + [0, 1], // nodeIds + 1530613239.0, // startS + 1530613270.0, // endS + 2, // requestId + 0, // noOfDataPoints + 500 // limit ); done(); }); @@ -198,7 +198,7 @@ describe('ClientTester', () => { client.reqId = 0; client.isOpen = true; client._sendDataPointsRequest = jest.fn(); - client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 0, 500) + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500, 0) .then(dataPoints => { expect(dataPoints[0].timestamp).toBeCloseTo(1531313250.0); expect(dataPoints[0].value["Output"].min).toBeCloseTo(0.638855091434); @@ -220,7 +220,7 @@ describe('ClientTester', () => { delete client.idToName[id]; } } - client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 0, 500) + client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500, 0) .catch(error => { expect(error).toBeInstanceOf(Error); expect(error.message).toMatch(/Output/); diff --git a/test/testTimeSync.js b/test/testTimeSync.js index b984069..96c92d6 100644 --- a/test/testTimeSync.js +++ b/test/testTimeSync.js @@ -171,7 +171,7 @@ async function runTest() { await runThrough( "requestDataPoints", - () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 500), + () => client.requestDataPoints(["Output", "CPULoad"], 1531313250.0, 1531461231.0, 0, 500), (timeSyncId, apiId) => { const timeResponse = { messageType: fakeData.Container.Type.eTimeResponse, From 189a984700dfeeee93a91607fa3671a6c528c205 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Fri, 4 Apr 2025 10:00:34 +0300 Subject: [PATCH 26/37] Removed hardcoded port adding to url --- client.js | 4 ---- examples/event.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/client.js b/client.js index 3a65f4d..9412dc9 100644 --- a/client.js +++ b/client.js @@ -40,10 +40,6 @@ class Client { if (!/^wss?:\/\//.test(url)) { url = `ws://${url}`; } - // Same for ":17000" - if (!/\:17000$/.test(url)) { - url += ':17000'; - } this.reqId = -1; this.autoReconnect = autoReconnect; diff --git a/examples/event.js b/examples/event.js index 7149d79..3ddb989 100644 --- a/examples/event.js +++ b/examples/event.js @@ -7,7 +7,7 @@ const { EventQueryFlags, MatchType } = cdplogger.Client; async function main() { - const client = new cdplogger.Client('127.0.0.1', true); + const client = new cdplogger.Client('127.0.0.1:17000', true); try { console.log("Waiting for connection to establish..."); From f03f42fe3d5f569f16e479f68440cf03f47dd05f Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Mon, 7 Apr 2025 15:02:38 +0300 Subject: [PATCH 27/37] Created a markdown file for docs and a quick start guide --- DOCUMENTATION.md | 296 ++++++++++++++++++++++++++++++++++++++++++++++ QUICKSTART.md | 150 +++++++++++++++++++++++ README.md | 6 +- examples/event.js | 2 +- 4 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 DOCUMENTATION.md create mode 100644 QUICKSTART.md diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 0000000..833e336 --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,296 @@ +# JavaScript CDP Logger Client + +**JavaScript CDP Logger Client** is an open-source library for interfacing with CDP Studio applications that use the **CDP Logger** component. It allows you to monitor and retrieve historical data (logged signal values) and system events from a running CDP application via WebSocket. The library works in both Node.js and browser environments (e.g. it can be integrated into a Vue.js frontend) and requires a CDP Logger server to be running in your CDP Studio system. + +## Quickstart + +For a quickstart guide, see the [QUICKSTART.md](QUICKSTART.md) file. + +## Overview and Purpose + +In **CDP Studio**, the CDP Logger component is responsible for logging selected values (signals) and events from your system for long-term storage ([Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html#:~:text=The%20CDP%20Logger%20is%20a,file%20or%20a%20remote%20server)). This client library connects to that CDP Logger (or an external LogServer) over WebSocket and uses CDP’s protobuf-based API to query the logged data. The purpose of the library is to provide an easy JavaScript interface to: + +- List what signals are being logged (and their metadata) +- Read historical data points for those signals (e.g. for plotting trends) +- Retrieve logged events from the system (with filtering options) +- Handle connection details like reconnection and time synchronization + +By using this library, developers can build dashboards, monitoring tools, or scripts that interact with a live CDP system’s historical data **without** needing to manually handle low-level WebSocket messaging or protobuf encoding. This README will guide you through the features, setup, and usage of the library. + +## Key Features + +- **Connect to CDP Logger via WebSocket:** Easily connect to a running CDP Logger or LogServer by specifying its host/port (e.g. `ws://127.0.0.1:17000`). The client handles establishing the WebSocket connection and managing message encoding/decoding. + +- **Retrieve Logged Values:** Query the list of logged signals (nodes) from the CDP Logger (equivalent to the Logger’s *LoggedValues* table in CDP Studio). Each logged node entry includes its name, full path (routing), and any associated tags/metadata (like engineering unit or description). You can also request historical data points for one or multiple signals over a time range. For example, you can fetch a downsampled series of values between a start and end timestamp, or even full-resolution data if needed. + +- **Event Logging and Querying:** Fetch historical **events** logged by the CDP Logger. By default, CDP Logger captures all system events ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=The%20CDP%20Logger%20is%20a,for%20logging%20a%20sine%20signal)), and this client allows you to query those events with powerful filtering options. You can filter by event sender (source component), by event data fields (supports wildcard matching on text fields), by event codes or severity, and by time ranges. The API provides methods to either count events matching a query or retrieve the event details. Retrieved events include timestamp, sender, event data (which may be structured data or messages), and tags (metadata) for the event source. + +- **Tag Support:** Supports **Node Tags** for logged values and event sender tags. If your CDP system defines custom tags (metadata) for signals (e.g. unit, description) or for event sources, the client will fetch and include this information in the results. For example, when you list logged nodes via this client, you’ll get any custom tag values (and their source) associated with each node. This was introduced in newer CDP versions (CDP 4.12 / API v4.0) and is fully supported by the library. + +- **Time Synchronization:** The client automatically synchronizes time with the server to account for clock drift. On each data or event query, it can perform a quick time exchange with the server to calculate the offset (`timeDiff`) between the client’s clock and the CDP Logger’s clock. This ensures that timestamp-based queries (for data points or events) align correctly with the logger’s timeline. Time sync is enabled by default and can be toggled on/off in case you want to use the client’s local time only. + +- **Automatic Reconnection:** If the WebSocket connection drops, the client can automatically attempt to reconnect (this is enabled by default). Upon reconnect, it will also resend any pending requests that were queued while the connection was down, so your application can recover seamlessly from transient network issues. You can disable auto-reconnect by passing `autoReconnect=false` when creating the client if you prefer to handle disconnections manually. + +- **Node.js and Browser Support:** The library is designed to work in Node.js (for back-end scripts or services) as well as in the browser (front-end web applications). In Node.js, it uses the popular `ws` package for WebSocket support, and in browsers it uses the native `WebSocket` API. The codebase is written in plain JavaScript, and a usage example with **Vue.js** is provided to demonstrate integration in a web UI (see below). + +- **Built on Protocol Buffers:** Communication with the CDP Logger uses Protocol Buffers (protobuf) messages defined by CDP. This library includes the necessary protobuf definitions (for container messages, data requests/responses, event queries, etc.), using the [`protobufjs`](https://www.npmjs.com/package/protobufjs) library under the hood. You don’t need to manually deal with proto files – the library handles serialization and parsing of messages into easy-to-use JavaScript objects. + +- **Logging API Version Support:** The client is compatible with CDP Logger API version 3.0 and above (CDP 4.3+). It implements newer API features such as event querying and node tags (available in API v4.0, CDP 4.12) while maintaining backward compatibility with the core functions from earlier versions. You can always check the logger’s API version by calling `client.requestApiVersion()` to ensure the server supports certain features. + +## Installation + +### Via npm + +You can install the library from npm: + +```bash +npm install cdp-logger-client +``` + +This will add the CDP Logger client to your project’s dependencies. The package bundles the necessary JavaScript files and protobuf definitions. The only peer dependency you might need is a WebSocket implementation if you are using Node.js (see **Prerequisites** and **Usage in Node.js** below). + +### In Browser (direct script include) + +If you are not using a module bundler and prefer to include the library via ` + + + + +``` + +Once these are included, a global object `cdplogger` will be available, through which you can create a client and use the API (as shown in the usage examples below). + +## Prerequisites + +Before using the CDP Logger Client, make sure you have the following: + +- **CDP Studio and a Running CDP Application** – You need a CDP Studio project/application running that includes a **CDPLogger** component (or a standalone **LogServer**) configured to log data. Ensure that the logger is active and has a network port open for the WebSocket connections. Typically, the CDP Logger’s server port is configured in the CDP Studio project (for example, it might default to 17000, but confirm in your project settings). The application should also have some signals added to the logger’s Logged Values, otherwise there’s no data to retrieve. *(See CDP Studio’s documentation on how to add signals to the logger, e.g. by right-clicking a signal and selecting “Add to Logger” ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=)).)* Also, if you want to retrieve events, ensure that **Event Logging** is enabled on the CDP Logger (it is true by default ([Event Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html#event-logging))). + +- **Node.js environment (for Node usage)** – If you plan to use this library in Node.js, you should have Node.js installed. Additionally, because Node does not have a built-in WebSocket, you will need to install a WebSocket library. We suggest using [`ws`](https://www.npmjs.com/package/ws), which the client has been tested with. In a Node context, you will instruct the client to use `ws` by assigning it to the global WebSocket (shown below). + +- **Modern Web Browser (for browser usage)** – If using in a web frontend, ensure you are using a reasonably modern browser that supports WebSockets (virtually all modern browsers do) and ES6 features. The library does not require any special polyfills aside from including the ProtoBuf runtime as mentioned. The Vue.js example provided assumes an environment where you can run ES2015+ code. + +- **ProtoBuf JS** – The library depends on `protobufjs` (included as an npm dependency). If you installed via npm and are using a bundler or Node, this will be installed automatically. If you are using direct script includes, include the `protobuf.min.js` as shown above. + +- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (3.0+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you’re running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. + +## Setup and Configuration + +Below we detail how to set up and use the CDP Logger Client in both Node.js and browser environments, with code examples. + +### Using the Client in Node.js + +In Node.js, you will typically import (or require) the library and set up a WebSocket polyfill, then create a client instance pointing to your CDP Logger’s address. + +**Example (Node.js):** + +```js +// 1. Install and import the CDP Logger Client +const cdplogger = require('cdp-logger-client'); + +// 2. Set up WebSocket for Node (since Node has no native WebSocket) +global.WebSocket = require('ws'); // ensure 'ws' is installed in your project + +// 3. Create a client instance connecting to the logger endpoint +// Replace the host and port with your CDP Logger's address. +const client = new cdplogger.Client('127.0.0.1:17000'); + +// 4. Use the client to query data. For example, get the logger version: +client.requestApiVersion() + .then(version => { + console.log("CDP Logger API Version:", version); + // E.g., might print "CDP Logger API Version: 4.0.0" + }) + .catch(err => { + console.error("Failed to get API version:", err); + }); + +// 5. Query the list of logged nodes (signals) and print their names: +client.requestLoggedNodes() + .then(nodes => { + console.log("Logged Nodes:"); + nodes.forEach(node => { + console.log(`- ${node.name} (Path: ${node.routing})`); + if (node.tags) { + // If tags are available (CDP 4.12+), print those as well + Object.entries(node.tags).forEach(([tagName, tagInfo]) => { + console.log(` Tag "${tagName}": ${tagInfo.value} (source: ${tagInfo.source})`); + }); + } + }); + }) + .catch(err => { + console.error("Error retrieving logged nodes:", err); + }); +``` + +A few notes on the above example: + +- The `Client` constructor takes the logger endpoint. You can provide it as `"host:port"` (as a string) or a full WebSocket URL (`"ws://host:port"` or `"wss://host:port"` for secure). If the `ws://` prefix is omitted, the library will prepend it automatically. In the example, `'127.0.0.1:17000'` becomes `ws://127.0.0.1:17000`. + +- We set `global.WebSocket = require('ws')` **before** creating the client. The library will use the global `WebSocket` class to establish the connection. In a Node environment, `ws` provides this. (If you forget to do this, you might get a reference error or no connection, since by default the code expects `window.WebSocket` in a browser or a global WebSocket in Node.) + +- The client connects immediately upon instantiation. It will attempt to open the WebSocket and, if `autoReconnect` is true (default), keep trying if the connection is refused or lost. You can check `client.isOpen` to see if the connection is currently open. In the example, we simply make requests; if the socket isn’t open yet, the library will queue the requests and send them once connected. + +- The API calls like `requestApiVersion()`, `requestLoggedNodes()` return Promises. You can also use `async/await` if you prefer. For instance, `const nodes = await client.requestLoggedNodes().catch(console.error);` inside an `async` function. + +- The `requestLoggedNodes()` call returns an array of node info objects. Each object has at least `{ name: string, routing: string }` and possibly a `tags` object if tags are supported and fetched. The `tags` object is a dictionary of tagName -> `{ value: any, source: string }`. For example, a node could have `node.tags.Unit = { value: "°C", source: "CDPStudio" }` indicating the engineering unit is degrees Celsius. + +You can also request historical **data points** for one or more signals using `client.requestDataPoints(names, startTimeSec, endTimeSec, numberOfPoints)`. For example: + +```js +// Assume we got `limits` from requestLogLimits (which provides start and end of log): +const limits = await client.requestLogLimits(); +const start = limits.startS; +const end = limits.endS; +// Request 100 data points for signals "Temperature" and "Pressure" over the full range +const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100); +dataPoints.forEach(point => { + console.log("Timestamp:", point.timestamp); + // Each point.value will contain an object with keys for each signal name: + // e.g., point.value["Temperature"] = { min: ..., max: ..., last: ... } + const tempData = point.value["Temperature"]; + if (tempData) { + console.log(` Temperature -> min: ${tempData.min}, max: ${tempData.max}, last: ${tempData.last}`); + } + const pressData = point.value["Pressure"]; + if (pressData) { + console.log(` Pressure -> min: ${pressData.min}, max: ${pressData.max}, last: ${pressData.last}`); + } +}); +``` + +The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `numberOfPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. + +Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here’s a brief Node example for events: + +```js +const query = { + senderConditions: [ + { value: "MyApp.AlarmManager", matchType: MatchType.Exact } + ], + dataConditions: { + // Assume events have a field "Text" and we want those containing "Overheat" + Text: ["Overheat*"] // '*' wildcard is the default option + }, + timeRangeStart: Date.now()/1000 - 24*3600, // (optional) last 24 hours in seconds (if time filtering desired) + limit: 50, // max 50 events + offset: 0, // start from the first match + flags: EventQueryFlags.NewestFirst // get newest events first +}; + +const totalMatching = await client.countEvents(query); +console.log(`There are ${totalMatching} events matching the query conditions.`); +const events = await client.requestEvents(query); +events.forEach(evt => { + console.log(`Event at ${evt.timestampSec} from ${evt.sender}:`, evt.data); + if (evt.tags) { + console.log(" Sender tags:", evt.tags); + } +}); +``` + +In this example, we filter events whose sender matches "MyApp.AlarmManager*" and whose text contains "Overheat". We retrieve up to 50 of the most recent such events. Each `evt` has properties like `timestampSec` (epoch time), `sender` (string identifier of the source), `data` (often an object or message describing the event), and `tags` (metadata about the sender, if available). The `EventQueryFlags` and `MatchType` static enums are provided by the library to refine queries (e.g., `Wildcard` vs `Exact` matching). See the CDP Logger documentation for full details on event query parameters ([Event Query](https://cdpstudio.com/manual/cdp/cdp2sql/logmanager-eventquery.html)). + +When you are done with the client (in Node or browser), you can call `client.disconnect()` to close the WebSocket and stop any automatic reconnection attempts. In Node scripts that are meant to exit, make sure to call `disconnect()` or `process.exit()` after your queries finish, otherwise the process may stay alive waiting for the socket to close. + +### Using the Client in a Browser + +Using the client in a browser is similar, except you don’t need to polyfill WebSocket (browsers have it natively) and you will access the library via the global `cdplogger` (if included via ` + + + + +``` + +As shown, the usage is very much the same as in Node. The `cdplogger.Client` class is the main entry point. In a browser context, you might integrate this with UI components or state management. For example, in a Vue.js app, you might call these client methods in a Vuex store or inside component lifecycle hooks to retrieve data and then render charts (as demonstrated in the included Vue example). The provided `model.js` (in this repository’s examples) shows a more involved integration: it uses the client to load historical data for multiple sensors and plot them using Chart.js, and to fetch events (like alarms) to display in a list. You can refer to that for inspiration on how to bind the data to a frontend. + +A few browser-specific notes: + +- **Security:** If your CDP Logger is served over HTTPS (or you are accessing it from an HTTPS page), use `wss://` for the WebSocket URL to avoid mixed content issues. Ensure the CDP Logger is configured with TLS if needed. For local testing with `http://localhost` you can use `ws://` without issues. + +- **CORS/WebSocket Policy:** WebSocket connections are not subject to the same-origin policy in the way XHR/Fetch are, but some environments might still require the server to accept the connection. The CDP Logger’s WebSocket server should accept connections from any origin by default. If you encounter issues connecting from a web page, check if any firewall or network configuration is blocking the websocket port. + +- **Performance:** Retrieving a lot of data points or events in one go can be heavy for the browser. If you plan to visualize large data sets, consider using pagination (e.g., request events 100 at a time using `offset`) or downsampling data points via the `numberOfPoints` parameter. The library itself streams the data efficiently, but rendering thousands of points in the DOM can be slow, so plan accordingly. + +## How to Run Tests + +This project includes a set of unit tests and simulation scripts to ensure the client works as expected. Tests are written using **Jest**. + +After you clone the repository and install dependencies (`npm install`), you can run the test suite with: + +```bash +npm test +``` + +This will run all the Jest tests. The tests cover various client behaviors, such as message parsing, time synchronization logic, and error handling. + +One notable test utility is the **time synchronization simulation** found in `tests/testTimeSync.js`. This script creates a dummy WebSocket (without a real server) and simulates responses to test how the client calculates the `timeDiff` between client and server clocks. It overrides the client’s internal methods to inject fake time responses and prints out the results for verification. You can run this script manually (e.g., `node tests/testTimeSync.js`) to see a step-by-step log of time sync in action. The script will output logs showing the time difference calculations with time sync **enabled vs disabled**, helping validate that the mechanism works correctly. + +When contributing to the project (or if you modify the code), please run `npm test` to ensure all tests still pass. If you add new features, adding corresponding tests is highly appreciated. + +## Contribution Guidelines + +Contributions are welcome! If you have an idea for improvement or have found a bug, please open an issue on the GitHub repository to discuss it. If you’d like to contribute code or documentation: + +1. **Fork the repository** on GitHub and create a new branch for your changes. +2. Make your changes in your fork. If adding a feature or fixing a bug, try to add or update unit tests to cover your change. +3. Ensure the code style remains consistent with the project (we use common JavaScript best practices; if the project has an ESLint configuration, please run it). +4. Run the test suite (`npm test`) to confirm all tests pass. +5. Commit your changes with clear commit messages. +6. **Open a Pull Request** to the main repository, describing the changes and the motivation. The maintainers will review your PR and merge it after any discussions or adjustments. + +For significant changes, it’s often good to discuss in an issue first to ensure the change aligns with the project goals. We aim to keep the library lightweight and focused on CDP Logger interactions. + +Also, make sure any contributions you submit are your own work and that you’re okay with releasing them under the project’s MIT license. + +## License + +This project is open-source software licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. This means you are free to use, modify, and distribute this library in your own projects, even commercial ones, provided you include the copyright notice and license text in any redistribution. + +## Resources and Helpful Links + +- **CDP Studio Documentation – CDP Logger:** To understand the context and capabilities of the CDP Logger component, see the official CDP Studio documentation. The CDP Logger is described as a component for logging values and events for long-term storage. You can read more in the CDP Studio Manual under *Framework - Data Logging*. (Visit the [CDP Studio Docs website](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html). + +- **CDP Studio Official Website:** For more information about CDP Studio in general (the development environment, features, downloads, etc.), visit the [official CDP Studio website](https://cdpstudio.com). This site contains tutorials, user manuals, and other resources to help you get started with building applications in CDP Studio. + +- **Example Project:** For a complete example of how to use the CDP Logger Client in a Web environment Vue.js project, see the [Adding a Vue.js Web GUI to Automation System](https://cdpstudio.com/manual/cdp/examples/webui-demo.html). + +- **GitHub Repository (Source Code):** You can find the source code for this library, report issues, and see example code on the project’s GitHub page: [CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient). Feel free to star the repo and watch for updates. All development and issue tracking is done through GitHub. + +- **Contact (Support):** If you have questions or need help with the library, you can reach out to the maintainers via the CDP Technologies support email: **support@cdptech.com**. We encourage you to use the issue tracker on GitHub for bug reports and feature requests, but for direct support inquiries, email is available. + +--- + +*Thank you for using the JavaScript CDP Logger Client!* We hope this library makes it easier to integrate CDP Studio’s powerful logging capabilities into your own tools and applications. ([GitHub - CDPTechnologies/JavascriptCDPLoggerClient: A simple Javascript interface to communicate with CDP applications containing a CDPLogger component to retrieve historic data.](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#:~:text=A%20simple%20JavaScript%20interface%20for,com)) \ No newline at end of file diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..17acea9 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,150 @@ +# Quick Start Guide – CDPLogger Client + +This guide demonstrates how to get started with the CDPLogger Client in both **Node.js** and **Browser** environments. Note that the client module must be built differently for each target environment. + +## Documentation + +For documentation on the JS logger see [DOCUMENTATION.md](DOCUMENTATION.md) + +## Overview + +- **Node.js Version:** + - Uses CommonJS modules (imported via `require()`). + - Loads protobuf definitions from local files (e.g. from `./generated/containerPb.js`). + - Requires a WebSocket polyfill (such as the `ws` package) since Node.js lacks a native WebSocket. + +- **Browser Version:** + - Uses the browser’s native WebSocket. + - Obtains protobuf definitions from the global scope via `window.root` (set by including `containerPb.js`). + +## Installation + +### For Node.js + +Install the CDPLogger Client and a WebSocket polyfill: + +```bash +npm install cdp-logger-client ws +``` + +### For Browser + +Include the following scripts in your HTML: +- `protobuf.min.js` – for the ProtoBuf runtime. +- `containerPb.js` – which sets up `window.root` with your protobuf definitions. +- The web version of `client.js` – which should include the web-specific modifications (see the "Adapting client.js for Web Support" section below). + +## Adapting client.js for Web Support + +To enable web support, ensure your `client.js` file includes these modifications: + +1. **Use the Browser’s Native WebSocket:** + In the web version, remove or comment out any code that requires a WebSocket polyfill. For example: + ```js + // const WebSocket = require('ws'); // Do not use this in the browser + ``` + +2. **Use Global Protobuf Definitions:** + Instead of importing protobuf definitions via CommonJS, obtain them from the global scope: + ```js + // For Node.js, you might load: + // const root = require('./generated/containerPb.js'); + // For Browser, use the global "root" defined by containerPb.js: + const root = window.root; + const Container = root.DBMessaging.Protobuf.Container; + const CDPValueType = root.ICD.Protobuf.CDPValueType; + const EventQuery = root.DBMessaging.Protobuf.EventQuery; + ``` + +3. **Expose the Client Globally:** + At the end of your `client.js`, attach the client API to the global window: + ```js + cdplogger.Client = Client; + window.cdplogger = cdplogger; + ``` + This ensures that when `client.js` is loaded in a browser, the `cdplogger` object (and its `Client` class) is available globally. + +*Make sure these modifications are only applied for the browser version of your client module.* + +## Usage + +### Node.js Example + +```js +// Import the client and set up the WebSocket polyfill +const cdplogger = require('cdp-logger-client'); +global.WebSocket = require('ws'); + +// Create a client instance (endpoint can be "127.0.0.1:17000" or "ws://127.0.0.1:17000") +const client = new cdplogger.Client('127.0.0.1:17000'); + +// Fetch the API version from the CDP Logger +client.requestApiVersion().then(version => { + console.log("CDP Logger API Version:", version); +}); + +// List logged nodes (displaying name and routing information) +client.requestLoggedNodes().then(nodes => { + nodes.forEach(node => { + console.log(`Name: ${node.name}, Routing: ${node.routing}`); + }); +}); + +// Disconnect after a short delay (for demonstration purposes) +setTimeout(() => { + client.disconnect(); + process.exit(0); +}, 5000); +``` + +*In the Node.js version, the module is imported using `require()`, and the WebSocket polyfill is provided by the `ws` package.* + +### Browser Example + +Create an HTML file that includes the necessary scripts. For example: + +```html + + + + + CDPLogger Client Quick Start + + + + + + + + + + + +``` + +*In the browser version, by including `client.js` (with the modifications described above), the client automatically uses the native WebSocket, the global protobuf definitions from `window.root`, and attaches the API to `window.cdplogger`.* + +## Prerequisites + +- **CDP Studio:** Ensure a CDP Studio application is running with an active **CDPLogger** (or LogServer) on a known WebSocket port (e.g., 17000). +- **For Node.js:** Install the `ws` package as a WebSocket polyfill. + +## Learn More + +- [Full README](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient) +- [CDP Logger Documentation](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html) diff --git a/README.md b/README.md index 77265ce..99cd4c5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # CDPLogger Client for JavaScript A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -For more information about CDP Studio see https://cdpstudio.com/. +- For documentation on the JS logger see [DOCUMENTATION.md](DOCUMENTATION.md). +- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](QUICKSTART.md) +- For more information about CDP Studio see https://cdpstudio.com/. ## Installation @@ -20,6 +22,8 @@ To run the automatic tests with fake data, execute: npm test ``` +Note: these jest tests execute on every push and pull of the repo as well. + To test the time sync functionality using simulated response: ```bash diff --git a/examples/event.js b/examples/event.js index 3ddb989..fb67f34 100644 --- a/examples/event.js +++ b/examples/event.js @@ -21,7 +21,7 @@ async function main() { matchType: MatchType.Exact }], dataConditions: { - Text: ["Invalid*"], //Wildcard is the default + Text: ["Invalid*"], // Wildcard is the default // Multiple data conditions can be specified }, limit: 100, From bce99c913e241d77c9c2e1c7f3ba54edeb2a82a3 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Tue, 8 Apr 2025 13:13:10 +0300 Subject: [PATCH 28/37] Fixed documentation mistakes --- DOCUMENTATION.md | 15 +++++------ QUICKSTART.md | 67 ++++++++++++++++++++++++++++++++++++------------ README.md | 2 +- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 833e336..e56db1d 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -82,7 +82,7 @@ Before using the CDP Logger Client, make sure you have the following: - **ProtoBuf JS** – The library depends on `protobufjs` (included as an npm dependency). If you installed via npm and are using a bundler or Node, this will be installed automatically. If you are using direct script includes, include the `protobuf.min.js` as shown above. -- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (3.0+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you’re running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. +- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (CDP 4.3+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you’re running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. ## Setup and Configuration @@ -149,7 +149,6 @@ A few notes on the above example: You can also request historical **data points** for one or more signals using `client.requestDataPoints(names, startTimeSec, endTimeSec, numberOfPoints)`. For example: ```js -// Assume we got `limits` from requestLogLimits (which provides start and end of log): const limits = await client.requestLogLimits(); const start = limits.startS; const end = limits.endS; @@ -175,7 +174,7 @@ The above demonstrates retrieving 100 aggregated data points between the earlies Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here’s a brief Node example for events: ```js -const query = { +const query = { // Note: all query arguments are optional senderConditions: [ { value: "MyApp.AlarmManager", matchType: MatchType.Exact } ], @@ -183,7 +182,7 @@ const query = { // Assume events have a field "Text" and we want those containing "Overheat" Text: ["Overheat*"] // '*' wildcard is the default option }, - timeRangeStart: Date.now()/1000 - 24*3600, // (optional) last 24 hours in seconds (if time filtering desired) + timeRangeStart: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) limit: 50, // max 50 events offset: 0, // start from the first match flags: EventQueryFlags.NewestFirst // get newest events first @@ -218,7 +217,7 @@ Using the client in a browser is similar, except you don’t need to polyfill We ``` -*In the browser version, by including `client.js` (with the modifications described above), the client automatically uses the native WebSocket, the global protobuf definitions from `window.root`, and attaches the API to `window.cdplogger`.* +*In the browser version, we use `window.location.hostname` to connect to the same host as the web page, with the default logger port 17000.* ## Prerequisites diff --git a/README.md b/README.md index 99cd4c5..0290a8c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # CDPLogger Client for JavaScript A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -- For documentation on the JS logger see [DOCUMENTATION.md](DOCUMENTATION.md). +- For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.md). - For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](QUICKSTART.md) - For more information about CDP Studio see https://cdpstudio.com/. From f6aa706a87e6318f8799e0e8b43cf0ffcfe8f5ed Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 10 Apr 2025 10:58:59 +0300 Subject: [PATCH 29/37] NPM setup --- GITHUB-GUIDE.md | 57 +++++++++++++++++++++++++++++++++++++++ README.md | 72 ++++++++++++++++++++++++------------------------- client.js | 10 ++++++- package.json | 37 ++++++++++++++++++++++--- 4 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 GITHUB-GUIDE.md diff --git a/GITHUB-GUIDE.md b/GITHUB-GUIDE.md new file mode 100644 index 0000000..0290a8c --- /dev/null +++ b/GITHUB-GUIDE.md @@ -0,0 +1,57 @@ +# CDPLogger Client for JavaScript + +A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. +- For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.md). +- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](QUICKSTART.md) +- For more information about CDP Studio see https://cdpstudio.com/. + +## Installation + +Clone the repository and install dependencies: + +```bash +npm install +``` + + +## Running Tests + +To run the automatic tests with fake data, execute: + +```bash +npm test +``` + +Note: these jest tests execute on every push and pull of the repo as well. + +To test the time sync functionality using simulated response: + +```bash +node test/testTimeSync.js +``` + + +## Usage + +The value.js file contains a simple logger built for the CDP Studio example case. + +1. Set up and run the Logger in CDP Studio. +(Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) +https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html + +2. Run the value.js file from the command line: + +```bash +node examples/value.js +``` + +For usage related to events run: + +```bash +node examples/event.js +``` + + +## Contact + +Email: support@cdptech.com \ No newline at end of file diff --git a/README.md b/README.md index 0290a8c..73471e0 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,57 @@ -# CDPLogger Client for JavaScript +# CDP Logger Client -A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -- For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.md). -- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](QUICKSTART.md) -- For more information about CDP Studio see https://cdpstudio.com/. +A JavaScript client for interacting with CDP Logger or LogServer via WebSocket. This client allows you to: +- Connect to a CDP Logger or LogServer +- Request logged nodes and their metadata +- Retrieve data points for specific nodes +- Query events from the logger +- Get log limits and API version information ## Installation -Clone the repository and install dependencies: - ```bash -npm install +npm install cdp-logger-client ``` +## Quick Start -## Running Tests - -To run the automatic tests with fake data, execute: +For a quick introduction, see the [QUICKSTART.md](QUICKSTART.md) guide. -```bash -npm test -``` - -Note: these jest tests execute on every push and pull of the repo as well. - -To test the time sync functionality using simulated response: - -```bash -node test/testTimeSync.js -``` +## Documentation +For detailed documentation, see [DOCUMENTATION.md](DOCUMENTATION.md). ## Usage -The value.js file contains a simple logger built for the CDP Studio example case. +### Node.js -1. Set up and run the Logger in CDP Studio. -(Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) -https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html +```javascript +const cdplogger = require('cdp-logger-client'); +global.WebSocket = require('ws'); -2. Run the value.js file from the command line: +const client = new cdplogger.Client('127.0.0.1:17000'); -```bash -node examples/value.js +// List logged nodes +client.requestLoggedNodes().then(nodes => { + console.log("Available nodes:", nodes); +}); ``` -For usage related to events run: - -```bash -node examples/event.js +### Browser + +```html + + + + ``` +## License -## Contact - -Email: support@cdptech.com \ No newline at end of file +MIT \ No newline at end of file diff --git a/client.js b/client.js index 9412dc9..56c5557 100644 --- a/client.js +++ b/client.js @@ -1117,7 +1117,15 @@ class Client { } } +// Export the module const cdplogger = {}; cdplogger.Client = Client; -module.exports = cdplogger; +// For Node.js +if (typeof module !== 'undefined' && module.exports) { + module.exports = cdplogger; +} +// For Browser +else if (typeof window !== 'undefined') { + window.cdplogger = cdplogger; +} diff --git a/package.json b/package.json index b79cf3a..7158e2e 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,43 @@ { - "devDependencies": { - "jest": "^29.7.0", - "ws": "^8.18.1" + "name": "cdp-logger-client", + "version": "1.0.0", + "description": "A JavaScript client for interacting with CDP Logger or LogServer via WebSocket", + "main": "client.js", + "files": [ + "client.js", + "generated/containerPb.js", + "README.md", + "QUICKSTART.md", + "DOCUMENTATION.md", + "LICENSE" + ], + "repository": { + "type": "git", + "url": "https://github.com/CDPTechnologies/JavascriptCDPLoggerClient.git" }, "scripts": { "test": "jest" }, + "keywords": [ + "cdp", + "cdp-studio", + "cdplogger", + "cdp-logger", + "cdp-logger-client", + "cdploggerclient", + "cdpjsclientlogger", + "cdp-js-client-logger", + "cdp-studio-logger", + "logger", + "logger-client" + ], + "author": "", + "license": "MIT", "dependencies": { "protobufjs": "^7.4.0" + }, + "devDependencies": { + "ws": "^8.13.0", + "jest": "^29.5.0" } } From dc2dad63020579fa219ff1c5e27bf3ae4f18fd0b Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 10 Apr 2025 11:05:15 +0300 Subject: [PATCH 30/37] Updated package.json --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7158e2e..39b8c1f 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,12 @@ "logger", "logger-client" ], - "author": "", + "author": "CDP Technologies", "license": "MIT", + "bugs": { + "url": "https://github.com/CDPTechnologies/JavascriptCDPLoggerClient/issues" + }, + "homepage": "https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#readme", "dependencies": { "protobufjs": "^7.4.0" }, From b182d640e5a407f7038da141f1b09e784ff279f0 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 10 Apr 2025 11:11:31 +0300 Subject: [PATCH 31/37] Added contacts to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 73471e0..50bd11d 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,11 @@ client.requestLoggedNodes().then(nodes => { ``` +## Resources + +For more information about CDP Studio see https://cdpstudio.com/. +Contact: support@cdptech.com + ## License MIT \ No newline at end of file From 15621e0e0749f1d4911f85af76c5e1173bc50145 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 10 Apr 2025 11:53:54 +0300 Subject: [PATCH 32/37] Updated docs --- GITHUB-GUIDE.md => .github/README.md | 0 QUICKSTART.md | 8 -------- README.md | 15 ++++++++++----- 3 files changed, 10 insertions(+), 13 deletions(-) rename GITHUB-GUIDE.md => .github/README.md (100%) diff --git a/GITHUB-GUIDE.md b/.github/README.md similarity index 100% rename from GITHUB-GUIDE.md rename to .github/README.md diff --git a/QUICKSTART.md b/QUICKSTART.md index a3f5993..58f10c6 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -56,14 +56,6 @@ To enable web support, ensure your `client.js` file includes these modifications const EventQuery = root.DBMessaging.Protobuf.EventQuery; ``` -3. **Expose the Client Globally:** - At the end of your `client.js`, attach the client API to the global window: - ```js - cdplogger.Client = Client; - window.cdplogger = cdplogger; - ``` - This ensures that when `client.js` is loaded in a browser, the `cdplogger` object (and its `Client` class) is available globally. - *Make sure these modifications are only applied for the browser version of your client module.* ## Usage diff --git a/README.md b/README.md index 50bd11d..e5d439f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ # CDP Logger Client -A JavaScript client for interacting with CDP Logger or LogServer via WebSocket. This client allows you to: -- Connect to a CDP Logger or LogServer +# CDP Logger Client + +A JavaScript client for reading historic data from systems created with the CDP Studio development platform. +For more information about CDP Studio, see https://cdpstudio.com/. +For more information about CDP Logger, see https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html. + +This client allows you to: +- Connect to a CDP Logger or LogServer component - Request logged nodes and their metadata - Retrieve data points for specific nodes - Query events from the logger @@ -52,10 +58,9 @@ client.requestLoggedNodes().then(nodes => { ``` -## Resources +## Contact -For more information about CDP Studio see https://cdpstudio.com/. -Contact: support@cdptech.com +Email: support@cdptech.com ## License From 3fdaba7bdcbbf6053e8eced30ac0b73950193a54 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 10 Apr 2025 12:45:25 +0300 Subject: [PATCH 33/37] Changed name from cdp-logger-client to cdplogger-client --- .gitignore | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ DOCUMENTATION.md | 4 +-- QUICKSTART.md | 4 +-- README.md | 6 ++--- package.json | 4 +-- 5 files changed, 74 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 9e99588..527ea72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,68 @@ +# Dependencies node_modules/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage +.grunt + +# Bower dependency directory +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons +build/Release + +# Dependency directories +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# npm config file +.npmrc + protos/ \ No newline at end of file diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index e56db1d..dd9299e 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -44,7 +44,7 @@ By using this library, developers can build dashboards, monitoring tools, or scr You can install the library from npm: ```bash -npm install cdp-logger-client +npm install cdplogger-client ``` This will add the CDP Logger client to your project’s dependencies. The package bundles the necessary JavaScript files and protobuf definitions. The only peer dependency you might need is a WebSocket implementation if you are using Node.js (see **Prerequisites** and **Usage in Node.js** below). @@ -96,7 +96,7 @@ In Node.js, you will typically import (or require) the library and set up a WebS ```js // 1. Install and import the CDP Logger Client -const cdplogger = require('cdp-logger-client'); +const cdplogger = require('cdplogger-client'); // 2. Set up WebSocket for Node (since Node has no native WebSocket) global.WebSocket = require('ws'); // ensure 'ws' is installed in your project diff --git a/QUICKSTART.md b/QUICKSTART.md index 58f10c6..be4c23c 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -24,7 +24,7 @@ For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.m Install the CDPLogger Client and a WebSocket polyfill (for the Node.js version): ```bash -npm install cdp-logger-client ws +npm install cdplogger-client ws ``` ### For Browser @@ -64,7 +64,7 @@ To enable web support, ensure your `client.js` file includes these modifications ```js // Import the client and set up the WebSocket polyfill -const cdplogger = require('cdp-logger-client'); +const cdplogger = require('cdplogger-client'); global.WebSocket = require('ws'); // Create a client instance (endpoint can be "127.0.0.1:17000" or "ws://127.0.0.1:17000") diff --git a/README.md b/README.md index e5d439f..3f1c4a8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # CDP Logger Client -# CDP Logger Client - A JavaScript client for reading historic data from systems created with the CDP Studio development platform. For more information about CDP Studio, see https://cdpstudio.com/. For more information about CDP Logger, see https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html. @@ -16,7 +14,7 @@ This client allows you to: ## Installation ```bash -npm install cdp-logger-client +npm install cdplogger-client ``` ## Quick Start @@ -32,7 +30,7 @@ For detailed documentation, see [DOCUMENTATION.md](DOCUMENTATION.md). ### Node.js ```javascript -const cdplogger = require('cdp-logger-client'); +const cdplogger = require('cdplogger-client'); global.WebSocket = require('ws'); const client = new cdplogger.Client('127.0.0.1:17000'); diff --git a/package.json b/package.json index 39b8c1f..48a78c6 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "cdp-logger-client", + "name": "cdplogger-client", "version": "1.0.0", "description": "A JavaScript client for interacting with CDP Logger or LogServer via WebSocket", "main": "client.js", @@ -23,7 +23,7 @@ "cdp-studio", "cdplogger", "cdp-logger", - "cdp-logger-client", + "cdplogger-client", "cdploggerclient", "cdpjsclientlogger", "cdp-js-client-logger", From 28458522ace8fa8b6485d149d9f6d70cb33c54de Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Mon, 28 Apr 2025 15:01:10 +0300 Subject: [PATCH 34/37] Publish version 1.0.2 and update package.json and README --- .github/README.md | 4 ++-- README.md | 15 --------------- package.json | 4 ++-- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/.github/README.md b/.github/README.md index 0290a8c..3ddefe5 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,8 +1,8 @@ # CDPLogger Client for JavaScript A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -- For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.md). -- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](QUICKSTART.md) +- For documentation on the JS logger client see [DOCUMENTATION.md](../DOCUMENTATION.md). +- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](../QUICKSTART.md) - For more information about CDP Studio see https://cdpstudio.com/. ## Installation diff --git a/README.md b/README.md index 3f1c4a8..768dd2d 100644 --- a/README.md +++ b/README.md @@ -41,21 +41,6 @@ client.requestLoggedNodes().then(nodes => { }); ``` -### Browser - -```html - - - - -``` - ## Contact Email: support@cdptech.com diff --git a/package.json b/package.json index 48a78c6..7094bff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cdplogger-client", - "version": "1.0.0", + "version": "1.0.2", "description": "A JavaScript client for interacting with CDP Logger or LogServer via WebSocket", "main": "client.js", "files": [ @@ -38,10 +38,10 @@ }, "homepage": "https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#readme", "dependencies": { + "ws": "^8.13.0", "protobufjs": "^7.4.0" }, "devDependencies": { - "ws": "^8.13.0", "jest": "^29.5.0" } } From 67a6a5535d6569537bb1dd4dcb187760a24e4ec7 Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Wed, 18 Jun 2025 14:03:37 +0300 Subject: [PATCH 35/37] Fix documentation --- DOCUMENTATION.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index dd9299e..50b23d1 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -146,14 +146,14 @@ A few notes on the above example: - The `requestLoggedNodes()` call returns an array of node info objects. Each object has at least `{ name: string, routing: string }` and possibly a `tags` object if tags are supported and fetched. The `tags` object is a dictionary of tagName -> `{ value: any, source: string }`. For example, a node could have `node.tags.Unit = { value: "°C", source: "CDPStudio" }` indicating the engineering unit is degrees Celsius. -You can also request historical **data points** for one or more signals using `client.requestDataPoints(names, startTimeSec, endTimeSec, numberOfPoints)`. For example: +You can also request historical **data points** for one or more signals using `client.requestDataPoints(nodeNames, startS, endS, noOfDataPoints, limit)`. For example: ```js const limits = await client.requestLogLimits(); const start = limits.startS; const end = limits.endS; // Request 100 data points for signals "Temperature" and "Pressure" over the full range -const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100); +const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100, 0); dataPoints.forEach(point => { console.log("Timestamp:", point.timestamp); // Each point.value will contain an object with keys for each signal name: @@ -169,11 +169,14 @@ dataPoints.forEach(point => { }); ``` -The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `numberOfPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. +The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `noOfDataPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here’s a brief Node example for events: ```js +// Helpful enums from the client for query construction +const { MatchType, EventQueryFlags } = cdplogger.Client; + const query = { // Note: all query arguments are optional senderConditions: [ { value: "MyApp.AlarmManager", matchType: MatchType.Exact } @@ -182,7 +185,7 @@ const query = { // Note: all query arguments are optional // Assume events have a field "Text" and we want those containing "Overheat" Text: ["Overheat*"] // '*' wildcard is the default option }, - timeRangeStart: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) + timeRangeBegin: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) limit: 50, // max 50 events offset: 0, // start from the first match flags: EventQueryFlags.NewestFirst // get newest events first From 62136b6ce103459fc31e39ed87ee2bb0a9b8133e Mon Sep 17 00:00:00 2001 From: stefanrammo Date: Thu, 19 Jun 2025 09:28:04 +0300 Subject: [PATCH 36/37] Add automatic detection to client.js between Node.js or browser --- .github/README.md | 10 +++++ DOCUMENTATION.md | 100 +++++++++++++++++++++++++--------------------- QUICKSTART.md | 62 ++++++++++++---------------- README.md | 33 ++++++++++++++- client.js | 19 +++++++-- examples/value.js | 5 +-- package.json | 2 +- 7 files changed, 140 insertions(+), 91 deletions(-) diff --git a/.github/README.md b/.github/README.md index 3ddefe5..b07115d 100644 --- a/.github/README.md +++ b/.github/README.md @@ -7,9 +7,19 @@ A simple JavaScript interface for communicating with CDP applications that inclu ## Installation +### NPM Package (Recommended) + +```bash +npm install cdplogger-client +``` + +### Development Setup + Clone the repository and install dependencies: ```bash +git clone https://github.com/CDPTechnologies/JavascriptCDPLoggerClient.git +cd JavascriptCDPLoggerClient npm install ``` diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index dd9299e..b6ca351 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -1,6 +1,6 @@ # JavaScript CDP Logger Client -**JavaScript CDP Logger Client** is an open-source library for interfacing with CDP Studio applications that use the **CDP Logger** component. It allows you to monitor and retrieve historical data (logged signal values) and system events from a running CDP application via WebSocket. The library works in both Node.js and browser environments (e.g. it can be integrated into a Vue.js frontend) and requires a CDP Logger server to be running in your CDP Studio system. +**JavaScript CDP Logger Client** is an open-source library for interfacing with CDP Studio applications that use the **CDP Logger** component. It allows you to monitor and retrieve historical data (logged signal values) and system events from a running CDP application via WebSocket. The library works seamlessly in both Node.js and browser environments (e.g. it can be integrated into a Vue.js frontend) and requires a CDP Logger server to be running in your CDP Studio system. ## Quickstart @@ -8,34 +8,34 @@ For a quickstart guide, see the [QUICKSTART.md](QUICKSTART.md) file. ## Overview and Purpose -In **CDP Studio**, the CDP Logger component is responsible for logging selected values (signals) and events from your system for long-term storage ([Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html#:~:text=The%20CDP%20Logger%20is%20a,file%20or%20a%20remote%20server)). This client library connects to that CDP Logger (or an external LogServer) over WebSocket and uses CDP’s protobuf-based API to query the logged data. The purpose of the library is to provide an easy JavaScript interface to: +In **CDP Studio**, the CDP Logger component is responsible for logging selected values (signals) and events from your system for long-term storage ([Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html#:~:text=The%20CDP%20Logger%20is%20a,file%20or%20a%20remote%20server)). This client library connects to that CDP Logger (or an external LogServer) over WebSocket and uses CDP's protobuf-based API to query the logged data. The purpose of the library is to provide an easy JavaScript interface to: - List what signals are being logged (and their metadata) - Read historical data points for those signals (e.g. for plotting trends) - Retrieve logged events from the system (with filtering options) - Handle connection details like reconnection and time synchronization -By using this library, developers can build dashboards, monitoring tools, or scripts that interact with a live CDP system’s historical data **without** needing to manually handle low-level WebSocket messaging or protobuf encoding. This README will guide you through the features, setup, and usage of the library. +By using this library, developers can build dashboards, monitoring tools, or scripts that interact with a live CDP system's historical data **without** needing to manually handle low-level WebSocket messaging or protobuf encoding. This README will guide you through the features, setup, and usage of the library. ## Key Features - **Connect to CDP Logger via WebSocket:** Easily connect to a running CDP Logger or LogServer by specifying its host/port (e.g. `ws://127.0.0.1:17000`). The client handles establishing the WebSocket connection and managing message encoding/decoding. -- **Retrieve Logged Values:** Query the list of logged signals (nodes) from the CDP Logger (equivalent to the Logger’s *LoggedValues* table in CDP Studio). Each logged node entry includes its name, full path (routing), and any associated tags/metadata (like engineering unit or description). You can also request historical data points for one or multiple signals over a time range. For example, you can fetch a downsampled series of values between a start and end timestamp, or even full-resolution data if needed. +- **Retrieve Logged Values:** Query the list of logged signals (nodes) from the CDP Logger (equivalent to the Logger's *LoggedValues* table in CDP Studio). Each logged node entry includes its name, full path (routing), and any associated tags/metadata (like engineering unit or description). You can also request historical data points for one or multiple signals over a time range. For example, you can fetch a downsampled series of values between a start and end timestamp, or even full-resolution data if needed. - **Event Logging and Querying:** Fetch historical **events** logged by the CDP Logger. By default, CDP Logger captures all system events ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=The%20CDP%20Logger%20is%20a,for%20logging%20a%20sine%20signal)), and this client allows you to query those events with powerful filtering options. You can filter by event sender (source component), by event data fields (supports wildcard matching on text fields), by event codes or severity, and by time ranges. The API provides methods to either count events matching a query or retrieve the event details. Retrieved events include timestamp, sender, event data (which may be structured data or messages), and tags (metadata) for the event source. -- **Tag Support:** Supports **Node Tags** for logged values and event sender tags. If your CDP system defines custom tags (metadata) for signals (e.g. unit, description) or for event sources, the client will fetch and include this information in the results. For example, when you list logged nodes via this client, you’ll get any custom tag values (and their source) associated with each node. This was introduced in newer CDP versions (CDP 4.12 / API v4.0) and is fully supported by the library. +- **Tag Support:** Supports **Node Tags** for logged values and event sender tags. If your CDP system defines custom tags (metadata) for signals (e.g. unit, description) or for event sources, the client will fetch and include this information in the results. For example, when you list logged nodes via this client, you'll get any custom tag values (and their source) associated with each node. This was introduced in newer CDP versions (CDP 4.12 / API v4.0) and is fully supported by the library. -- **Time Synchronization:** The client automatically synchronizes time with the server to account for clock drift. On each data or event query, it can perform a quick time exchange with the server to calculate the offset (`timeDiff`) between the client’s clock and the CDP Logger’s clock. This ensures that timestamp-based queries (for data points or events) align correctly with the logger’s timeline. Time sync is enabled by default and can be toggled on/off in case you want to use the client’s local time only. +- **Time Synchronization:** The client automatically synchronizes time with the server to account for clock drift. On each data or event query, it can perform a quick time exchange with the server to calculate the offset (`timeDiff`) between the client's clock and the CDP Logger's clock. This ensures that timestamp-based queries (for data points or events) align correctly with the logger's timeline. Time sync is enabled by default and can be toggled on/off in case you want to use the client's local time only. - **Automatic Reconnection:** If the WebSocket connection drops, the client can automatically attempt to reconnect (this is enabled by default). Upon reconnect, it will also resend any pending requests that were queued while the connection was down, so your application can recover seamlessly from transient network issues. You can disable auto-reconnect by passing `autoReconnect=false` when creating the client if you prefer to handle disconnections manually. - **Node.js and Browser Support:** The library is designed to work in Node.js (for back-end scripts or services) as well as in the browser (front-end web applications). In Node.js, it uses the popular `ws` package for WebSocket support, and in browsers it uses the native `WebSocket` API. The codebase is written in plain JavaScript, and a usage example with **Vue.js** is provided to demonstrate integration in a web UI (see below). -- **Built on Protocol Buffers:** Communication with the CDP Logger uses Protocol Buffers (protobuf) messages defined by CDP. This library includes the necessary protobuf definitions (for container messages, data requests/responses, event queries, etc.), using the [`protobufjs`](https://www.npmjs.com/package/protobufjs) library under the hood. You don’t need to manually deal with proto files – the library handles serialization and parsing of messages into easy-to-use JavaScript objects. +- **Built on Protocol Buffers:** Communication with the CDP Logger uses Protocol Buffers (protobuf) messages defined by CDP. This library includes the necessary protobuf definitions (for container messages, data requests/responses, event queries, etc.), using the [`protobufjs`](https://www.npmjs.com/package/protobufjs) library under the hood. You don't need to manually deal with proto files – the library handles serialization and parsing of messages into easy-to-use JavaScript objects. -- **Logging API Version Support:** The client is compatible with CDP Logger API version 3.0 and above (CDP 4.3+). It implements newer API features such as event querying and node tags (available in API v4.0, CDP 4.12) while maintaining backward compatibility with the core functions from earlier versions. You can always check the logger’s API version by calling `client.requestApiVersion()` to ensure the server supports certain features. +- **Logging API Version Support:** The client is compatible with CDP Logger API version 3.0 and above (CDP 4.3+). It implements newer API features such as event querying and node tags (available in API v4.0, CDP 4.12) while maintaining backward compatibility with the core functions from earlier versions. You can always check the logger's API version by calling `client.requestApiVersion()` to ensure the server supports certain features. ## Installation @@ -47,42 +47,50 @@ You can install the library from npm: npm install cdplogger-client ``` -This will add the CDP Logger client to your project’s dependencies. The package bundles the necessary JavaScript files and protobuf definitions. The only peer dependency you might need is a WebSocket implementation if you are using Node.js (see **Prerequisites** and **Usage in Node.js** below). +This will add the CDP Logger client to your project's dependencies. The package bundles the necessary JavaScript files, protobuf definitions, and the `ws` WebSocket implementation used in Node.js. No additional peer dependencies are required. ### In Browser (direct script include) -If you are not using a module bundler and prefer to include the library via ` - + ``` -Once these are included, a global object `cdplogger` will be available, through which you can create a client and use the API (as shown in the usage examples below). +Once these are included, a global object `cdplogger` will be available, through which you can create a client and use the API. You'll also need to access the protobuf definitions from the global scope: + +```js +// Access protobuf definitions from global scope +const root = window.root; +const Container = root.DBMessaging.Protobuf.Container; +const CDPValueType = root.ICD.Protobuf.CDPValueType; +const EventQuery = root.DBMessaging.Protobuf.EventQuery; +``` ## Prerequisites Before using the CDP Logger Client, make sure you have the following: -- **CDP Studio and a Running CDP Application** – You need a CDP Studio project/application running that includes a **CDPLogger** component (or a standalone **LogServer**) configured to log data. Ensure that the logger is active and has a network port open for the WebSocket connections. Typically, the CDP Logger’s server port is configured in the CDP Studio project (for example, it might default to 17000, but confirm in your project settings). The application should also have some signals added to the logger’s Logged Values, otherwise there’s no data to retrieve. *(See CDP Studio’s documentation on how to add signals to the logger, e.g. by right-clicking a signal and selecting “Add to Logger” ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=)).)* Also, if you want to retrieve events, ensure that **Event Logging** is enabled on the CDP Logger (it is true by default ([Event Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html#event-logging))). +- **CDP Studio and a Running CDP Application** – You need a CDP Studio project/application running that includes a **CDPLogger** component (or a standalone **LogServer**) configured to log data. Ensure that the logger is active and has a network port open for the WebSocket connections. Typically, the CDP Logger's server port is configured in the CDP Studio project (for example, it might default to 17000, but confirm in your project settings). The application should also have some signals added to the logger's Logged Values, otherwise there's no data to retrieve. *(See CDP Studio's documentation on how to add signals to the logger, e.g. by right-clicking a signal and selecting "Add to Logger" ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=)).)* Also, if you want to retrieve events, ensure that **Event Logging** is enabled on the CDP Logger (it is true by default ([Event Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html#event-logging))). -- **Node.js environment (for Node usage)** – If you plan to use this library in Node.js, you should have Node.js installed. Additionally, because Node does not have a built-in WebSocket, you will need to install a WebSocket library. We suggest using [`ws`](https://www.npmjs.com/package/ws), which the client has been tested with. In a Node context, you will instruct the client to use `ws` by assigning it to the global WebSocket (shown below). +- **Node.js environment (for Node usage)** – If you plan to use this library in Node.js, you should have Node.js installed. -- **Modern Web Browser (for browser usage)** – If using in a web frontend, ensure you are using a reasonably modern browser that supports WebSockets (virtually all modern browsers do) and ES6 features. The library does not require any special polyfills aside from including the ProtoBuf runtime as mentioned. The Vue.js example provided assumes an environment where you can run ES2015+ code. +- **Modern Web Browser (for browser usage)** – If using in a web frontend, ensure you are using a reasonably modern browser that supports WebSockets (virtually all modern browsers do) and ES6 features. The library automatically uses the browser's native WebSocket API. The Vue.js example provided assumes an environment where you can run ES2015+ code ([Vue.js Example](https://cdpstudio.com/manual/cdp/examples/webui-demo.html)). - **ProtoBuf JS** – The library depends on `protobufjs` (included as an npm dependency). If you installed via npm and are using a bundler or Node, this will be installed automatically. If you are using direct script includes, include the `protobuf.min.js` as shown above. -- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (CDP 4.3+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you’re running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. +- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (CDP 4.3+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you're running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. ## Setup and Configuration @@ -90,7 +98,7 @@ Below we detail how to set up and use the CDP Logger Client in both Node.js and ### Using the Client in Node.js -In Node.js, you will typically import (or require) the library and set up a WebSocket polyfill, then create a client instance pointing to your CDP Logger’s address. +In Node.js, you will typically import (or require) the library and create a client instance pointing to your CDP Logger's address. **Example (Node.js):** @@ -98,14 +106,12 @@ In Node.js, you will typically import (or require) the library and set up a WebS // 1. Install and import the CDP Logger Client const cdplogger = require('cdplogger-client'); -// 2. Set up WebSocket for Node (since Node has no native WebSocket) -global.WebSocket = require('ws'); // ensure 'ws' is installed in your project +// 2. Create a client instance connecting to the logger endpoint -// 3. Create a client instance connecting to the logger endpoint // Replace the host and port with your CDP Logger's address. -const client = new cdplogger.Client('127.0.0.1:17000'); +const client = new cdplogger.Client('127.0.0.1:17000'); -// 4. Use the client to query data. For example, get the logger version: +// 3. Use the client to query data. For example, get the logger version: client.requestApiVersion() .then(version => { console.log("CDP Logger API Version:", version); @@ -115,7 +121,7 @@ client.requestApiVersion() console.error("Failed to get API version:", err); }); -// 5. Query the list of logged nodes (signals) and print their names: +// 4. Query the list of logged nodes (signals) and print their names: client.requestLoggedNodes() .then(nodes => { console.log("Logged Nodes:"); @@ -138,22 +144,21 @@ A few notes on the above example: - The `Client` constructor takes the logger endpoint. You can provide it as `"host:port"` (as a string) or a full WebSocket URL (`"ws://host:port"` or `"wss://host:port"` for secure). If the `ws://` prefix is omitted, the library will prepend it automatically. In the example, `'127.0.0.1:17000'` becomes `ws://127.0.0.1:17000`. -- We set `global.WebSocket = require('ws')` **before** creating the client. The library will use the global `WebSocket` class to establish the connection. In a Node environment, `ws` provides this. (If you forget to do this, you might get a reference error or no connection, since by default the code expects `window.WebSocket` in a browser or a global WebSocket in Node.) -- The client connects immediately upon instantiation. It will attempt to open the WebSocket and, if `autoReconnect` is true (default), keep trying if the connection is refused or lost. You can check `client.isOpen` to see if the connection is currently open. In the example, we simply make requests; if the socket isn’t open yet, the library will queue the requests and send them once connected. +- The client connects immediately upon instantiation. It will attempt to open the WebSocket and, if `autoReconnect` is true (default), keep trying if the connection is refused or lost. You can check `client.isOpen` to see if the connection is currently open. In the example, we simply make requests; if the socket isn't open yet, the library will queue the requests and send them once connected. - The API calls like `requestApiVersion()`, `requestLoggedNodes()` return Promises. You can also use `async/await` if you prefer. For instance, `const nodes = await client.requestLoggedNodes().catch(console.error);` inside an `async` function. - The `requestLoggedNodes()` call returns an array of node info objects. Each object has at least `{ name: string, routing: string }` and possibly a `tags` object if tags are supported and fetched. The `tags` object is a dictionary of tagName -> `{ value: any, source: string }`. For example, a node could have `node.tags.Unit = { value: "°C", source: "CDPStudio" }` indicating the engineering unit is degrees Celsius. -You can also request historical **data points** for one or more signals using `client.requestDataPoints(names, startTimeSec, endTimeSec, numberOfPoints)`. For example: +You can also request historical **data points** for one or more signals using `client.requestDataPoints(nodeNames, startS, endS, noOfDataPoints, limit)`. For example: ```js const limits = await client.requestLogLimits(); const start = limits.startS; const end = limits.endS; // Request 100 data points for signals "Temperature" and "Pressure" over the full range -const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100); +const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100, 0); dataPoints.forEach(point => { console.log("Timestamp:", point.timestamp); // Each point.value will contain an object with keys for each signal name: @@ -169,11 +174,14 @@ dataPoints.forEach(point => { }); ``` -The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `numberOfPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. +The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `noOfDataPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. -Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here’s a brief Node example for events: +Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here's a brief Node example for events: ```js +// Helpful enums from the client for query construction +const { MatchType, EventQueryFlags } = cdplogger.Client; + const query = { // Note: all query arguments are optional senderConditions: [ { value: "MyApp.AlarmManager", matchType: MatchType.Exact } @@ -182,7 +190,7 @@ const query = { // Note: all query arguments are optional // Assume events have a field "Text" and we want those containing "Overheat" Text: ["Overheat*"] // '*' wildcard is the default option }, - timeRangeStart: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) + timeRangeBegin: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) limit: 50, // max 50 events offset: 0, // start from the first match flags: EventQueryFlags.NewestFirst // get newest events first @@ -205,7 +213,7 @@ When you are done with the client (in Node or browser), you can call `client.dis ### Using the Client in a Browser -Using the client in a browser is similar, except you don’t need to polyfill WebSocket (browsers have it natively) and you will access the library via the global `cdplogger` (if included via ` ``` -As shown, the usage is very much the same as in Node. The `cdplogger.Client` class is the main entry point. In a browser context, you might integrate this with UI components or state management. For example, in a Vue.js app, you might call these client methods in a Vuex store or inside component lifecycle hooks to retrieve data and then render charts (as demonstrated in the included Vue example). The provided `model.js` (in this repository’s examples) shows a more involved integration: it uses the client to load historical data for multiple sensors and plot them using Chart.js, and to fetch events (like alarms) to display in a list. You can refer to that for inspiration on how to bind the data to a frontend. +As shown, the usage is very much the same as in Node. The `cdplogger.Client` class is the main entry point. In a browser context, you might integrate this with UI components or state management. For example, in a Vue.js app, you might call these client methods in a Vuex store or inside component lifecycle hooks to retrieve data and then render charts (as demonstrated in the included Vue example). The provided `model.js` (in this repository's examples) shows a more involved integration: it uses the client to load historical data for multiple sensors and plot them using Chart.js, and to fetch events (like alarms) to display in a list. You can refer to that for inspiration on how to bind the data to a frontend. A few browser-specific notes: -- **CORS/WebSocket Policy:** WebSocket connections are not subject to the same-origin policy in the way XHR/Fetch are, but some environments might still require the server to accept the connection. The CDP Logger’s WebSocket server should accept connections from any origin by default. If you encounter issues connecting from a web page, check if any firewall or network configuration is blocking the websocket port. +- **CORS/WebSocket Policy:** WebSocket connections are not subject to the same-origin policy in the way XHR/Fetch are, but some environments might still require the server to accept the connection. The CDP Logger's WebSocket server should accept connections from any origin by default. If you encounter issues connecting from a web page, check if any firewall or network configuration is blocking the websocket port. - **Performance:** Retrieving a lot of data points or events in one go can be heavy for the browser. If you plan to visualize large data sets, consider using pagination (e.g., request events 100 at a time using `offset`) or downsampling data points via the `noOfDataPoints` parameter. The library itself streams the data efficiently, but rendering thousands of points in the DOM can be slow, so plan accordingly. @@ -251,15 +259,15 @@ After you clone the repository and install dependencies (`npm install`), you can npm test ``` -This will run all the Jest tests. The tests cover various client behaviors, such as message parsing, time synchronization logic, and error handling. +This will run all the Jest tests. The tests cover various client behaviors, such as message parsing, time synchronization logic, and error handling. -One notable test utility is the **time synchronization simulation** found in `tests/testTimeSync.js`. This script creates a dummy WebSocket (without a real server) and simulates responses to test how the client calculates the `timeDiff` between client and server clocks. It overrides the client’s internal methods to inject fake time responses and prints out the results for verification. You can run this script manually (e.g., `node tests/testTimeSync.js`) to see a step-by-step log of time sync in action. The script will output logs showing the time difference calculations with time sync **enabled vs disabled**, helping validate that the mechanism works correctly. +One notable test utility is the **time synchronization simulation** found in `tests/testTimeSync.js`. This script creates a dummy WebSocket (without a real server) and simulates responses to test how the client calculates the `timeDiff` between client and server clocks. It overrides the client's internal methods to inject fake time responses and prints out the results for verification. You can run this script manually (e.g., `node tests/testTimeSync.js`) to see a step-by-step log of time sync in action. The script will output logs showing the time difference calculations with time sync **enabled vs disabled**, helping validate that the mechanism works correctly. When contributing to the project (or if you modify the code), please run `npm test` to ensure all tests still pass. If you add new features, adding corresponding tests is highly appreciated. ## Contribution Guidelines -Contributions are welcome! If you have an idea for improvement or have found a bug, please open an issue on the GitHub repository to discuss it. If you’d like to contribute code or documentation: +Contributions are welcome! If you have an idea for improvement or have found a bug, please open an issue on the GitHub repository to discuss it. If you'd like to contribute code or documentation: 1. **Fork the repository** on GitHub and create a new branch for your changes. 2. Make your changes in your fork. If adding a feature or fixing a bug, try to add or update unit tests to cover your change. @@ -268,13 +276,13 @@ Contributions are welcome! If you have an idea for improvement or have found a b 5. Commit your changes with clear commit messages. 6. **Open a Pull Request** to the main repository, describing the changes and the motivation. The maintainers will review your PR and merge it after any discussions or adjustments. -For significant changes, it’s often good to discuss in an issue first to ensure the change aligns with the project goals. We aim to keep the library lightweight and focused on CDP Logger interactions. +For significant changes, it's often good to discuss in an issue first to ensure the change aligns with the project goals. We aim to keep the library lightweight and focused on CDP Logger interactions. -Also, make sure any contributions you submit are your own work and that you’re okay with releasing them under the project’s MIT license. +Also, make sure any contributions you submit are your own work and that you're okay with releasing them under the project's MIT license. ## License -This project is open-source software licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. This means you are free to use, modify, and distribute this library in your own projects, even commercial ones, provided you include the copyright notice and license text in any redistribution. +This project is open-source software licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. This means you are free to use, modify, and distribute this library in your own projects, even commercial ones, provided you include the copyright notice and license text in any redistribution. ## Resources and Helpful Links @@ -284,10 +292,10 @@ This project is open-source software licensed under the **MIT License**. See the - **Example Project:** For a complete example of how to use the CDP Logger Client in a Web environment Vue.js project, see the [Adding a Vue.js Web GUI to Automation System](https://cdpstudio.com/manual/cdp/examples/webui-demo.html). -- **GitHub Repository (Source Code):** You can find the source code for this library, report issues, and see example code on the project’s GitHub page: [CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient). Feel free to star the repo and watch for updates. All development and issue tracking is done through GitHub. +- **GitHub Repository (Source Code):** You can find the source code for this library, report issues, and see example code on the project's GitHub page: [CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient). Feel free to star the repo and watch for updates. All development and issue tracking is done through GitHub. - **Contact (Support):** If you have questions or need help with the library, you can reach out to the maintainers via the CDP Technologies support email: **support@cdptech.com**. We encourage you to use the issue tracker on GitHub for bug reports and feature requests, but for direct support inquiries, email is available. --- -*Thank you for using the JavaScript CDP Logger Client!* We hope this library makes it easier to integrate CDP Studio’s powerful logging capabilities into your own tools and applications. ([GitHub - CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#:~:text=A%20simple%20JavaScript%20interface%20for,com)) \ No newline at end of file +*Thank you for using the JavaScript CDP Logger Client!* We hope this library makes it easier to integrate CDP Studio's powerful logging capabilities into your own tools and applications. ([GitHub - CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#:~:text=A%20simple%20JavaScript%20interface%20for,com)) \ No newline at end of file diff --git a/QUICKSTART.md b/QUICKSTART.md index be4c23c..cefd842 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,6 +1,6 @@ # Quick Start Guide – CDPLogger Client -This guide demonstrates how to get started with the CDPLogger Client in both **Node.js** and **Browser** environments. Note that the client module must be built differently for each target environment. +This guide demonstrates how to get started with the CDPLogger Client in both **Node.js** and **Browser** environments. The client automatically detects the environment and works seamlessly in both. ## Documentation @@ -8,64 +8,47 @@ For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.m ## Overview -- **Node.js Version:** - - Uses CommonJS modules (imported via `require()`). - - Loads protobuf definitions from local files (e.g. from `./generated/containerPb.js`). - - Requires a WebSocket polyfill (such as the `ws` package) since Node.js lacks a native WebSocket. +The CDPLogger Client uses **automatic environment detection** to work in both Node.js and browser environments from a single source file: -- **Browser Version:** - - Uses the browser's native WebSocket. - - Obtains protobuf definitions from the global scope via `window.root` (set by including `containerPb.js`). +- **Node.js:** + - Automatically loads protobuf definitions using `require('./generated/containerPb.js')` + - Uses the `ws` package for WebSocket functionality (installed as a dependency) + - No manual setup required + +- **Browser:** + - Uses the browser's native WebSocket API + - Expects protobuf definitions to be available at `window.root` + - Requires including the containerPb.js script before the client ## Installation ### For Node.js -Install the CDPLogger Client and a WebSocket polyfill (for the Node.js version): - ```bash -npm install cdplogger-client ws +npm install cdplogger-client ``` ### For Browser Include the following scripts in your HTML: - `protobuf.min.js` – for the ProtoBuf runtime. -- `containerPb.js` – which sets up `window.root` with your protobuf definitions. -- The web version of `client.js` – which should include the web-specific modifications (see the "Adapting client.js for Web Support" section below). - -## Adapting client.js for Web Support - -To enable web support, ensure your `client.js` file includes these modifications: - -1. **Use the Browser's Native WebSocket:** - In the web version, remove or comment out any code that requires a WebSocket polyfill. For example: - ```js - // const WebSocket = require('ws'); // Do not use this in the browser - ``` - -2. **Use Global Protobuf Definitions:** - Instead of importing protobuf definitions via CommonJS, obtain them from the global scope: +- `containerPb.js` – which sets up `window.root` with your protobuf definitions +- `client.js` – the same file works in both Node.js and browser environments +- Instead of importing protobuf definitions via CommonJS, obtain them from the global scope: ```js - // For Node.js, you might load: - // const root = require('./generated/containerPb.js'); - // For Browser, use the global "root" defined by containerPb.js: const root = window.root; const Container = root.DBMessaging.Protobuf.Container; const CDPValueType = root.ICD.Protobuf.CDPValueType; const EventQuery = root.DBMessaging.Protobuf.EventQuery; ``` - -*Make sure these modifications are only applied for the browser version of your client module.* ## Usage ### Node.js Example ```js -// Import the client and set up the WebSocket polyfill +// Import the client const cdplogger = require('cdplogger-client'); -global.WebSocket = require('ws'); // Create a client instance (endpoint can be "127.0.0.1:17000" or "ws://127.0.0.1:17000") const client = new cdplogger.Client('127.0.0.1:17000'); @@ -106,7 +89,7 @@ setTimeout(() => { }, 5000); ``` -*In the Node.js version, the module is imported using `require()`, and the WebSocket polyfill is provided by the `ws` package.* +*The client automatically detects the Node.js environment and uses the `ws` package for WebSocket functionality.* ### Browser Example @@ -122,11 +105,17 @@ Create an HTML file that includes the necessary scripts. For example: - + + + + + + + + + +``` + ## Contact Email: support@cdptech.com diff --git a/client.js b/client.js index 56c5557..a12e4c4 100644 --- a/client.js +++ b/client.js @@ -1,5 +1,18 @@ -const WebSocket = require('ws'); -const root = require('./generated/containerPb.js'); +// Environment detection and dependency loading +let root; // protobuf definitions +let WS; // WebSocket constructor + +if (typeof window === 'undefined') { + // ---- Node / CommonJS ---- + root = require('./generated/containerPb.js'); + WS = global.WebSocket || require('ws'); + global.WebSocket = WS; // make sure anything else sees it +} else { + // ---- Browser ---- + root = window.root; // injected by + + + + + + +Then use via ``studio.logger.Client``: + + .. code:: javascript + + var loggerClient = new studio.logger.Client(window.location.hostname + ":17000"); + +Static properties: + +- ``studio.logger.Client.EventQueryFlags`` - ``{ None: 0, NewestFirst: 1, TimeRangeBeginExclusive: 2, TimeRangeEndExclusive: 4, UseLogStampForTimeRange: 8 }`` +- ``studio.logger.Client.MatchType`` - ``{ Exact: 0, Wildcard: 1 }`` + +LoggerClient API +~~~~~~~~~~~~~~~~ + +The logger client returned by ``client.logger()`` provides these methods: + +- ``requestApiVersion()`` - Returns Promise with the logger API version string. +- ``requestLoggedNodes()`` - Returns Promise with array of ``{ name, routing, tags }`` for each logged signal. +- ``requestLogLimits()`` - Returns Promise with ``{ startS, endS }`` — the earliest and latest logged timestamps in seconds. +- ``requestDataPoints(nodeNames, startS, endS, noOfDataPoints, limit)`` - Returns Promise with array of data points. Each point has ``{ timestamp, value }`` where value maps signal names to ``{ min, max, last }``. +- ``requestEvents(query)`` - Returns Promise with array of events. Query supports ``limit``, ``offset``, ``flags``, ``timeRangeBegin``, ``timeRangeEnd``, ``codeMask``, ``senderConditions``, ``dataConditions``. +- ``countEvents(query)`` - Returns Promise with the count of matching events. +- ``getEventCodeDescription(code)`` - Returns human-readable description for an event code (e.g. ``"AlarmSet + SourceObjectUnavailable"``). +- ``getEventCodeString(code)`` - Returns compact event code string (e.g. ``"RepriseAlarmSet"``, ``"Ack"``). +- ``getSenderTags(sender)`` - Returns Promise with tags for an event sender. +- ``disconnect()`` - Closes the connection and disables auto-reconnect. +- ``setEnableTimeSync(enable)`` - Enable or disable automatic time synchronization with the server. + diff --git a/index.js b/index.js index c89d6ac..de22b08 100644 --- a/index.js +++ b/index.js @@ -1560,6 +1560,48 @@ studio.internal = (function(proto) { return { transport: transport, instanceKey: instanceKey }; } + this.createServiceTransport = function(serviceId) { + var result = makeServiceTransport(serviceId); + serviceConnections.set(result.instanceKey, result.transport); + return result; + }; + + function isLoggerService(service) { + return service.type === 'websocketproxy' && + service.metadata && + service.metadata.proxy_type === 'logserver'; + } + + this.findLoggerService = function(name) { + for (var service of availableServices.values()) { + if (isLoggerService(service) && (!name || service.name === name)) { + return service; + } + } + return null; + }; + + this.findAllLoggerServices = function() { + var result = []; + availableServices.forEach(function(service) { + if (isLoggerService(service)) { + result.push({ name: service.name, metadata: service.metadata }); + } + }); + return result; + }; + + var serviceUpdateListeners = []; + + this.addServiceUpdateListener = function(fn) { + serviceUpdateListeners.push(fn); + }; + + this.removeServiceUpdateListener = function(fn) { + var idx = serviceUpdateListeners.indexOf(fn); + if (idx !== -1) serviceUpdateListeners.splice(idx, 1); + }; + function resendServicesRequest() { if (currentMetadata && currentMetadata.compatVersion >= PROXY_MIN_COMPAT_VERSION) { console.log("Did not receive services notification within expected interval. Re-requesting services."); @@ -1657,6 +1699,10 @@ studio.internal = (function(proto) { availableServices.set(Number(service.serviceId), service); }); + serviceUpdateListeners.slice().forEach(function(fn) { + try { fn(); } catch (e) { console.error("Service update listener threw:", e); } + }); + if (!isPrimaryConnection) { return; } @@ -2634,7 +2680,7 @@ studio.api = (function(internal) { return pathParts.reduce(findNode, self.root()); } - // timeout: 0 means immediate fail (old behavior) + // timeout: 0 means fail immediately if the app is not currently available if (options && options.timeout === 0) { return doFind(); } @@ -2656,12 +2702,258 @@ studio.api = (function(internal) { return system._getAppConnections(); }; + // --- Logger integration --- + + var SIBLING_POLL_MS = 2000; // Poll interval for discovering new sibling connections + var LoggerClient = studio.logger ? studio.logger.Client : null; + var loggerClients = {}; + var loggerPromises = {}; + var pendingLoggerCleanups = []; + + function getPrimaryConnection() { + return system._getAppConnections()[0]; + } + + function isConnectionAlive(connection) { + var transport = connection._getTransport(); + return transport && transport.readyState() === WebSocket.OPEN; + } + + function findLoggerAcrossConnections(name) { + var connections = system._getAppConnections(); + for (var i = 0; i < connections.length; i++) { + if (!isConnectionAlive(connections[i])) continue; + var service = connections[i].findLoggerService(name); + if (service) { + return { connection: connections[i], service: service }; + } + } + return null; + } + + function findAllLoggersAcrossConnections() { + var result = []; + var connections = system._getAppConnections(); + for (var i = 0; i < connections.length; i++) { + if (!isConnectionAlive(connections[i])) continue; + var loggers = connections[i].findAllLoggerServices(); + for (var j = 0; j < loggers.length; j++) { + result.push(loggers[j]); + } + } + return result; + } + + function createLoggerFromService(connection, service, cacheKey) { + var result = connection.createServiceTransport(Number(service.serviceId)); + var loggerClient = new LoggerClient(result.transport, false); + loggerClients[cacheKey] = loggerClient; + return loggerClient; + } + + /** + * Get a logger client for querying historic data and events (CDP 5.1+). + * Discovers loggers from all applications in the system, including + * sibling apps connected via proxy. + * @param {string} [name] - Logger service name to filter by, e.g. "App.CDPLogger". + * @param {number} [options.timeout] - Timeout in milliseconds. Without timeout, waits indefinitely until a matching logger appears. timeout: 0 rejects immediately if no matching logger is currently available. + * @returns {Promise.} + */ + this.logger = function(name, options) { + var timeout = options && options.timeout; + if (!LoggerClient) { + return Promise.reject(new Error("Logger client not available")); + } + var cacheKey = name || '__default__'; + if (loggerClients[cacheKey] && !loggerClients[cacheKey].disconnected) { + return Promise.resolve(loggerClients[cacheKey]); + } + delete loggerClients[cacheKey]; + if (loggerPromises[cacheKey]) { + return loggerPromises[cacheKey]; + } + + var promise = new Promise(function(resolve, reject) { + system.onConnect(function() { + var primary = getPrimaryConnection(); + if (!primary.supportsProxyProtocol()) { + reject(new Error("Logger service discovery requires CDP 5.1+")); + return; + } + var found = findLoggerAcrossConnections(name); + if (found) { + resolve(createLoggerFromService(found.connection, found.service, cacheKey)); + return; + } + // timeout: 0 means fail immediately if no logger is currently available + if (timeout === 0) { + reject(new Error("Timeout: no logger service found" + (name ? " for '" + name + "'" : ""))); + return; + } + // Wait for matching service to appear on any connection + var settled = false; + var timer = null; + var listenedConnections = []; + + function settle() { + if (settled) return false; + settled = true; + clearTimeout(timer); + clearInterval(pollInterval); + listenedConnections.forEach(function(conn) { + conn.removeServiceUpdateListener(listener); + }); + var idx = pendingLoggerCleanups.indexOf(cleanup); + if (idx !== -1) pendingLoggerCleanups.splice(idx, 1); + return true; + } + + if (timeout) { + timer = setTimeout(function() { + if (settle()) { + delete loggerPromises[cacheKey]; + reject(new Error("Timeout: no logger service found" + (name ? " for '" + name + "'" : ""))); + } + }, timeout); + } + + var pollInterval = null; + + function listener() { + // Register on any new connections that appeared since last check + var connections = system._getAppConnections(); + for (var i = 0; i < connections.length; i++) { + if (listenedConnections.indexOf(connections[i]) === -1) { + connections[i].addServiceUpdateListener(listener); + listenedConnections.push(connections[i]); + } + } + var f = findLoggerAcrossConnections(name); + if (f && settle()) { + resolve(createLoggerFromService(f.connection, f.service, cacheKey)); + } + } + + var cleanup = { + reject: function() { + if (settle()) { + delete loggerPromises[cacheKey]; + reject(new Error("Connection closed")); + } + } + }; + pendingLoggerCleanups.push(cleanup); + // Listen on all current connections for service updates + var connections = system._getAppConnections(); + for (var i = 0; i < connections.length; i++) { + connections[i].addServiceUpdateListener(listener); + listenedConnections.push(connections[i]); + } + // Poll for new sibling connections that may appear after proxy discovery + pollInterval = setInterval(listener, SIBLING_POLL_MS); + }, reject, autoConnect); + }); + + loggerPromises[cacheKey] = promise; + function clearPromise() { delete loggerPromises[cacheKey]; } + promise.then(clearPromise, clearPromise); + return promise; + }; + + /** + * Get all available logger services. Resolves immediately if services + * have already been discovered, otherwise waits for the first update. + * @returns {Promise.>} + */ + this.loggers = function() { + return new Promise(function(resolve, reject) { + system.onConnect(function() { + var primary = getPrimaryConnection(); + if (!primary.supportsProxyProtocol()) { + reject(new Error("Logger service discovery requires CDP 5.1+")); + return; + } + // Check all connections for logger services + var allLoggers = findAllLoggersAcrossConnections(); + if (allLoggers.length > 0) { + resolve(allLoggers); + return; + } + // Primary has received services but none are loggers — return current snapshot + if (primary.services().size > 0) { + resolve(allLoggers); + return; + } + var settled = false; + var listenedConnections = []; + function settle() { + if (settled) return false; + settled = true; + listenedConnections.forEach(function(conn) { + conn.removeServiceUpdateListener(listener); + }); + var idx = pendingLoggerCleanups.indexOf(cleanup); + if (idx !== -1) pendingLoggerCleanups.splice(idx, 1); + return true; + } + function listener() { + if (settle()) { + resolve(findAllLoggersAcrossConnections()); + } + } + var cleanup = { + reject: function() { + if (settle()) { + reject(new Error("Connection closed")); + } + } + }; + pendingLoggerCleanups.push(cleanup); + var connections = system._getAppConnections(); + for (var i = 0; i < connections.length; i++) { + connections[i].addServiceUpdateListener(listener); + listenedConnections.push(connections[i]); + } + }, reject, autoConnect); + }); + }; + + // Wrap close() to clean up logger clients + var originalClose = this.close; + this.close = function() { + Object.keys(loggerClients).forEach(function(key) { + try { loggerClients[key].disconnect(); } catch (e) { + console.error("Error disconnecting logger client:", e); + } + }); + loggerClients = {}; + loggerPromises = {}; + // Reject all pending logger/loggers promises and remove their listeners + var cleanups = pendingLoggerCleanups.slice(); + pendingLoggerCleanups = []; + cleanups.forEach(function(c) { c.reject(); }); + originalClose(); + }; }; return obj; })(studio.internal); +/* -------------------------------------------------------------------------- + * Logger client bundle + * ------------------------------------------------------------------------ */ +studio.logger = (function() { + var isNode = (typeof process !== 'undefined') && process.versions && process.versions.node && (typeof window === 'undefined'); + if (isNode) { + return require('./logger/logger-client.js'); + } + if (typeof window !== 'undefined' && window.cdplogger) { + return window.cdplogger; + } + return null; +})(); + /* -------------------------------------------------------------------------- * Module export (CommonJS/ES Module hybrid) * ------------------------------------------------------------------------ */ diff --git a/logger/.github/README.md b/logger/.github/README.md deleted file mode 100644 index b07115d..0000000 --- a/logger/.github/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# CDPLogger Client for JavaScript - -A simple JavaScript interface for communicating with CDP applications that include a CDPLogger component to retrieve historic data. -- For documentation on the JS logger client see [DOCUMENTATION.md](../DOCUMENTATION.md). -- For a quickstart guide on how to set-up the npm project for either Node or Web see [QUICKSTART.md](../QUICKSTART.md) -- For more information about CDP Studio see https://cdpstudio.com/. - -## Installation - -### NPM Package (Recommended) - -```bash -npm install cdplogger-client -``` - -### Development Setup - -Clone the repository and install dependencies: - -```bash -git clone https://github.com/CDPTechnologies/JavascriptCDPLoggerClient.git -cd JavascriptCDPLoggerClient -npm install -``` - - -## Running Tests - -To run the automatic tests with fake data, execute: - -```bash -npm test -``` - -Note: these jest tests execute on every push and pull of the repo as well. - -To test the time sync functionality using simulated response: - -```bash -node test/testTimeSync.js -``` - - -## Usage - -The value.js file contains a simple logger built for the CDP Studio example case. - -1. Set up and run the Logger in CDP Studio. -(Refer to Help → Framework - Data Logging → How to Setup Logging in Automation System) -https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html - -2. Run the value.js file from the command line: - -```bash -node examples/value.js -``` - -For usage related to events run: - -```bash -node examples/event.js -``` - - -## Contact - -Email: support@cdptech.com \ No newline at end of file diff --git a/logger/.github/workflows/test.yml b/logger/.github/workflows/test.yml deleted file mode 100644 index 52af724..0000000 --- a/logger/.github/workflows/test.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Run Jest Tests - -on: - push: - branches: [ '**' ] # Run on all branches - pull_request: - branches: [ '**' ] # Run on PRs targeting any branch - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '18' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run tests - run: npm test - - - name: Cleanup - if: always() - run: | - echo "Cleaning up..." - rm -rf node_modules - rm -rf .npm \ No newline at end of file diff --git a/logger/.gitignore b/logger/.gitignore deleted file mode 100644 index 527ea72..0000000 --- a/logger/.gitignore +++ /dev/null @@ -1,68 +0,0 @@ -# Dependencies -node_modules/ - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage -.grunt - -# Bower dependency directory -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons -build/Release - -# Dependency directories -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# next.js build output -.next - -# npm config file -.npmrc - -protos/ \ No newline at end of file diff --git a/logger/DOCUMENTATION.md b/logger/DOCUMENTATION.md index b6ca351..03f25a1 100644 --- a/logger/DOCUMENTATION.md +++ b/logger/DOCUMENTATION.md @@ -1,301 +1,74 @@ -# JavaScript CDP Logger Client +# CDP Logger Client — Background -**JavaScript CDP Logger Client** is an open-source library for interfacing with CDP Studio applications that use the **CDP Logger** component. It allows you to monitor and retrieve historical data (logged signal values) and system events from a running CDP application via WebSocket. The library works seamlessly in both Node.js and browser environments (e.g. it can be integrated into a Vue.js frontend) and requires a CDP Logger server to be running in your CDP Studio system. +This document provides background on the CDP Logger data query protocol. For API reference and usage examples, see the [README](../README.rst). -## Quickstart +## What the CDP Logger Does -For a quickstart guide, see the [QUICKSTART.md](QUICKSTART.md) file. +In CDP Studio, the **CDPLogger** component logs selected signal values and system events for long-term storage. It stores data in a local database (SQLite via CDPCompactDatastore) and serves it over a protobuf-based WebSocket API. Each logged signal produces time-series data with min, max, and last values per sample interval. -## Overview and Purpose +The logger client provides: -In **CDP Studio**, the CDP Logger component is responsible for logging selected values (signals) and events from your system for long-term storage ([Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html#:~:text=The%20CDP%20Logger%20is%20a,file%20or%20a%20remote%20server)). This client library connects to that CDP Logger (or an external LogServer) over WebSocket and uses CDP's protobuf-based API to query the logged data. The purpose of the library is to provide an easy JavaScript interface to: +- **Logged signal discovery** — list what signals are being logged, with their names, paths, and custom tags (unit, description, etc.). +- **Historical data queries** — retrieve time-series data points for one or more signals over a time range, with optional downsampling or full resolution. +- **Event queries** — retrieve and filter system events (alarms, state changes) by sender, data fields, event codes, and time range. +- **Time synchronization** — automatic clock offset calculation between client and server to align timestamps. +- **Node.js and browser support** — works in both environments using the same API. -- List what signals are being logged (and their metadata) -- Read historical data points for those signals (e.g. for plotting trends) -- Retrieve logged events from the system (with filtering options) -- Handle connection details like reconnection and time synchronization +For more information, see [CDP Logger Documentation](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html) and [Configuration Example](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html). -By using this library, developers can build dashboards, monitoring tools, or scripts that interact with a live CDP system's historical data **without** needing to manually handle low-level WebSocket messaging or protobuf encoding. This README will guide you through the features, setup, and usage of the library. +## Connection Methods -## Key Features +### Proxy Discovery (CDP 5.1+, Recommended) -- **Connect to CDP Logger via WebSocket:** Easily connect to a running CDP Logger or LogServer by specifying its host/port (e.g. `ws://127.0.0.1:17000`). The client handles establishing the WebSocket connection and managing message encoding/decoding. +The `client.logger()` method discovers CDPLogger services via the StudioAPI proxy protocol. The logger registers as a `websocketproxy` service with `proxy_type: "logserver"`, and the client finds it in `ServicesNotification`. The logger protocol is tunneled through the existing StudioAPI WebSocket — no separate port or connection is needed. -- **Retrieve Logged Values:** Query the list of logged signals (nodes) from the CDP Logger (equivalent to the Logger's *LoggedValues* table in CDP Studio). Each logged node entry includes its name, full path (routing), and any associated tags/metadata (like engineering unit or description). You can also request historical data points for one or multiple signals over a time range. For example, you can fetch a downsampled series of values between a start and end timestamp, or even full-resolution data if needed. +This works across sibling applications: if CDPLogger runs on a different app than the one the client connects to, discovery still works because the client searches all proxy connections. -- **Event Logging and Querying:** Fetch historical **events** logged by the CDP Logger. By default, CDP Logger captures all system events ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=The%20CDP%20Logger%20is%20a,for%20logging%20a%20sine%20signal)), and this client allows you to query those events with powerful filtering options. You can filter by event sender (source component), by event data fields (supports wildcard matching on text fields), by event codes or severity, and by time ranges. The API provides methods to either count events matching a query or retrieve the event details. Retrieved events include timestamp, sender, event data (which may be structured data or messages), and tags (metadata) for the event source. +### Direct WebSocket (CDP 4.3+) -- **Tag Support:** Supports **Node Tags** for logged values and event sender tags. If your CDP system defines custom tags (metadata) for signals (e.g. unit, description) or for event sources, the client will fetch and include this information in the results. For example, when you list logged nodes via this client, you'll get any custom tag values (and their source) associated with each node. This was introduced in newer CDP versions (CDP 4.12 / API v4.0) and is fully supported by the library. +The standalone `studio.logger.Client("host:port")` connects directly to the CDPLogger's WebSocket port (configured as `ServerPort` in CDP Studio, typically 17000). This bypasses StudioAPI authentication and requires the port to be reachable from the client. Browser security settings often reject connections to non-standard ports, especially over HTTPS. -- **Time Synchronization:** The client automatically synchronizes time with the server to account for clock drift. On each data or event query, it can perform a quick time exchange with the server to calculate the offset (`timeDiff`) between the client's clock and the CDP Logger's clock. This ensures that timestamp-based queries (for data points or events) align correctly with the logger's timeline. Time sync is enabled by default and can be toggled on/off in case you want to use the client's local time only. +## Data Query Details -- **Automatic Reconnection:** If the WebSocket connection drops, the client can automatically attempt to reconnect (this is enabled by default). Upon reconnect, it will also resend any pending requests that were queued while the connection was down, so your application can recover seamlessly from transient network issues. You can disable auto-reconnect by passing `autoReconnect=false` when creating the client if you prefer to handle disconnections manually. +### Data Point Downsampling -- **Node.js and Browser Support:** The library is designed to work in Node.js (for back-end scripts or services) as well as in the browser (front-end web applications). In Node.js, it uses the popular `ws` package for WebSocket support, and in browsers it uses the native `WebSocket` API. The codebase is written in plain JavaScript, and a usage example with **Vue.js** is provided to demonstrate integration in a web UI (see below). +When `noOfDataPoints > 0`, the server divides the requested time range into that many intervals and returns one aggregated sample per interval with `{ min, max, last }` values. Setting `noOfDataPoints = 0` returns full resolution data (every logged sample). -- **Built on Protocol Buffers:** Communication with the CDP Logger uses Protocol Buffers (protobuf) messages defined by CDP. This library includes the necessary protobuf definitions (for container messages, data requests/responses, event queries, etc.), using the [`protobufjs`](https://www.npmjs.com/package/protobufjs) library under the hood. You don't need to manually deal with proto files – the library handles serialization and parsing of messages into easy-to-use JavaScript objects. +For large time ranges, full resolution queries can return very large result sets. The server limits responses to 50,000 rows (API 3.2+). For larger data sets, query in patches by advancing `startS` through the time range. -- **Logging API Version Support:** The client is compatible with CDP Logger API version 3.0 and above (CDP 4.3+). It implements newer API features such as event querying and node tags (available in API v4.0, CDP 4.12) while maintaining backward compatibility with the core functions from earlier versions. You can always check the logger's API version by calling `client.requestApiVersion()` to ensure the server supports certain features. +### Event Query Filtering -## Installation +Events can be filtered by multiple criteria simultaneously: -### Via npm +- **Sender conditions** — match the event source path. Each condition has a `value` (string) and `matchType` (`Exact` or `Wildcard`). Wildcard uses `*` for any characters. +- **Data conditions** — match fields within the event's data payload. Keys are field names (e.g. `"Text"`), values are arrays of match strings (wildcard by default). +- **Code mask** — bitwise filter on event codes. Common codes: `AlarmSet (0x1)`, `AlarmClr (0x2)`, `AlarmAck (0x4)`, `AlarmReprise (0x40)`, `SourceObjectUnavailable (0x100)`, `NodeBoot (0x40000000)`. +- **Time range** — `timeRangeBegin` and `timeRangeEnd` in seconds (epoch). Combine with `UseLogStampForTimeRange` flag to use the logger's log timestamp instead of the event timestamp. -You can install the library from npm: +### Time Synchronization -```bash -npm install cdplogger-client -``` +The client calculates the clock offset between itself and the server by exchanging timestamp messages. This `timeDiff` is applied to `requestLogLimits()` and `requestDataPoints()` results so that time ranges align with the client's clock. Disable with `setEnableTimeSync(false)` to get raw server timestamps. -This will add the CDP Logger client to your project's dependencies. The package bundles the necessary JavaScript files, protobuf definitions, and the `ws` WebSocket implementation used in Node.js. No additional peer dependencies are required. +### Node Tags -### In Browser (direct script include) +Logged nodes can have custom tags (key-value metadata such as unit or description), available since API 4.0 (CDP 4.12). Tags are returned by `requestLoggedNodes()` as `{ name, routing, tags }` where `tags` is an object mapping tag names to `{ value, source }`. Event senders also have tags, accessible via `getSenderTags(sender)`. -If you are not using a module bundler and prefer to include the library via ` - - - - -``` +## Resources -Once these are included, a global object `cdplogger` will be available, through which you can create a client and use the API. You'll also need to access the protobuf definitions from the global scope: - -```js -// Access protobuf definitions from global scope -const root = window.root; -const Container = root.DBMessaging.Protobuf.Container; -const CDPValueType = root.ICD.Protobuf.CDPValueType; -const EventQuery = root.DBMessaging.Protobuf.EventQuery; -``` - -## Prerequisites - -Before using the CDP Logger Client, make sure you have the following: - -- **CDP Studio and a Running CDP Application** – You need a CDP Studio project/application running that includes a **CDPLogger** component (or a standalone **LogServer**) configured to log data. Ensure that the logger is active and has a network port open for the WebSocket connections. Typically, the CDP Logger's server port is configured in the CDP Studio project (for example, it might default to 17000, but confirm in your project settings). The application should also have some signals added to the logger's Logged Values, otherwise there's no data to retrieve. *(See CDP Studio's documentation on how to add signals to the logger, e.g. by right-clicking a signal and selecting "Add to Logger" ([How to Setup Logging in Automation System | Framework - Data Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html#:~:text=)).)* Also, if you want to retrieve events, ensure that **Event Logging** is enabled on the CDP Logger (it is true by default ([Event Logging](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html#event-logging))). - -- **Node.js environment (for Node usage)** – If you plan to use this library in Node.js, you should have Node.js installed. - -- **Modern Web Browser (for browser usage)** – If using in a web frontend, ensure you are using a reasonably modern browser that supports WebSockets (virtually all modern browsers do) and ES6 features. The library automatically uses the browser's native WebSocket API. The Vue.js example provided assumes an environment where you can run ES2015+ code ([Vue.js Example](https://cdpstudio.com/manual/cdp/examples/webui-demo.html)). - -- **ProtoBuf JS** – The library depends on `protobufjs` (included as an npm dependency). If you installed via npm and are using a bundler or Node, this will be installed automatically. If you are using direct script includes, include the `protobuf.min.js` as shown above. - -- **CDP Logger API Compatibility** – As noted, the target CDP Logger should be running a version that supports the queries you need. Basic data queries work on older versions (CDP 4.3+), but features like tags and advanced event filtering require newer CDP releases (CDP 4.12 for tags support, etc.). If you're running an older CDP version and some API calls fail or are not supported, consider upgrading CDP Studio or limiting to the supported features. - -## Setup and Configuration - -Below we detail how to set up and use the CDP Logger Client in both Node.js and browser environments, with code examples. - -### Using the Client in Node.js - -In Node.js, you will typically import (or require) the library and create a client instance pointing to your CDP Logger's address. - -**Example (Node.js):** - -```js -// 1. Install and import the CDP Logger Client -const cdplogger = require('cdplogger-client'); - -// 2. Create a client instance connecting to the logger endpoint - -// Replace the host and port with your CDP Logger's address. -const client = new cdplogger.Client('127.0.0.1:17000'); - -// 3. Use the client to query data. For example, get the logger version: -client.requestApiVersion() - .then(version => { - console.log("CDP Logger API Version:", version); - // E.g., might print "CDP Logger API Version: 4.0.0" - }) - .catch(err => { - console.error("Failed to get API version:", err); - }); - -// 4. Query the list of logged nodes (signals) and print their names: -client.requestLoggedNodes() - .then(nodes => { - console.log("Logged Nodes:"); - nodes.forEach(node => { - console.log(`- ${node.name} (Path: ${node.routing})`); - if (node.tags) { - // If tags are available (CDP 4.12+), print those as well - Object.entries(node.tags).forEach(([tagName, tagInfo]) => { - console.log(` Tag "${tagName}": ${tagInfo.value} (source: ${tagInfo.source})`); - }); - } - }); - }) - .catch(err => { - console.error("Error retrieving logged nodes:", err); - }); -``` - -A few notes on the above example: - -- The `Client` constructor takes the logger endpoint. You can provide it as `"host:port"` (as a string) or a full WebSocket URL (`"ws://host:port"` or `"wss://host:port"` for secure). If the `ws://` prefix is omitted, the library will prepend it automatically. In the example, `'127.0.0.1:17000'` becomes `ws://127.0.0.1:17000`. - - -- The client connects immediately upon instantiation. It will attempt to open the WebSocket and, if `autoReconnect` is true (default), keep trying if the connection is refused or lost. You can check `client.isOpen` to see if the connection is currently open. In the example, we simply make requests; if the socket isn't open yet, the library will queue the requests and send them once connected. - -- The API calls like `requestApiVersion()`, `requestLoggedNodes()` return Promises. You can also use `async/await` if you prefer. For instance, `const nodes = await client.requestLoggedNodes().catch(console.error);` inside an `async` function. - -- The `requestLoggedNodes()` call returns an array of node info objects. Each object has at least `{ name: string, routing: string }` and possibly a `tags` object if tags are supported and fetched. The `tags` object is a dictionary of tagName -> `{ value: any, source: string }`. For example, a node could have `node.tags.Unit = { value: "°C", source: "CDPStudio" }` indicating the engineering unit is degrees Celsius. - -You can also request historical **data points** for one or more signals using `client.requestDataPoints(nodeNames, startS, endS, noOfDataPoints, limit)`. For example: - -```js -const limits = await client.requestLogLimits(); -const start = limits.startS; -const end = limits.endS; -// Request 100 data points for signals "Temperature" and "Pressure" over the full range -const dataPoints = await client.requestDataPoints(["Temperature", "Pressure"], start, end, 100, 0); -dataPoints.forEach(point => { - console.log("Timestamp:", point.timestamp); - // Each point.value will contain an object with keys for each signal name: - // e.g., point.value["Temperature"] = { min: ..., max: ..., last: ... } - const tempData = point.value["Temperature"]; - if (tempData) { - console.log(` Temperature -> min: ${tempData.min}, max: ${tempData.max}, last: ${tempData.last}`); - } - const pressData = point.value["Pressure"]; - if (pressData) { - console.log(` Pressure -> min: ${pressData.min}, max: ${pressData.max}, last: ${pressData.last}`); - } -}); -``` - -The above demonstrates retrieving 100 aggregated data points between the earliest and latest logged times. Each data point might represent an interval of time within the range, with `min`, `max`, and `last` values of the signal during that interval (this is how the CDP Logger provides downsampled data). If you instead want full resolution data, you can specify `noOfDataPoints = 0` to get all points (be careful with performance if the range is large). You can also specify a `limit` (max number of points) separate from the number of intervals, as well as request specific aggregation methods. - -Finally, to retrieve **events**, you can use `client.requestEvents(query)` along with constructing a query object. You can also use `client.countEvents(query)` to just get the count. Here's a brief Node example for events: - -```js -// Helpful enums from the client for query construction -const { MatchType, EventQueryFlags } = cdplogger.Client; - -const query = { // Note: all query arguments are optional - senderConditions: [ - { value: "MyApp.AlarmManager", matchType: MatchType.Exact } - ], - dataConditions: { - // Assume events have a field "Text" and we want those containing "Overheat" - Text: ["Overheat*"] // '*' wildcard is the default option - }, - timeRangeBegin: Date.now()/1000 - 24*3600, // last 24 hours in seconds (if time filtering desired) - limit: 50, // max 50 events - offset: 0, // start from the first match - flags: EventQueryFlags.NewestFirst // get newest events first -}; - -const totalMatching = await client.countEvents(query); -console.log(`There are ${totalMatching} events matching the query conditions.`); -const events = await client.requestEvents(query); -events.forEach(evt => { - console.log(`Event at ${evt.timestampSec} from ${evt.sender}:`, evt.data); - if (evt.tags) { - console.log(" Sender tags:", evt.tags); - } -}); -``` - -In this example, we filter events whose sender matches "MyApp.AlarmManager*" and whose text contains "Overheat". We retrieve up to 50 of the most recent such events. Each `evt` has properties like `timestampSec` (epoch time), `sender` (string identifier of the source), `data` (often an object or message describing the event), and `tags` (metadata about the sender, if available). The `EventQueryFlags` and `MatchType` static enums are provided by the library to refine queries (e.g., `Wildcard` vs `Exact` matching). See the CDP Logger documentation for full details on event query parameters ([Event Query](https://cdpstudio.com/manual/cdp/cdp2sql/logmanager-eventquery.html)). - -When you are done with the client (in Node or browser), you can call `client.disconnect()` to close the WebSocket and stop any automatic reconnection attempts. In Node scripts that are meant to exit, make sure to call `disconnect()` or `process.exit()` after your queries finish, otherwise the process may stay alive waiting for the socket to close. - -### Using the Client in a Browser - -Using the client in a browser is similar, except you don't need to polyfill WebSocket (browsers have it natively) and you will access the library via the global `cdplogger` (if included via ` - - - - -``` - -As shown, the usage is very much the same as in Node. The `cdplogger.Client` class is the main entry point. In a browser context, you might integrate this with UI components or state management. For example, in a Vue.js app, you might call these client methods in a Vuex store or inside component lifecycle hooks to retrieve data and then render charts (as demonstrated in the included Vue example). The provided `model.js` (in this repository's examples) shows a more involved integration: it uses the client to load historical data for multiple sensors and plot them using Chart.js, and to fetch events (like alarms) to display in a list. You can refer to that for inspiration on how to bind the data to a frontend. - -A few browser-specific notes: - -- **CORS/WebSocket Policy:** WebSocket connections are not subject to the same-origin policy in the way XHR/Fetch are, but some environments might still require the server to accept the connection. The CDP Logger's WebSocket server should accept connections from any origin by default. If you encounter issues connecting from a web page, check if any firewall or network configuration is blocking the websocket port. - -- **Performance:** Retrieving a lot of data points or events in one go can be heavy for the browser. If you plan to visualize large data sets, consider using pagination (e.g., request events 100 at a time using `offset`) or downsampling data points via the `noOfDataPoints` parameter. The library itself streams the data efficiently, but rendering thousands of points in the DOM can be slow, so plan accordingly. - -## How to Run Tests - -This project includes a set of unit tests and simulation scripts to ensure the client works as expected. Tests are written using **Jest**. - -After you clone the repository and install dependencies (`npm install`), you can run the test suite with: - -```bash -npm test -``` - -This will run all the Jest tests. The tests cover various client behaviors, such as message parsing, time synchronization logic, and error handling. - -One notable test utility is the **time synchronization simulation** found in `tests/testTimeSync.js`. This script creates a dummy WebSocket (without a real server) and simulates responses to test how the client calculates the `timeDiff` between client and server clocks. It overrides the client's internal methods to inject fake time responses and prints out the results for verification. You can run this script manually (e.g., `node tests/testTimeSync.js`) to see a step-by-step log of time sync in action. The script will output logs showing the time difference calculations with time sync **enabled vs disabled**, helping validate that the mechanism works correctly. - -When contributing to the project (or if you modify the code), please run `npm test` to ensure all tests still pass. If you add new features, adding corresponding tests is highly appreciated. - -## Contribution Guidelines - -Contributions are welcome! If you have an idea for improvement or have found a bug, please open an issue on the GitHub repository to discuss it. If you'd like to contribute code or documentation: - -1. **Fork the repository** on GitHub and create a new branch for your changes. -2. Make your changes in your fork. If adding a feature or fixing a bug, try to add or update unit tests to cover your change. -3. Ensure the code style remains consistent with the project (we use common JavaScript best practices; if the project has an ESLint configuration, please run it). -4. Run the test suite (`npm test`) to confirm all tests pass. -5. Commit your changes with clear commit messages. -6. **Open a Pull Request** to the main repository, describing the changes and the motivation. The maintainers will review your PR and merge it after any discussions or adjustments. - -For significant changes, it's often good to discuss in an issue first to ensure the change aligns with the project goals. We aim to keep the library lightweight and focused on CDP Logger interactions. - -Also, make sure any contributions you submit are your own work and that you're okay with releasing them under the project's MIT license. - -## License - -This project is open-source software licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. This means you are free to use, modify, and distribute this library in your own projects, even commercial ones, provided you include the copyright notice and license text in any redistribution. - -## Resources and Helpful Links - -- **CDP Studio Documentation – CDP Logger:** To understand the context and capabilities of the CDP Logger component, see the official CDP Studio documentation. The CDP Logger is described as a component for logging values and events for long-term storage. You can read more in the CDP Studio Manual under *Framework - Data Logging*. (Visit the [CDP Studio Docs website](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html). - -- **CDP Studio Official Website:** For more information about CDP Studio in general (the development environment, features, downloads, etc.), visit the [official CDP Studio website](https://cdpstudio.com). This site contains tutorials, user manuals, and other resources to help you get started with building applications in CDP Studio. - -- **Example Project:** For a complete example of how to use the CDP Logger Client in a Web environment Vue.js project, see the [Adding a Vue.js Web GUI to Automation System](https://cdpstudio.com/manual/cdp/examples/webui-demo.html). - -- **GitHub Repository (Source Code):** You can find the source code for this library, report issues, and see example code on the project's GitHub page: [CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient). Feel free to star the repo and watch for updates. All development and issue tracking is done through GitHub. - -- **Contact (Support):** If you have questions or need help with the library, you can reach out to the maintainers via the CDP Technologies support email: **support@cdptech.com**. We encourage you to use the issue tracker on GitHub for bug reports and feature requests, but for direct support inquiries, email is available. - ---- - -*Thank you for using the JavaScript CDP Logger Client!* We hope this library makes it easier to integrate CDP Studio's powerful logging capabilities into your own tools and applications. ([GitHub - CDPTechnologies/JavascriptCDPLoggerClient](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient#:~:text=A%20simple%20JavaScript%20interface%20for,com)) \ No newline at end of file +- [CDP Logger Documentation](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html) +- [CDP Logger Configuration Example](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-example.html) +- [Vue.js Web GUI Example](https://cdpstudio.com/manual/cdp/examples/webui-demo.html) +- [CDP Studio Website](https://cdpstudio.com) +- [cdp-client GitHub Repository](https://github.com/CDPTechnologies/JavascriptCDPClient) +- Support: support@cdptech.com diff --git a/logger/LICENSE b/logger/LICENSE index bc893f4..58ff452 100644 --- a/logger/LICENSE +++ b/logger/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 CDP Technologies +Copyright (c) 2026 CDP Technologies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/logger/QUICKSTART.md b/logger/QUICKSTART.md deleted file mode 100644 index cefd842..0000000 --- a/logger/QUICKSTART.md +++ /dev/null @@ -1,167 +0,0 @@ -# Quick Start Guide – CDPLogger Client - -This guide demonstrates how to get started with the CDPLogger Client in both **Node.js** and **Browser** environments. The client automatically detects the environment and works seamlessly in both. - -## Documentation - -For documentation on the JS logger client see [DOCUMENTATION.md](DOCUMENTATION.md) - -## Overview - -The CDPLogger Client uses **automatic environment detection** to work in both Node.js and browser environments from a single source file: - -- **Node.js:** - - Automatically loads protobuf definitions using `require('./generated/containerPb.js')` - - Uses the `ws` package for WebSocket functionality (installed as a dependency) - - No manual setup required - -- **Browser:** - - Uses the browser's native WebSocket API - - Expects protobuf definitions to be available at `window.root` - - Requires including the containerPb.js script before the client - -## Installation - -### For Node.js - -```bash -npm install cdplogger-client -``` - -### For Browser - -Include the following scripts in your HTML: -- `protobuf.min.js` – for the ProtoBuf runtime. -- `containerPb.js` – which sets up `window.root` with your protobuf definitions -- `client.js` – the same file works in both Node.js and browser environments -- Instead of importing protobuf definitions via CommonJS, obtain them from the global scope: - ```js - const root = window.root; - const Container = root.DBMessaging.Protobuf.Container; - const CDPValueType = root.ICD.Protobuf.CDPValueType; - const EventQuery = root.DBMessaging.Protobuf.EventQuery; - ``` - -## Usage - -### Node.js Example - -```js -// Import the client -const cdplogger = require('cdplogger-client'); - -// Create a client instance (endpoint can be "127.0.0.1:17000" or "ws://127.0.0.1:17000") -const client = new cdplogger.Client('127.0.0.1:17000'); - -// List logged nodes (displaying name and routing information) -client.requestLoggedNodes().then(nodes => { - nodes.forEach(node => { - console.log(`Name: ${node.name}, Routing: ${node.routing}`); - }); - - // If we have nodes, request data points for the first one - if (nodes.length > 0) { - const nodeName = nodes[0].name; - console.log(`\nRequesting data points for node: ${nodeName}`); - - // Get log limits and request data points - client.requestLogLimits().then(limits => { - return client.requestDataPoints([nodeName], limits.startS, limits.endS, 10, 0); - }).then(dataPoints => { - console.log(`\nReceived ${dataPoints.length} data points:`); - dataPoints.forEach(point => { - console.log(`Timestamp: ${new Date(point.timestamp * 1000).toISOString()}`); - if (point.value && point.value[nodeName]) { - const val = point.value[nodeName]; - console.log(` Min: ${val.min}, Max: ${val.max}, Last: ${val.last}`); - } - }); - }).catch(err => { - console.error("Error retrieving data points:", err); - }); - } -}); - -// Disconnect after a short delay (for demonstration purposes) -setTimeout(() => { - client.disconnect(); - process.exit(0); -}, 5000); -``` - -*The client automatically detects the Node.js environment and uses the `ws` package for WebSocket functionality.* - -### Browser Example - -Create an HTML file that includes the necessary scripts. For example: - -```html - - - - - CDPLogger Client Quick Start - - - - - - - - - - - -``` - -*In the browser version, we use `window.location.hostname` to connect to the same host as the web page, with the default logger port 17000.* - -## Prerequisites - -- **CDP Studio:** Ensure a CDP Studio application is running with an active **CDPLogger** (or LogServer) on a known WebSocket port (e.g., 17000). -- **For Node.js:** No additional setup required - WebSocket support is automatically configured. -- **For Browser:** Ensure `containerPb.js` is available and sets up `window.root` with protobuf definitions. - -## Learn More - -- [Full README](https://github.com/CDPTechnologies/JavascriptCDPLoggerClient) -- [CDP Logger Documentation](https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-configuration-manual.html) diff --git a/logger/README.md b/logger/README.md deleted file mode 100644 index c89ec84..0000000 --- a/logger/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# CDP Logger Client - -A JavaScript client for reading historic data from systems created with the CDP Studio development platform. -For more information about CDP Studio, see https://cdpstudio.com/. -For more information about CDP Logger, see https://cdpstudio.com/manual/cdp/cdplogger/cdplogger-index.html. - -This client allows you to: -- Connect to a CDP Logger or LogServer component -- Request logged nodes and their metadata -- Retrieve data points for specific nodes -- Query events from the logger -- Get log limits and API version information - -## Installation - -```bash -npm install cdplogger-client -``` - -## Quick Start - -For a quick introduction, see the [QUICKSTART.md](QUICKSTART.md) guide. - -## Documentation - -For detailed documentation, see [DOCUMENTATION.md](DOCUMENTATION.md). - -## Usage - -### Node.js - -```javascript -const cdplogger = require('cdplogger-client'); - -const client = new cdplogger.Client('127.0.0.1:17000'); - -// List logged nodes -client.requestLoggedNodes().then(nodes => { - console.log("Available nodes:", nodes); -}); -``` - -### Browser - -```html - - - - - - - - - - - - -``` - -## Contact - -Email: support@cdptech.com - -## License - -MIT \ No newline at end of file diff --git a/logger/container.proto.js b/logger/container.proto.js new file mode 100644 index 0000000..1be43b0 --- /dev/null +++ b/logger/container.proto.js @@ -0,0 +1,64 @@ +const containerProtoText = ` +// This is the .proto file in Google Protocol Buffers format. +// When this file is compiled with Google Protocol Buffers compiler +// (https://code.google.com/p/protobuf/downloads/list), then Java/Python/C++ +// code is generated which contains methods for serializing and deserializing +// the messages contained in this .proto file. + +syntax = "proto2"; + +package DBMessaging.Protobuf; + +option optimize_for = LITE_RUNTIME; +option java_package = "no.icd.dbmessaging.protobuf"; + +import "database.proto"; + +/** Common union-style base type for all Protobuf messages in DB. */ +message Container { + enum Type { + eSignalInfoRequest = 1; + eSignalInfoResponse = 2; + eSignalDataRequest = 3; + eSignalDataResponse = 4; + eCriterionLimitsRequest = 5; + eCriterionLimitsResponse = 6; + eVersionRequest = 7; + eVersionResponse = 8; + eError = 9; + eTimeRequest = 10; + eTimeResponse = 11; + eEventSenderTagsRequest = 12; + eEventSenderTagsResponse = 13; + eCountEventsRequest = 14; + eCountEventsResponse = 15; + eEventsRequest = 16; + eEventsResponse = 17; + } + optional Type message_type = 1; + optional SignalInfoRequest signal_info_request = 2; + optional SignalInfoResponse signal_info_response = 3; + optional SignalDataRequest signal_data_request = 4; + optional SignalDataResponse signal_data_response = 5; + optional CriterionLimitsRequest criterion_limits_request = 6; + optional CriterionLimitsResponse criterion_limits_response = 7; + optional VersionRequest version_request = 8; + optional VersionResponse version_response = 9; + optional Error error = 10; + optional TimeRequest time_request = 11; + optional TimeResponse time_response = 12; + optional EventSenderTagsRequest event_sender_tags_request = 13; + optional EventSenderTagsResponse event_sender_tags_response = 14; + optional CountEventsRequest count_events_request = 15; + optional CountEventsResponse count_events_response = 16; + optional EventsRequest events_request = 17; + optional EventsResponse events_response = 18; + extensions 100 to max; +} +`; + +if (typeof module !== 'undefined' && module.exports) { + module.exports = containerProtoText; +} else if (typeof window !== 'undefined') { + window.containerProto = containerProtoText; +} diff --git a/logger/database.proto.js b/logger/database.proto.js new file mode 100644 index 0000000..96bd08f --- /dev/null +++ b/logger/database.proto.js @@ -0,0 +1,170 @@ +const databaseProtoText = ` +// This is the .proto file in Google Protocol Buffers format. +// When this file is compiled with Google Protocol Buffers compiler +// (https://code.google.com/p/protobuf/downloads/list), then Java/Python/C++ +// code is generated which contains methods for serializing and deserializing +// the messages contained in this .proto file. + +syntax = "proto2"; + +package DBMessaging.Protobuf; + +option optimize_for = LITE_RUNTIME; +option java_package = "no.icd.dbmessaging.protobuf"; + +import "variant.proto"; + +// Signal queries + +message SignalInfoRequest { + optional uint32 request_id = 1; +} + +message SignalInfoResponse { + optional uint32 request_id = 1; + repeated string name = 2; + repeated uint32 id = 3; + repeated ICD.Protobuf.CDPValueType type = 4; + repeated string path = 5; + repeated TagMap tagMap = 6; +} + +message TagInfo { + optional string value = 1; + optional string source = 2; +} + +message TagMap { + map tags = 1; +} + +message SignalDataRequest { + optional uint32 request_id = 1; + repeated uint32 signal_id = 2; + optional double criterion_min = 3; + optional double criterion_max = 4; + optional uint32 num_of_datapoints = 5; // requested resolution + optional uint32 limit = 6; // Return the first 'n' rows of the query result +} + +message SignalDataResponse { + optional uint32 request_id = 1; // corresponds to SignalDataRequest::request_id + repeated double criterion = 2; + repeated SignalDataRow row = 3; +} + +message SignalDataRow { + repeated uint32 signal_id = 1; + repeated ICD.Protobuf.VariantValue min_values = 2; + repeated ICD.Protobuf.VariantValue max_values = 3; + repeated ICD.Protobuf.VariantValue last_values = 4; +} + +message CriterionLimitsRequest { + optional uint32 request_id = 1; +} + +message CriterionLimitsResponse { + optional uint32 request_id = 1; // corresponds to CriterionLimitsRequest::request_id + optional double criterion_min = 2; + optional double criterion_max = 3; +} + +// Event queries + +message Event { + optional string sender = 1; + map data = 2; + optional double timestamp_sec = 3; + optional uint64 id = 4; + optional uint32 code = 5; + optional uint32 status = 6; + optional double logstamp_sec = 7; +} + +message EventQuery { + enum MatchType { + Exact = 0; + Wildcard = 1; + } + + message Condition { + optional string value = 1; + optional MatchType type = 2; + } + + message ConditionList { + repeated Condition conditions = 1; + } + + optional double time_range_begin = 1; + optional double time_range_end = 2; + optional uint32 code_mask = 3; + optional uint32 limit = 4; + optional uint32 offset = 5; + optional uint32 flags = 6; + optional ConditionList sender_conditions = 7; + map data_conditions = 8; +} + +message EventSenderTagsRequest { + optional uint32 request_id = 1; +} + +message EventSenderTagsResponse { + optional uint32 request_id = 1; + map sender_tags = 2; +} + +message CountEventsRequest { + optional uint32 request_id = 1; + optional EventQuery query = 2; +} + +message CountEventsResponse { + optional uint32 request_id = 1; + optional int64 count = 2; +} + +message EventsRequest { + optional uint32 request_id = 1; + optional EventQuery query = 2; +} + +message EventsResponse { + optional uint32 request_id = 1; + repeated Event events = 2; +} + +// Server info queries + +message VersionRequest { + optional uint32 request_id = 1; +} + +message VersionResponse { + optional uint32 request_id = 1; + optional string version = 2; +} + +message Error { + optional uint32 request_id = 1; + optional string errorMessage = 2; + optional int32 errorCode = 3; +} + +message TimeRequest { + optional uint32 request_id = 1; +} + +message TimeResponse { + optional uint32 request_id = 1; + optional fixed64 timestamp = 2; // nanoseconds +} +`; + +if (typeof module !== 'undefined' && module.exports) { + module.exports = databaseProtoText; +} else if (typeof window !== 'undefined') { + window.databaseProto = databaseProtoText; +} diff --git a/logger/examples/event.js b/logger/examples/event.js index fb67f34..d7fed0a 100644 --- a/logger/examples/event.js +++ b/logger/examples/event.js @@ -1,70 +1,38 @@ -// event.js -// An example script to see filtered events +// event.js — Query events via service discovery +// +// Usage: node event.js [host:port] +// Default connects to 127.0.0.1:7689 -const cdplogger = require('../client'); +var studio = require('../../index.js'); +var EventQueryFlags = studio.logger.Client.EventQueryFlags; -const { EventQueryFlags, MatchType } = cdplogger.Client; +var address = process.argv[2] || '127.0.0.1:7689'; +var client = new studio.api.Client(address); - -async function main() { - const client = new cdplogger.Client('127.0.0.1:17000', true); - - try { - console.log("Waiting for connection to establish..."); - // Wait a bit to allow the connection to be established - await new Promise(resolve => setTimeout(resolve, 2000)); - - // Build the query with a limit and offset - const query = { - senderConditions: [{ - value: "CDPLoggerDemoApp.InvalidLicense", - matchType: MatchType.Exact - }], - dataConditions: { - Text: ["Invalid*"], // Wildcard is the default - // Multiple data conditions can be specified - }, - limit: 100, - offset: 0, - flags: EventQueryFlags.NewestFirst | EventQueryFlags.UseLogStampForTimeRange - }; - - console.log("Counting matching events..."); - const totalCount = await client.countEvents(query); - console.log(`Total matching events count: ${totalCount}`); - - console.log("Sending event query..."); - console.log("Query:", JSON.stringify(query, null, 2)); - - const events = await client.requestEvents(query); - console.log(`Received ${events.length} events`); - - if (events.length > 0) { - console.log('\nEvents:'); - events.forEach(event => { - // If event.data is a string, parse it; otherwise assume it's already an object. - const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data; - console.log(JSON.stringify({ - timestamp: event.timestampSec, - sender: event.sender, - data: data, - // The event tags will be attached (or requested if not yet available) - tags: event.tags - }, null, 2)); - }); - } - - } catch (error) { - console.error('Error:', error); - console.error('Stack:', error.stack); - } finally { - console.log("Disconnecting from CDP Logger..."); - client.disconnect(); - process.exit(0); - } -} - -main().catch(error => { - console.error("Unhandled error:", error); +client.logger().then(function(logger) { + return logger.countEvents({}).then(function(count) { + console.log('Total events: ' + count); + return logger.requestEvents({ + limit: 20, + flags: EventQueryFlags.NewestFirst + }); + }).then(function(events) { + console.log('\nLatest ' + events.length + ' events:\n'); + events.forEach(function(event) { + var code = logger.getEventCodeString(event.code); + console.log(new Date(event.timestampSec * 1000).toISOString() + + ' [' + (code || event.code) + '] ' + + event.sender); + if (event.data && event.data.Text) { + console.log(' ' + event.data.Text); + } + }); + }); +}).then(function() { + client.close(); + process.exit(0); +}).catch(function(err) { + console.error('Error:', err); + client.close(); process.exit(1); }); diff --git a/logger/examples/value.js b/logger/examples/value.js index 149be14..0e96f8b 100644 --- a/logger/examples/value.js +++ b/logger/examples/value.js @@ -1,73 +1,45 @@ -// value.js -// Example demonstration showing how to retrieve logged node data - -const cdplogger = require('../client'); - -// Print the node information (name, routing, and tags) -function printLoggedNodes() { - client.requestLoggedNodes() - .then(nodes => { - console.log("Connected nodes:"); - nodes.forEach(node => { - console.log(`Name: ${node.name}, Routing: ${node.routing}`); - if (node.tags) { - console.log("Tags:"); - Object.entries(node.tags).forEach(([key, tagInfo]) => { - console.log(` ${key}: value=${tagInfo.value}, source=${tagInfo.source}`); - }); - } - console.log('--------------------'); - }); - }) - .catch(err => { - console.error("Error retrieving logged nodes:", err); - }); -} - -// Print data points for the "Output" node. -async function printDataPoints() { - try { - const limits = await client.requestLogLimits(); - console.log("Log limits received:", limits); - - const dataPoints = await client.requestDataPoints(["Output"], limits.startS, limits.endS, 25); - console.log("Data Points retrieved:"); - dataPoints.forEach(point => { - console.log(`Timestamp: ${point.timestamp}`); - if (point.value && point.value["Output"]) { - const val = point.value["Output"]; - console.log(`Min: ${val.min}`); - console.log(`Max: ${val.max}`); - console.log(`Last: ${val.last}`); - } else { - console.log("No data for 'Output':", point); +// value.js — Query historic data points via service discovery +// +// Usage: node value.js [host:port] +// Default connects to 127.0.0.1:7689 + +var studio = require('../../index.js'); + +var address = process.argv[2] || '127.0.0.1:7689'; +var client = new studio.api.Client(address); + +client.logger().then(function(logger) { + return logger.requestLoggedNodes().then(function(nodes) { + console.log('Logged nodes:'); + nodes.forEach(function(node) { + console.log(' ' + node.name + ' (' + node.routing + ')'); + if (node.tags) { + Object.keys(node.tags).forEach(function(key) { + console.log(' ' + key + ': ' + node.tags[key].value); + }); } - console.log('--------------------'); }); - } catch (err) { - console.error("Error retrieving data points:", err); - } -} - - -async function main() { - try { - printLoggedNodes(); - await printDataPoints(); - } catch (error) { - console.error("Error in main:", error); - } finally { - client.disconnect(); - process.exit(0); - } -} - -// Create a new client instance. (In this example, autoReconnect is disabled.) -const client = new cdplogger.Client('ws://127.0.0.1:17000', false); - -// Instead of overriding ws.onopen (which may cancel internal logic), -// add an event listener so that _onOpen is still called. -client.ws.addEventListener("open", () => { - console.log("WebSocket connection established."); - main(); + return logger.requestLogLimits(); + }).then(function(limits) { + console.log('\nLog range: ' + new Date(limits.startS * 1000).toISOString() + + ' to ' + new Date(limits.endS * 1000).toISOString()); + var nodeName = 'CPULoad'; + return logger.requestDataPoints([nodeName], limits.startS, limits.endS, 10, 0) + .then(function(points) { + console.log('\n' + nodeName + ' (' + points.length + ' points):'); + points.forEach(function(p) { + var v = p.value[nodeName]; + console.log(' ' + new Date(p.timestamp * 1000).toISOString() + + ' min=' + v.min.toFixed(4) + ' max=' + v.max.toFixed(4) + + ' last=' + v.last.toFixed(4)); + }); + }); + }); +}).then(function() { + client.close(); + process.exit(0); +}).catch(function(err) { + console.error('Error:', err); + client.close(); + process.exit(1); }); diff --git a/logger/generated/containerPb.js b/logger/generated/containerPb.js deleted file mode 100644 index 303b8b0..0000000 --- a/logger/generated/containerPb.js +++ /dev/null @@ -1,7899 +0,0 @@ -// TODO Guide on how this file was generated -/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ -"use strict"; - -var $protobuf = require("protobufjs/minimal"); - -// Common aliases -var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; - -// Exported root namespace -var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); - -$root.DBMessaging = (function() { - - /** - * Namespace DBMessaging. - * @exports DBMessaging - * @namespace - */ - var DBMessaging = {}; - - DBMessaging.Protobuf = (function() { - - /** - * Namespace Protobuf. - * @memberof DBMessaging - * @namespace - */ - var Protobuf = {}; - - Protobuf.Container = (function() { - - /** - * Properties of a Container. - * @memberof DBMessaging.Protobuf - * @interface IContainer - * @property {DBMessaging.Protobuf.Container.Type|null} [messageType] Container messageType - * @property {DBMessaging.Protobuf.ISignalInfoRequest|null} [signalInfoRequest] Container signalInfoRequest - * @property {DBMessaging.Protobuf.ISignalInfoResponse|null} [signalInfoResponse] Container signalInfoResponse - * @property {DBMessaging.Protobuf.ISignalDataRequest|null} [signalDataRequest] Container signalDataRequest - * @property {DBMessaging.Protobuf.ISignalDataResponse|null} [signalDataResponse] Container signalDataResponse - * @property {DBMessaging.Protobuf.ICriterionLimitsRequest|null} [criterionLimitsRequest] Container criterionLimitsRequest - * @property {DBMessaging.Protobuf.ICriterionLimitsResponse|null} [criterionLimitsResponse] Container criterionLimitsResponse - * @property {DBMessaging.Protobuf.IVersionRequest|null} [versionRequest] Container versionRequest - * @property {DBMessaging.Protobuf.IVersionResponse|null} [versionResponse] Container versionResponse - * @property {DBMessaging.Protobuf.IError|null} [error] Container error - * @property {DBMessaging.Protobuf.ITimeRequest|null} [timeRequest] Container timeRequest - * @property {DBMessaging.Protobuf.ITimeResponse|null} [timeResponse] Container timeResponse - * @property {DBMessaging.Protobuf.IEventSenderTagsRequest|null} [eventSenderTagsRequest] Container eventSenderTagsRequest - * @property {DBMessaging.Protobuf.IEventSenderTagsResponse|null} [eventSenderTagsResponse] Container eventSenderTagsResponse - * @property {DBMessaging.Protobuf.ICountEventsRequest|null} [countEventsRequest] Container countEventsRequest - * @property {DBMessaging.Protobuf.ICountEventsResponse|null} [countEventsResponse] Container countEventsResponse - * @property {DBMessaging.Protobuf.IEventsRequest|null} [eventsRequest] Container eventsRequest - * @property {DBMessaging.Protobuf.IEventsResponse|null} [eventsResponse] Container eventsResponse - */ - - /** - * Constructs a new Container. - * @memberof DBMessaging.Protobuf - * @classdesc Common union-style base type for all Protobuf messages in DB. - * @implements IContainer - * @constructor - * @param {DBMessaging.Protobuf.IContainer=} [properties] Properties to set - */ - function Container(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Container messageType. - * @member {DBMessaging.Protobuf.Container.Type} messageType - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.messageType = 1; - - /** - * Container signalInfoRequest. - * @member {DBMessaging.Protobuf.ISignalInfoRequest|null|undefined} signalInfoRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.signalInfoRequest = null; - - /** - * Container signalInfoResponse. - * @member {DBMessaging.Protobuf.ISignalInfoResponse|null|undefined} signalInfoResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.signalInfoResponse = null; - - /** - * Container signalDataRequest. - * @member {DBMessaging.Protobuf.ISignalDataRequest|null|undefined} signalDataRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.signalDataRequest = null; - - /** - * Container signalDataResponse. - * @member {DBMessaging.Protobuf.ISignalDataResponse|null|undefined} signalDataResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.signalDataResponse = null; - - /** - * Container criterionLimitsRequest. - * @member {DBMessaging.Protobuf.ICriterionLimitsRequest|null|undefined} criterionLimitsRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.criterionLimitsRequest = null; - - /** - * Container criterionLimitsResponse. - * @member {DBMessaging.Protobuf.ICriterionLimitsResponse|null|undefined} criterionLimitsResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.criterionLimitsResponse = null; - - /** - * Container versionRequest. - * @member {DBMessaging.Protobuf.IVersionRequest|null|undefined} versionRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.versionRequest = null; - - /** - * Container versionResponse. - * @member {DBMessaging.Protobuf.IVersionResponse|null|undefined} versionResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.versionResponse = null; - - /** - * Container error. - * @member {DBMessaging.Protobuf.IError|null|undefined} error - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.error = null; - - /** - * Container timeRequest. - * @member {DBMessaging.Protobuf.ITimeRequest|null|undefined} timeRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.timeRequest = null; - - /** - * Container timeResponse. - * @member {DBMessaging.Protobuf.ITimeResponse|null|undefined} timeResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.timeResponse = null; - - /** - * Container eventSenderTagsRequest. - * @member {DBMessaging.Protobuf.IEventSenderTagsRequest|null|undefined} eventSenderTagsRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.eventSenderTagsRequest = null; - - /** - * Container eventSenderTagsResponse. - * @member {DBMessaging.Protobuf.IEventSenderTagsResponse|null|undefined} eventSenderTagsResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.eventSenderTagsResponse = null; - - /** - * Container countEventsRequest. - * @member {DBMessaging.Protobuf.ICountEventsRequest|null|undefined} countEventsRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.countEventsRequest = null; - - /** - * Container countEventsResponse. - * @member {DBMessaging.Protobuf.ICountEventsResponse|null|undefined} countEventsResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.countEventsResponse = null; - - /** - * Container eventsRequest. - * @member {DBMessaging.Protobuf.IEventsRequest|null|undefined} eventsRequest - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.eventsRequest = null; - - /** - * Container eventsResponse. - * @member {DBMessaging.Protobuf.IEventsResponse|null|undefined} eventsResponse - * @memberof DBMessaging.Protobuf.Container - * @instance - */ - Container.prototype.eventsResponse = null; - - /** - * Creates a new Container instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {DBMessaging.Protobuf.IContainer=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.Container} Container instance - */ - Container.create = function create(properties) { - return new Container(properties); - }; - - /** - * Encodes the specified Container message. Does not implicitly {@link DBMessaging.Protobuf.Container.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {DBMessaging.Protobuf.IContainer} message Container message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Container.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.messageType != null && Object.hasOwnProperty.call(message, "messageType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.messageType); - if (message.signalInfoRequest != null && Object.hasOwnProperty.call(message, "signalInfoRequest")) - $root.DBMessaging.Protobuf.SignalInfoRequest.encode(message.signalInfoRequest, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.signalInfoResponse != null && Object.hasOwnProperty.call(message, "signalInfoResponse")) - $root.DBMessaging.Protobuf.SignalInfoResponse.encode(message.signalInfoResponse, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.signalDataRequest != null && Object.hasOwnProperty.call(message, "signalDataRequest")) - $root.DBMessaging.Protobuf.SignalDataRequest.encode(message.signalDataRequest, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - if (message.signalDataResponse != null && Object.hasOwnProperty.call(message, "signalDataResponse")) - $root.DBMessaging.Protobuf.SignalDataResponse.encode(message.signalDataResponse, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.criterionLimitsRequest != null && Object.hasOwnProperty.call(message, "criterionLimitsRequest")) - $root.DBMessaging.Protobuf.CriterionLimitsRequest.encode(message.criterionLimitsRequest, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); - if (message.criterionLimitsResponse != null && Object.hasOwnProperty.call(message, "criterionLimitsResponse")) - $root.DBMessaging.Protobuf.CriterionLimitsResponse.encode(message.criterionLimitsResponse, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.versionRequest != null && Object.hasOwnProperty.call(message, "versionRequest")) - $root.DBMessaging.Protobuf.VersionRequest.encode(message.versionRequest, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.versionResponse != null && Object.hasOwnProperty.call(message, "versionResponse")) - $root.DBMessaging.Protobuf.VersionResponse.encode(message.versionResponse, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); - if (message.error != null && Object.hasOwnProperty.call(message, "error")) - $root.DBMessaging.Protobuf.Error.encode(message.error, writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim(); - if (message.timeRequest != null && Object.hasOwnProperty.call(message, "timeRequest")) - $root.DBMessaging.Protobuf.TimeRequest.encode(message.timeRequest, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - if (message.timeResponse != null && Object.hasOwnProperty.call(message, "timeResponse")) - $root.DBMessaging.Protobuf.TimeResponse.encode(message.timeResponse, writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim(); - if (message.eventSenderTagsRequest != null && Object.hasOwnProperty.call(message, "eventSenderTagsRequest")) - $root.DBMessaging.Protobuf.EventSenderTagsRequest.encode(message.eventSenderTagsRequest, writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); - if (message.eventSenderTagsResponse != null && Object.hasOwnProperty.call(message, "eventSenderTagsResponse")) - $root.DBMessaging.Protobuf.EventSenderTagsResponse.encode(message.eventSenderTagsResponse, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.countEventsRequest != null && Object.hasOwnProperty.call(message, "countEventsRequest")) - $root.DBMessaging.Protobuf.CountEventsRequest.encode(message.countEventsRequest, writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); - if (message.countEventsResponse != null && Object.hasOwnProperty.call(message, "countEventsResponse")) - $root.DBMessaging.Protobuf.CountEventsResponse.encode(message.countEventsResponse, writer.uint32(/* id 16, wireType 2 =*/130).fork()).ldelim(); - if (message.eventsRequest != null && Object.hasOwnProperty.call(message, "eventsRequest")) - $root.DBMessaging.Protobuf.EventsRequest.encode(message.eventsRequest, writer.uint32(/* id 17, wireType 2 =*/138).fork()).ldelim(); - if (message.eventsResponse != null && Object.hasOwnProperty.call(message, "eventsResponse")) - $root.DBMessaging.Protobuf.EventsResponse.encode(message.eventsResponse, writer.uint32(/* id 18, wireType 2 =*/146).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Container message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Container.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {DBMessaging.Protobuf.IContainer} message Container message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Container.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Container message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.Container} Container - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Container.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Container(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.messageType = reader.int32(); - break; - } - case 2: { - message.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.decode(reader, reader.uint32()); - break; - } - case 3: { - message.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.decode(reader, reader.uint32()); - break; - } - case 4: { - message.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.decode(reader, reader.uint32()); - break; - } - case 5: { - message.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.decode(reader, reader.uint32()); - break; - } - case 6: { - message.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.decode(reader, reader.uint32()); - break; - } - case 7: { - message.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.decode(reader, reader.uint32()); - break; - } - case 8: { - message.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.decode(reader, reader.uint32()); - break; - } - case 9: { - message.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.decode(reader, reader.uint32()); - break; - } - case 10: { - message.error = $root.DBMessaging.Protobuf.Error.decode(reader, reader.uint32()); - break; - } - case 11: { - message.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.decode(reader, reader.uint32()); - break; - } - case 12: { - message.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.decode(reader, reader.uint32()); - break; - } - case 13: { - message.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.decode(reader, reader.uint32()); - break; - } - case 14: { - message.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.decode(reader, reader.uint32()); - break; - } - case 15: { - message.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.decode(reader, reader.uint32()); - break; - } - case 16: { - message.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.decode(reader, reader.uint32()); - break; - } - case 17: { - message.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.decode(reader, reader.uint32()); - break; - } - case 18: { - message.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Container message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.Container} Container - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Container.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Container message. - * @function verify - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Container.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.messageType != null && message.hasOwnProperty("messageType")) - switch (message.messageType) { - default: - return "messageType: enum value expected"; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - break; - } - if (message.signalInfoRequest != null && message.hasOwnProperty("signalInfoRequest")) { - var error = $root.DBMessaging.Protobuf.SignalInfoRequest.verify(message.signalInfoRequest); - if (error) - return "signalInfoRequest." + error; - } - if (message.signalInfoResponse != null && message.hasOwnProperty("signalInfoResponse")) { - var error = $root.DBMessaging.Protobuf.SignalInfoResponse.verify(message.signalInfoResponse); - if (error) - return "signalInfoResponse." + error; - } - if (message.signalDataRequest != null && message.hasOwnProperty("signalDataRequest")) { - var error = $root.DBMessaging.Protobuf.SignalDataRequest.verify(message.signalDataRequest); - if (error) - return "signalDataRequest." + error; - } - if (message.signalDataResponse != null && message.hasOwnProperty("signalDataResponse")) { - var error = $root.DBMessaging.Protobuf.SignalDataResponse.verify(message.signalDataResponse); - if (error) - return "signalDataResponse." + error; - } - if (message.criterionLimitsRequest != null && message.hasOwnProperty("criterionLimitsRequest")) { - var error = $root.DBMessaging.Protobuf.CriterionLimitsRequest.verify(message.criterionLimitsRequest); - if (error) - return "criterionLimitsRequest." + error; - } - if (message.criterionLimitsResponse != null && message.hasOwnProperty("criterionLimitsResponse")) { - var error = $root.DBMessaging.Protobuf.CriterionLimitsResponse.verify(message.criterionLimitsResponse); - if (error) - return "criterionLimitsResponse." + error; - } - if (message.versionRequest != null && message.hasOwnProperty("versionRequest")) { - var error = $root.DBMessaging.Protobuf.VersionRequest.verify(message.versionRequest); - if (error) - return "versionRequest." + error; - } - if (message.versionResponse != null && message.hasOwnProperty("versionResponse")) { - var error = $root.DBMessaging.Protobuf.VersionResponse.verify(message.versionResponse); - if (error) - return "versionResponse." + error; - } - if (message.error != null && message.hasOwnProperty("error")) { - var error = $root.DBMessaging.Protobuf.Error.verify(message.error); - if (error) - return "error." + error; - } - if (message.timeRequest != null && message.hasOwnProperty("timeRequest")) { - var error = $root.DBMessaging.Protobuf.TimeRequest.verify(message.timeRequest); - if (error) - return "timeRequest." + error; - } - if (message.timeResponse != null && message.hasOwnProperty("timeResponse")) { - var error = $root.DBMessaging.Protobuf.TimeResponse.verify(message.timeResponse); - if (error) - return "timeResponse." + error; - } - if (message.eventSenderTagsRequest != null && message.hasOwnProperty("eventSenderTagsRequest")) { - var error = $root.DBMessaging.Protobuf.EventSenderTagsRequest.verify(message.eventSenderTagsRequest); - if (error) - return "eventSenderTagsRequest." + error; - } - if (message.eventSenderTagsResponse != null && message.hasOwnProperty("eventSenderTagsResponse")) { - var error = $root.DBMessaging.Protobuf.EventSenderTagsResponse.verify(message.eventSenderTagsResponse); - if (error) - return "eventSenderTagsResponse." + error; - } - if (message.countEventsRequest != null && message.hasOwnProperty("countEventsRequest")) { - var error = $root.DBMessaging.Protobuf.CountEventsRequest.verify(message.countEventsRequest); - if (error) - return "countEventsRequest." + error; - } - if (message.countEventsResponse != null && message.hasOwnProperty("countEventsResponse")) { - var error = $root.DBMessaging.Protobuf.CountEventsResponse.verify(message.countEventsResponse); - if (error) - return "countEventsResponse." + error; - } - if (message.eventsRequest != null && message.hasOwnProperty("eventsRequest")) { - var error = $root.DBMessaging.Protobuf.EventsRequest.verify(message.eventsRequest); - if (error) - return "eventsRequest." + error; - } - if (message.eventsResponse != null && message.hasOwnProperty("eventsResponse")) { - var error = $root.DBMessaging.Protobuf.EventsResponse.verify(message.eventsResponse); - if (error) - return "eventsResponse." + error; - } - return null; - }; - - /** - * Creates a Container message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.Container} Container - */ - Container.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.Container) - return object; - var message = new $root.DBMessaging.Protobuf.Container(); - switch (object.messageType) { - default: - if (typeof object.messageType === "number") { - message.messageType = object.messageType; - break; - } - break; - case "eSignalInfoRequest": - case 1: - message.messageType = 1; - break; - case "eSignalInfoResponse": - case 2: - message.messageType = 2; - break; - case "eSignalDataRequest": - case 3: - message.messageType = 3; - break; - case "eSignalDataResponse": - case 4: - message.messageType = 4; - break; - case "eCriterionLimitsRequest": - case 5: - message.messageType = 5; - break; - case "eCriterionLimitsResponse": - case 6: - message.messageType = 6; - break; - case "eVersionRequest": - case 7: - message.messageType = 7; - break; - case "eVersionResponse": - case 8: - message.messageType = 8; - break; - case "eError": - case 9: - message.messageType = 9; - break; - case "eTimeRequest": - case 10: - message.messageType = 10; - break; - case "eTimeResponse": - case 11: - message.messageType = 11; - break; - case "eEventSenderTagsRequest": - case 12: - message.messageType = 12; - break; - case "eEventSenderTagsResponse": - case 13: - message.messageType = 13; - break; - case "eCountEventsRequest": - case 14: - message.messageType = 14; - break; - case "eCountEventsResponse": - case 15: - message.messageType = 15; - break; - case "eEventsRequest": - case 16: - message.messageType = 16; - break; - case "eEventsResponse": - case 17: - message.messageType = 17; - break; - } - if (object.signalInfoRequest != null) { - if (typeof object.signalInfoRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.signalInfoRequest: object expected"); - message.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.fromObject(object.signalInfoRequest); - } - if (object.signalInfoResponse != null) { - if (typeof object.signalInfoResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.signalInfoResponse: object expected"); - message.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.fromObject(object.signalInfoResponse); - } - if (object.signalDataRequest != null) { - if (typeof object.signalDataRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.signalDataRequest: object expected"); - message.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.fromObject(object.signalDataRequest); - } - if (object.signalDataResponse != null) { - if (typeof object.signalDataResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.signalDataResponse: object expected"); - message.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.fromObject(object.signalDataResponse); - } - if (object.criterionLimitsRequest != null) { - if (typeof object.criterionLimitsRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.criterionLimitsRequest: object expected"); - message.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.fromObject(object.criterionLimitsRequest); - } - if (object.criterionLimitsResponse != null) { - if (typeof object.criterionLimitsResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.criterionLimitsResponse: object expected"); - message.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.fromObject(object.criterionLimitsResponse); - } - if (object.versionRequest != null) { - if (typeof object.versionRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.versionRequest: object expected"); - message.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.fromObject(object.versionRequest); - } - if (object.versionResponse != null) { - if (typeof object.versionResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.versionResponse: object expected"); - message.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.fromObject(object.versionResponse); - } - if (object.error != null) { - if (typeof object.error !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.error: object expected"); - message.error = $root.DBMessaging.Protobuf.Error.fromObject(object.error); - } - if (object.timeRequest != null) { - if (typeof object.timeRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.timeRequest: object expected"); - message.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.fromObject(object.timeRequest); - } - if (object.timeResponse != null) { - if (typeof object.timeResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.timeResponse: object expected"); - message.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.fromObject(object.timeResponse); - } - if (object.eventSenderTagsRequest != null) { - if (typeof object.eventSenderTagsRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.eventSenderTagsRequest: object expected"); - message.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.fromObject(object.eventSenderTagsRequest); - } - if (object.eventSenderTagsResponse != null) { - if (typeof object.eventSenderTagsResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.eventSenderTagsResponse: object expected"); - message.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.fromObject(object.eventSenderTagsResponse); - } - if (object.countEventsRequest != null) { - if (typeof object.countEventsRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.countEventsRequest: object expected"); - message.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.fromObject(object.countEventsRequest); - } - if (object.countEventsResponse != null) { - if (typeof object.countEventsResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.countEventsResponse: object expected"); - message.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.fromObject(object.countEventsResponse); - } - if (object.eventsRequest != null) { - if (typeof object.eventsRequest !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.eventsRequest: object expected"); - message.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.fromObject(object.eventsRequest); - } - if (object.eventsResponse != null) { - if (typeof object.eventsResponse !== "object") - throw TypeError(".DBMessaging.Protobuf.Container.eventsResponse: object expected"); - message.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.fromObject(object.eventsResponse); - } - return message; - }; - - /** - * Creates a plain object from a Container message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {DBMessaging.Protobuf.Container} message Container - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Container.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.messageType = options.enums === String ? "eSignalInfoRequest" : 1; - object.signalInfoRequest = null; - object.signalInfoResponse = null; - object.signalDataRequest = null; - object.signalDataResponse = null; - object.criterionLimitsRequest = null; - object.criterionLimitsResponse = null; - object.versionRequest = null; - object.versionResponse = null; - object.error = null; - object.timeRequest = null; - object.timeResponse = null; - object.eventSenderTagsRequest = null; - object.eventSenderTagsResponse = null; - object.countEventsRequest = null; - object.countEventsResponse = null; - object.eventsRequest = null; - object.eventsResponse = null; - } - if (message.messageType != null && message.hasOwnProperty("messageType")) - object.messageType = options.enums === String ? $root.DBMessaging.Protobuf.Container.Type[message.messageType] === undefined ? message.messageType : $root.DBMessaging.Protobuf.Container.Type[message.messageType] : message.messageType; - if (message.signalInfoRequest != null && message.hasOwnProperty("signalInfoRequest")) - object.signalInfoRequest = $root.DBMessaging.Protobuf.SignalInfoRequest.toObject(message.signalInfoRequest, options); - if (message.signalInfoResponse != null && message.hasOwnProperty("signalInfoResponse")) - object.signalInfoResponse = $root.DBMessaging.Protobuf.SignalInfoResponse.toObject(message.signalInfoResponse, options); - if (message.signalDataRequest != null && message.hasOwnProperty("signalDataRequest")) - object.signalDataRequest = $root.DBMessaging.Protobuf.SignalDataRequest.toObject(message.signalDataRequest, options); - if (message.signalDataResponse != null && message.hasOwnProperty("signalDataResponse")) - object.signalDataResponse = $root.DBMessaging.Protobuf.SignalDataResponse.toObject(message.signalDataResponse, options); - if (message.criterionLimitsRequest != null && message.hasOwnProperty("criterionLimitsRequest")) - object.criterionLimitsRequest = $root.DBMessaging.Protobuf.CriterionLimitsRequest.toObject(message.criterionLimitsRequest, options); - if (message.criterionLimitsResponse != null && message.hasOwnProperty("criterionLimitsResponse")) - object.criterionLimitsResponse = $root.DBMessaging.Protobuf.CriterionLimitsResponse.toObject(message.criterionLimitsResponse, options); - if (message.versionRequest != null && message.hasOwnProperty("versionRequest")) - object.versionRequest = $root.DBMessaging.Protobuf.VersionRequest.toObject(message.versionRequest, options); - if (message.versionResponse != null && message.hasOwnProperty("versionResponse")) - object.versionResponse = $root.DBMessaging.Protobuf.VersionResponse.toObject(message.versionResponse, options); - if (message.error != null && message.hasOwnProperty("error")) - object.error = $root.DBMessaging.Protobuf.Error.toObject(message.error, options); - if (message.timeRequest != null && message.hasOwnProperty("timeRequest")) - object.timeRequest = $root.DBMessaging.Protobuf.TimeRequest.toObject(message.timeRequest, options); - if (message.timeResponse != null && message.hasOwnProperty("timeResponse")) - object.timeResponse = $root.DBMessaging.Protobuf.TimeResponse.toObject(message.timeResponse, options); - if (message.eventSenderTagsRequest != null && message.hasOwnProperty("eventSenderTagsRequest")) - object.eventSenderTagsRequest = $root.DBMessaging.Protobuf.EventSenderTagsRequest.toObject(message.eventSenderTagsRequest, options); - if (message.eventSenderTagsResponse != null && message.hasOwnProperty("eventSenderTagsResponse")) - object.eventSenderTagsResponse = $root.DBMessaging.Protobuf.EventSenderTagsResponse.toObject(message.eventSenderTagsResponse, options); - if (message.countEventsRequest != null && message.hasOwnProperty("countEventsRequest")) - object.countEventsRequest = $root.DBMessaging.Protobuf.CountEventsRequest.toObject(message.countEventsRequest, options); - if (message.countEventsResponse != null && message.hasOwnProperty("countEventsResponse")) - object.countEventsResponse = $root.DBMessaging.Protobuf.CountEventsResponse.toObject(message.countEventsResponse, options); - if (message.eventsRequest != null && message.hasOwnProperty("eventsRequest")) - object.eventsRequest = $root.DBMessaging.Protobuf.EventsRequest.toObject(message.eventsRequest, options); - if (message.eventsResponse != null && message.hasOwnProperty("eventsResponse")) - object.eventsResponse = $root.DBMessaging.Protobuf.EventsResponse.toObject(message.eventsResponse, options); - return object; - }; - - /** - * Converts this Container to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.Container - * @instance - * @returns {Object.} JSON object - */ - Container.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Container - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.Container - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Container.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.Container"; - }; - - /** - * Type enum. - * @name DBMessaging.Protobuf.Container.Type - * @enum {number} - * @property {number} eSignalInfoRequest=1 eSignalInfoRequest value - * @property {number} eSignalInfoResponse=2 eSignalInfoResponse value - * @property {number} eSignalDataRequest=3 eSignalDataRequest value - * @property {number} eSignalDataResponse=4 eSignalDataResponse value - * @property {number} eCriterionLimitsRequest=5 eCriterionLimitsRequest value - * @property {number} eCriterionLimitsResponse=6 eCriterionLimitsResponse value - * @property {number} eVersionRequest=7 eVersionRequest value - * @property {number} eVersionResponse=8 eVersionResponse value - * @property {number} eError=9 eError value - * @property {number} eTimeRequest=10 eTimeRequest value - * @property {number} eTimeResponse=11 eTimeResponse value - * @property {number} eEventSenderTagsRequest=12 eEventSenderTagsRequest value - * @property {number} eEventSenderTagsResponse=13 eEventSenderTagsResponse value - * @property {number} eCountEventsRequest=14 eCountEventsRequest value - * @property {number} eCountEventsResponse=15 eCountEventsResponse value - * @property {number} eEventsRequest=16 eEventsRequest value - * @property {number} eEventsResponse=17 eEventsResponse value - */ - Container.Type = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[1] = "eSignalInfoRequest"] = 1; - values[valuesById[2] = "eSignalInfoResponse"] = 2; - values[valuesById[3] = "eSignalDataRequest"] = 3; - values[valuesById[4] = "eSignalDataResponse"] = 4; - values[valuesById[5] = "eCriterionLimitsRequest"] = 5; - values[valuesById[6] = "eCriterionLimitsResponse"] = 6; - values[valuesById[7] = "eVersionRequest"] = 7; - values[valuesById[8] = "eVersionResponse"] = 8; - values[valuesById[9] = "eError"] = 9; - values[valuesById[10] = "eTimeRequest"] = 10; - values[valuesById[11] = "eTimeResponse"] = 11; - values[valuesById[12] = "eEventSenderTagsRequest"] = 12; - values[valuesById[13] = "eEventSenderTagsResponse"] = 13; - values[valuesById[14] = "eCountEventsRequest"] = 14; - values[valuesById[15] = "eCountEventsResponse"] = 15; - values[valuesById[16] = "eEventsRequest"] = 16; - values[valuesById[17] = "eEventsResponse"] = 17; - return values; - })(); - - return Container; - })(); - - Protobuf.SignalInfoRequest = (function() { - - /** - * Properties of a SignalInfoRequest. - * @memberof DBMessaging.Protobuf - * @interface ISignalInfoRequest - * @property {number|null} [requestId] SignalInfoRequest requestId - */ - - /** - * Constructs a new SignalInfoRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a SignalInfoRequest. - * @implements ISignalInfoRequest - * @constructor - * @param {DBMessaging.Protobuf.ISignalInfoRequest=} [properties] Properties to set - */ - function SignalInfoRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SignalInfoRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @instance - */ - SignalInfoRequest.prototype.requestId = 0; - - /** - * Creates a new SignalInfoRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {DBMessaging.Protobuf.ISignalInfoRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest instance - */ - SignalInfoRequest.create = function create(properties) { - return new SignalInfoRequest(properties); - }; - - /** - * Encodes the specified SignalInfoRequest message. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {DBMessaging.Protobuf.ISignalInfoRequest} message SignalInfoRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalInfoRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - return writer; - }; - - /** - * Encodes the specified SignalInfoRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {DBMessaging.Protobuf.ISignalInfoRequest} message SignalInfoRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalInfoRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SignalInfoRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalInfoRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalInfoRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SignalInfoRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalInfoRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SignalInfoRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SignalInfoRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - return null; - }; - - /** - * Creates a SignalInfoRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.SignalInfoRequest} SignalInfoRequest - */ - SignalInfoRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.SignalInfoRequest) - return object; - var message = new $root.DBMessaging.Protobuf.SignalInfoRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - return message; - }; - - /** - * Creates a plain object from a SignalInfoRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {DBMessaging.Protobuf.SignalInfoRequest} message SignalInfoRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SignalInfoRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - return object; - }; - - /** - * Converts this SignalInfoRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @instance - * @returns {Object.} JSON object - */ - SignalInfoRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SignalInfoRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.SignalInfoRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SignalInfoRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.SignalInfoRequest"; - }; - - return SignalInfoRequest; - })(); - - Protobuf.SignalInfoResponse = (function() { - - /** - * Properties of a SignalInfoResponse. - * @memberof DBMessaging.Protobuf - * @interface ISignalInfoResponse - * @property {number|null} [requestId] SignalInfoResponse requestId - * @property {Array.|null} [name] SignalInfoResponse name - * @property {Array.|null} [id] SignalInfoResponse id - * @property {Array.|null} [type] SignalInfoResponse type - * @property {Array.|null} [path] SignalInfoResponse path - * @property {Array.|null} [tagMap] SignalInfoResponse tagMap - */ - - /** - * Constructs a new SignalInfoResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a SignalInfoResponse. - * @implements ISignalInfoResponse - * @constructor - * @param {DBMessaging.Protobuf.ISignalInfoResponse=} [properties] Properties to set - */ - function SignalInfoResponse(properties) { - this.name = []; - this.id = []; - this.type = []; - this.path = []; - this.tagMap = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SignalInfoResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.requestId = 0; - - /** - * SignalInfoResponse name. - * @member {Array.} name - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.name = $util.emptyArray; - - /** - * SignalInfoResponse id. - * @member {Array.} id - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.id = $util.emptyArray; - - /** - * SignalInfoResponse type. - * @member {Array.} type - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.type = $util.emptyArray; - - /** - * SignalInfoResponse path. - * @member {Array.} path - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.path = $util.emptyArray; - - /** - * SignalInfoResponse tagMap. - * @member {Array.} tagMap - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - */ - SignalInfoResponse.prototype.tagMap = $util.emptyArray; - - /** - * Creates a new SignalInfoResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {DBMessaging.Protobuf.ISignalInfoResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse instance - */ - SignalInfoResponse.create = function create(properties) { - return new SignalInfoResponse(properties); - }; - - /** - * Encodes the specified SignalInfoResponse message. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {DBMessaging.Protobuf.ISignalInfoResponse} message SignalInfoResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalInfoResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.name != null && message.name.length) - for (var i = 0; i < message.name.length; ++i) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.name[i]); - if (message.id != null && message.id.length) - for (var i = 0; i < message.id.length; ++i) - writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.id[i]); - if (message.type != null && message.type.length) - for (var i = 0; i < message.type.length; ++i) - writer.uint32(/* id 4, wireType 0 =*/32).int32(message.type[i]); - if (message.path != null && message.path.length) - for (var i = 0; i < message.path.length; ++i) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.path[i]); - if (message.tagMap != null && message.tagMap.length) - for (var i = 0; i < message.tagMap.length; ++i) - $root.DBMessaging.Protobuf.TagMap.encode(message.tagMap[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified SignalInfoResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalInfoResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {DBMessaging.Protobuf.ISignalInfoResponse} message SignalInfoResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalInfoResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SignalInfoResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalInfoResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalInfoResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - if (!(message.name && message.name.length)) - message.name = []; - message.name.push(reader.string()); - break; - } - case 3: { - if (!(message.id && message.id.length)) - message.id = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.id.push(reader.uint32()); - } else - message.id.push(reader.uint32()); - break; - } - case 4: { - if (!(message.type && message.type.length)) - message.type = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.type.push(reader.int32()); - } else - message.type.push(reader.int32()); - break; - } - case 5: { - if (!(message.path && message.path.length)) - message.path = []; - message.path.push(reader.string()); - break; - } - case 6: { - if (!(message.tagMap && message.tagMap.length)) - message.tagMap = []; - message.tagMap.push($root.DBMessaging.Protobuf.TagMap.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SignalInfoResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalInfoResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SignalInfoResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SignalInfoResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.name != null && message.hasOwnProperty("name")) { - if (!Array.isArray(message.name)) - return "name: array expected"; - for (var i = 0; i < message.name.length; ++i) - if (!$util.isString(message.name[i])) - return "name: string[] expected"; - } - if (message.id != null && message.hasOwnProperty("id")) { - if (!Array.isArray(message.id)) - return "id: array expected"; - for (var i = 0; i < message.id.length; ++i) - if (!$util.isInteger(message.id[i])) - return "id: integer[] expected"; - } - if (message.type != null && message.hasOwnProperty("type")) { - if (!Array.isArray(message.type)) - return "type: array expected"; - for (var i = 0; i < message.type.length; ++i) - switch (message.type[i]) { - default: - return "type: enum value[] expected"; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 100: - break; - } - } - if (message.path != null && message.hasOwnProperty("path")) { - if (!Array.isArray(message.path)) - return "path: array expected"; - for (var i = 0; i < message.path.length; ++i) - if (!$util.isString(message.path[i])) - return "path: string[] expected"; - } - if (message.tagMap != null && message.hasOwnProperty("tagMap")) { - if (!Array.isArray(message.tagMap)) - return "tagMap: array expected"; - for (var i = 0; i < message.tagMap.length; ++i) { - var error = $root.DBMessaging.Protobuf.TagMap.verify(message.tagMap[i]); - if (error) - return "tagMap." + error; - } - } - return null; - }; - - /** - * Creates a SignalInfoResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.SignalInfoResponse} SignalInfoResponse - */ - SignalInfoResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.SignalInfoResponse) - return object; - var message = new $root.DBMessaging.Protobuf.SignalInfoResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.name) { - if (!Array.isArray(object.name)) - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.name: array expected"); - message.name = []; - for (var i = 0; i < object.name.length; ++i) - message.name[i] = String(object.name[i]); - } - if (object.id) { - if (!Array.isArray(object.id)) - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.id: array expected"); - message.id = []; - for (var i = 0; i < object.id.length; ++i) - message.id[i] = object.id[i] >>> 0; - } - if (object.type) { - if (!Array.isArray(object.type)) - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.type: array expected"); - message.type = []; - for (var i = 0; i < object.type.length; ++i) - switch (object.type[i]) { - default: - if (typeof object.type[i] === "number") { - message.type[i] = object.type[i]; - break; - } - case "eUNDEFINED": - case 0: - message.type[i] = 0; - break; - case "eDOUBLE": - case 1: - message.type[i] = 1; - break; - case "eUINT64": - case 2: - message.type[i] = 2; - break; - case "eINT64": - case 3: - message.type[i] = 3; - break; - case "eFLOAT": - case 4: - message.type[i] = 4; - break; - case "eUINT": - case 5: - message.type[i] = 5; - break; - case "eINT": - case 6: - message.type[i] = 6; - break; - case "eUSHORT": - case 7: - message.type[i] = 7; - break; - case "eSHORT": - case 8: - message.type[i] = 8; - break; - case "eUCHAR": - case 9: - message.type[i] = 9; - break; - case "eCHAR": - case 10: - message.type[i] = 10; - break; - case "eBOOL": - case 11: - message.type[i] = 11; - break; - case "eSTRING": - case 12: - message.type[i] = 12; - break; - case "eUSERTYPE": - case 100: - message.type[i] = 100; - break; - } - } - if (object.path) { - if (!Array.isArray(object.path)) - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.path: array expected"); - message.path = []; - for (var i = 0; i < object.path.length; ++i) - message.path[i] = String(object.path[i]); - } - if (object.tagMap) { - if (!Array.isArray(object.tagMap)) - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.tagMap: array expected"); - message.tagMap = []; - for (var i = 0; i < object.tagMap.length; ++i) { - if (typeof object.tagMap[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.SignalInfoResponse.tagMap: object expected"); - message.tagMap[i] = $root.DBMessaging.Protobuf.TagMap.fromObject(object.tagMap[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a SignalInfoResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {DBMessaging.Protobuf.SignalInfoResponse} message SignalInfoResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SignalInfoResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.name = []; - object.id = []; - object.type = []; - object.path = []; - object.tagMap = []; - } - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.name && message.name.length) { - object.name = []; - for (var j = 0; j < message.name.length; ++j) - object.name[j] = message.name[j]; - } - if (message.id && message.id.length) { - object.id = []; - for (var j = 0; j < message.id.length; ++j) - object.id[j] = message.id[j]; - } - if (message.type && message.type.length) { - object.type = []; - for (var j = 0; j < message.type.length; ++j) - object.type[j] = options.enums === String ? $root.ICD.Protobuf.CDPValueType[message.type[j]] === undefined ? message.type[j] : $root.ICD.Protobuf.CDPValueType[message.type[j]] : message.type[j]; - } - if (message.path && message.path.length) { - object.path = []; - for (var j = 0; j < message.path.length; ++j) - object.path[j] = message.path[j]; - } - if (message.tagMap && message.tagMap.length) { - object.tagMap = []; - for (var j = 0; j < message.tagMap.length; ++j) - object.tagMap[j] = $root.DBMessaging.Protobuf.TagMap.toObject(message.tagMap[j], options); - } - return object; - }; - - /** - * Converts this SignalInfoResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @instance - * @returns {Object.} JSON object - */ - SignalInfoResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SignalInfoResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.SignalInfoResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SignalInfoResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.SignalInfoResponse"; - }; - - return SignalInfoResponse; - })(); - - Protobuf.TagInfo = (function() { - - /** - * Properties of a TagInfo. - * @memberof DBMessaging.Protobuf - * @interface ITagInfo - * @property {string|null} [value] TagInfo value - * @property {string|null} [source] TagInfo source - */ - - /** - * Constructs a new TagInfo. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a TagInfo. - * @implements ITagInfo - * @constructor - * @param {DBMessaging.Protobuf.ITagInfo=} [properties] Properties to set - */ - function TagInfo(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * TagInfo value. - * @member {string} value - * @memberof DBMessaging.Protobuf.TagInfo - * @instance - */ - TagInfo.prototype.value = ""; - - /** - * TagInfo source. - * @member {string} source - * @memberof DBMessaging.Protobuf.TagInfo - * @instance - */ - TagInfo.prototype.source = ""; - - /** - * Creates a new TagInfo instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {DBMessaging.Protobuf.ITagInfo=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.TagInfo} TagInfo instance - */ - TagInfo.create = function create(properties) { - return new TagInfo(properties); - }; - - /** - * Encodes the specified TagInfo message. Does not implicitly {@link DBMessaging.Protobuf.TagInfo.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {DBMessaging.Protobuf.ITagInfo} message TagInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TagInfo.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.value); - if (message.source != null && Object.hasOwnProperty.call(message, "source")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.source); - return writer; - }; - - /** - * Encodes the specified TagInfo message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TagInfo.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {DBMessaging.Protobuf.ITagInfo} message TagInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TagInfo.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TagInfo message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.TagInfo} TagInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TagInfo.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TagInfo(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.value = reader.string(); - break; - } - case 2: { - message.source = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TagInfo message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.TagInfo} TagInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TagInfo.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TagInfo message. - * @function verify - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TagInfo.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!$util.isString(message.value)) - return "value: string expected"; - if (message.source != null && message.hasOwnProperty("source")) - if (!$util.isString(message.source)) - return "source: string expected"; - return null; - }; - - /** - * Creates a TagInfo message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.TagInfo} TagInfo - */ - TagInfo.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.TagInfo) - return object; - var message = new $root.DBMessaging.Protobuf.TagInfo(); - if (object.value != null) - message.value = String(object.value); - if (object.source != null) - message.source = String(object.source); - return message; - }; - - /** - * Creates a plain object from a TagInfo message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {DBMessaging.Protobuf.TagInfo} message TagInfo - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TagInfo.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.value = ""; - object.source = ""; - } - if (message.value != null && message.hasOwnProperty("value")) - object.value = message.value; - if (message.source != null && message.hasOwnProperty("source")) - object.source = message.source; - return object; - }; - - /** - * Converts this TagInfo to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.TagInfo - * @instance - * @returns {Object.} JSON object - */ - TagInfo.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TagInfo - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.TagInfo - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TagInfo.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.TagInfo"; - }; - - return TagInfo; - })(); - - Protobuf.TagMap = (function() { - - /** - * Properties of a TagMap. - * @memberof DBMessaging.Protobuf - * @interface ITagMap - * @property {Object.|null} [tags] TagMap tags - */ - - /** - * Constructs a new TagMap. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a TagMap. - * @implements ITagMap - * @constructor - * @param {DBMessaging.Protobuf.ITagMap=} [properties] Properties to set - */ - function TagMap(properties) { - this.tags = {}; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * TagMap tags. - * @member {Object.} tags - * @memberof DBMessaging.Protobuf.TagMap - * @instance - */ - TagMap.prototype.tags = $util.emptyObject; - - /** - * Creates a new TagMap instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {DBMessaging.Protobuf.ITagMap=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.TagMap} TagMap instance - */ - TagMap.create = function create(properties) { - return new TagMap(properties); - }; - - /** - * Encodes the specified TagMap message. Does not implicitly {@link DBMessaging.Protobuf.TagMap.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {DBMessaging.Protobuf.ITagMap} message TagMap message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TagMap.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tags != null && Object.hasOwnProperty.call(message, "tags")) - for (var keys = Object.keys(message.tags), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 1, wireType 2 =*/10).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.DBMessaging.Protobuf.TagInfo.encode(message.tags[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - return writer; - }; - - /** - * Encodes the specified TagMap message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TagMap.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {DBMessaging.Protobuf.ITagMap} message TagMap message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TagMap.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TagMap message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.TagMap} TagMap - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TagMap.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TagMap(), key, value; - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (message.tags === $util.emptyObject) - message.tags = {}; - var end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - var tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.DBMessaging.Protobuf.TagInfo.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.tags[key] = value; - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TagMap message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.TagMap} TagMap - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TagMap.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TagMap message. - * @function verify - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TagMap.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.tags != null && message.hasOwnProperty("tags")) { - if (!$util.isObject(message.tags)) - return "tags: object expected"; - var key = Object.keys(message.tags); - for (var i = 0; i < key.length; ++i) { - var error = $root.DBMessaging.Protobuf.TagInfo.verify(message.tags[key[i]]); - if (error) - return "tags." + error; - } - } - return null; - }; - - /** - * Creates a TagMap message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.TagMap} TagMap - */ - TagMap.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.TagMap) - return object; - var message = new $root.DBMessaging.Protobuf.TagMap(); - if (object.tags) { - if (typeof object.tags !== "object") - throw TypeError(".DBMessaging.Protobuf.TagMap.tags: object expected"); - message.tags = {}; - for (var keys = Object.keys(object.tags), i = 0; i < keys.length; ++i) { - if (typeof object.tags[keys[i]] !== "object") - throw TypeError(".DBMessaging.Protobuf.TagMap.tags: object expected"); - message.tags[keys[i]] = $root.DBMessaging.Protobuf.TagInfo.fromObject(object.tags[keys[i]]); - } - } - return message; - }; - - /** - * Creates a plain object from a TagMap message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {DBMessaging.Protobuf.TagMap} message TagMap - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TagMap.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.objects || options.defaults) - object.tags = {}; - var keys2; - if (message.tags && (keys2 = Object.keys(message.tags)).length) { - object.tags = {}; - for (var j = 0; j < keys2.length; ++j) - object.tags[keys2[j]] = $root.DBMessaging.Protobuf.TagInfo.toObject(message.tags[keys2[j]], options); - } - return object; - }; - - /** - * Converts this TagMap to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.TagMap - * @instance - * @returns {Object.} JSON object - */ - TagMap.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TagMap - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.TagMap - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TagMap.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.TagMap"; - }; - - return TagMap; - })(); - - Protobuf.SignalDataRequest = (function() { - - /** - * Properties of a SignalDataRequest. - * @memberof DBMessaging.Protobuf - * @interface ISignalDataRequest - * @property {number|null} [requestId] SignalDataRequest requestId - * @property {Array.|null} [signalId] SignalDataRequest signalId - * @property {number|null} [criterionMin] SignalDataRequest criterionMin - * @property {number|null} [criterionMax] SignalDataRequest criterionMax - * @property {number|null} [numOfDatapoints] SignalDataRequest numOfDatapoints - * @property {number|null} [limit] SignalDataRequest limit - */ - - /** - * Constructs a new SignalDataRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a SignalDataRequest. - * @implements ISignalDataRequest - * @constructor - * @param {DBMessaging.Protobuf.ISignalDataRequest=} [properties] Properties to set - */ - function SignalDataRequest(properties) { - this.signalId = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SignalDataRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.requestId = 0; - - /** - * SignalDataRequest signalId. - * @member {Array.} signalId - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.signalId = $util.emptyArray; - - /** - * SignalDataRequest criterionMin. - * @member {number} criterionMin - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.criterionMin = 0; - - /** - * SignalDataRequest criterionMax. - * @member {number} criterionMax - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.criterionMax = 0; - - /** - * SignalDataRequest numOfDatapoints. - * @member {number} numOfDatapoints - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.numOfDatapoints = 0; - - /** - * SignalDataRequest limit. - * @member {number} limit - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - */ - SignalDataRequest.prototype.limit = 0; - - /** - * Creates a new SignalDataRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {DBMessaging.Protobuf.ISignalDataRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest instance - */ - SignalDataRequest.create = function create(properties) { - return new SignalDataRequest(properties); - }; - - /** - * Encodes the specified SignalDataRequest message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {DBMessaging.Protobuf.ISignalDataRequest} message SignalDataRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.signalId != null && message.signalId.length) - for (var i = 0; i < message.signalId.length; ++i) - writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.signalId[i]); - if (message.criterionMin != null && Object.hasOwnProperty.call(message, "criterionMin")) - writer.uint32(/* id 3, wireType 1 =*/25).double(message.criterionMin); - if (message.criterionMax != null && Object.hasOwnProperty.call(message, "criterionMax")) - writer.uint32(/* id 4, wireType 1 =*/33).double(message.criterionMax); - if (message.numOfDatapoints != null && Object.hasOwnProperty.call(message, "numOfDatapoints")) - writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.numOfDatapoints); - if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) - writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.limit); - return writer; - }; - - /** - * Encodes the specified SignalDataRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {DBMessaging.Protobuf.ISignalDataRequest} message SignalDataRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SignalDataRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - if (!(message.signalId && message.signalId.length)) - message.signalId = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.signalId.push(reader.uint32()); - } else - message.signalId.push(reader.uint32()); - break; - } - case 3: { - message.criterionMin = reader.double(); - break; - } - case 4: { - message.criterionMax = reader.double(); - break; - } - case 5: { - message.numOfDatapoints = reader.uint32(); - break; - } - case 6: { - message.limit = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SignalDataRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SignalDataRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SignalDataRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.signalId != null && message.hasOwnProperty("signalId")) { - if (!Array.isArray(message.signalId)) - return "signalId: array expected"; - for (var i = 0; i < message.signalId.length; ++i) - if (!$util.isInteger(message.signalId[i])) - return "signalId: integer[] expected"; - } - if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) - if (typeof message.criterionMin !== "number") - return "criterionMin: number expected"; - if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) - if (typeof message.criterionMax !== "number") - return "criterionMax: number expected"; - if (message.numOfDatapoints != null && message.hasOwnProperty("numOfDatapoints")) - if (!$util.isInteger(message.numOfDatapoints)) - return "numOfDatapoints: integer expected"; - if (message.limit != null && message.hasOwnProperty("limit")) - if (!$util.isInteger(message.limit)) - return "limit: integer expected"; - return null; - }; - - /** - * Creates a SignalDataRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.SignalDataRequest} SignalDataRequest - */ - SignalDataRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.SignalDataRequest) - return object; - var message = new $root.DBMessaging.Protobuf.SignalDataRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.signalId) { - if (!Array.isArray(object.signalId)) - throw TypeError(".DBMessaging.Protobuf.SignalDataRequest.signalId: array expected"); - message.signalId = []; - for (var i = 0; i < object.signalId.length; ++i) - message.signalId[i] = object.signalId[i] >>> 0; - } - if (object.criterionMin != null) - message.criterionMin = Number(object.criterionMin); - if (object.criterionMax != null) - message.criterionMax = Number(object.criterionMax); - if (object.numOfDatapoints != null) - message.numOfDatapoints = object.numOfDatapoints >>> 0; - if (object.limit != null) - message.limit = object.limit >>> 0; - return message; - }; - - /** - * Creates a plain object from a SignalDataRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {DBMessaging.Protobuf.SignalDataRequest} message SignalDataRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SignalDataRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.signalId = []; - if (options.defaults) { - object.requestId = 0; - object.criterionMin = 0; - object.criterionMax = 0; - object.numOfDatapoints = 0; - object.limit = 0; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.signalId && message.signalId.length) { - object.signalId = []; - for (var j = 0; j < message.signalId.length; ++j) - object.signalId[j] = message.signalId[j]; - } - if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) - object.criterionMin = options.json && !isFinite(message.criterionMin) ? String(message.criterionMin) : message.criterionMin; - if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) - object.criterionMax = options.json && !isFinite(message.criterionMax) ? String(message.criterionMax) : message.criterionMax; - if (message.numOfDatapoints != null && message.hasOwnProperty("numOfDatapoints")) - object.numOfDatapoints = message.numOfDatapoints; - if (message.limit != null && message.hasOwnProperty("limit")) - object.limit = message.limit; - return object; - }; - - /** - * Converts this SignalDataRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @instance - * @returns {Object.} JSON object - */ - SignalDataRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SignalDataRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.SignalDataRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SignalDataRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataRequest"; - }; - - return SignalDataRequest; - })(); - - Protobuf.SignalDataResponse = (function() { - - /** - * Properties of a SignalDataResponse. - * @memberof DBMessaging.Protobuf - * @interface ISignalDataResponse - * @property {number|null} [requestId] SignalDataResponse requestId - * @property {Array.|null} [criterion] SignalDataResponse criterion - * @property {Array.|null} [row] SignalDataResponse row - */ - - /** - * Constructs a new SignalDataResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a SignalDataResponse. - * @implements ISignalDataResponse - * @constructor - * @param {DBMessaging.Protobuf.ISignalDataResponse=} [properties] Properties to set - */ - function SignalDataResponse(properties) { - this.criterion = []; - this.row = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SignalDataResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @instance - */ - SignalDataResponse.prototype.requestId = 0; - - /** - * SignalDataResponse criterion. - * @member {Array.} criterion - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @instance - */ - SignalDataResponse.prototype.criterion = $util.emptyArray; - - /** - * SignalDataResponse row. - * @member {Array.} row - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @instance - */ - SignalDataResponse.prototype.row = $util.emptyArray; - - /** - * Creates a new SignalDataResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {DBMessaging.Protobuf.ISignalDataResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse instance - */ - SignalDataResponse.create = function create(properties) { - return new SignalDataResponse(properties); - }; - - /** - * Encodes the specified SignalDataResponse message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {DBMessaging.Protobuf.ISignalDataResponse} message SignalDataResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.criterion != null && message.criterion.length) - for (var i = 0; i < message.criterion.length; ++i) - writer.uint32(/* id 2, wireType 1 =*/17).double(message.criterion[i]); - if (message.row != null && message.row.length) - for (var i = 0; i < message.row.length; ++i) - $root.DBMessaging.Protobuf.SignalDataRow.encode(message.row[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified SignalDataResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {DBMessaging.Protobuf.ISignalDataResponse} message SignalDataResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SignalDataResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - if (!(message.criterion && message.criterion.length)) - message.criterion = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.criterion.push(reader.double()); - } else - message.criterion.push(reader.double()); - break; - } - case 3: { - if (!(message.row && message.row.length)) - message.row = []; - message.row.push($root.DBMessaging.Protobuf.SignalDataRow.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SignalDataResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SignalDataResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SignalDataResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.criterion != null && message.hasOwnProperty("criterion")) { - if (!Array.isArray(message.criterion)) - return "criterion: array expected"; - for (var i = 0; i < message.criterion.length; ++i) - if (typeof message.criterion[i] !== "number") - return "criterion: number[] expected"; - } - if (message.row != null && message.hasOwnProperty("row")) { - if (!Array.isArray(message.row)) - return "row: array expected"; - for (var i = 0; i < message.row.length; ++i) { - var error = $root.DBMessaging.Protobuf.SignalDataRow.verify(message.row[i]); - if (error) - return "row." + error; - } - } - return null; - }; - - /** - * Creates a SignalDataResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.SignalDataResponse} SignalDataResponse - */ - SignalDataResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.SignalDataResponse) - return object; - var message = new $root.DBMessaging.Protobuf.SignalDataResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.criterion) { - if (!Array.isArray(object.criterion)) - throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.criterion: array expected"); - message.criterion = []; - for (var i = 0; i < object.criterion.length; ++i) - message.criterion[i] = Number(object.criterion[i]); - } - if (object.row) { - if (!Array.isArray(object.row)) - throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.row: array expected"); - message.row = []; - for (var i = 0; i < object.row.length; ++i) { - if (typeof object.row[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.SignalDataResponse.row: object expected"); - message.row[i] = $root.DBMessaging.Protobuf.SignalDataRow.fromObject(object.row[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a SignalDataResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {DBMessaging.Protobuf.SignalDataResponse} message SignalDataResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SignalDataResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.criterion = []; - object.row = []; - } - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.criterion && message.criterion.length) { - object.criterion = []; - for (var j = 0; j < message.criterion.length; ++j) - object.criterion[j] = options.json && !isFinite(message.criterion[j]) ? String(message.criterion[j]) : message.criterion[j]; - } - if (message.row && message.row.length) { - object.row = []; - for (var j = 0; j < message.row.length; ++j) - object.row[j] = $root.DBMessaging.Protobuf.SignalDataRow.toObject(message.row[j], options); - } - return object; - }; - - /** - * Converts this SignalDataResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @instance - * @returns {Object.} JSON object - */ - SignalDataResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SignalDataResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.SignalDataResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SignalDataResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataResponse"; - }; - - return SignalDataResponse; - })(); - - Protobuf.SignalDataRow = (function() { - - /** - * Properties of a SignalDataRow. - * @memberof DBMessaging.Protobuf - * @interface ISignalDataRow - * @property {Array.|null} [signalId] SignalDataRow signalId - * @property {Array.|null} [minValues] SignalDataRow minValues - * @property {Array.|null} [maxValues] SignalDataRow maxValues - * @property {Array.|null} [lastValues] SignalDataRow lastValues - */ - - /** - * Constructs a new SignalDataRow. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a SignalDataRow. - * @implements ISignalDataRow - * @constructor - * @param {DBMessaging.Protobuf.ISignalDataRow=} [properties] Properties to set - */ - function SignalDataRow(properties) { - this.signalId = []; - this.minValues = []; - this.maxValues = []; - this.lastValues = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SignalDataRow signalId. - * @member {Array.} signalId - * @memberof DBMessaging.Protobuf.SignalDataRow - * @instance - */ - SignalDataRow.prototype.signalId = $util.emptyArray; - - /** - * SignalDataRow minValues. - * @member {Array.} minValues - * @memberof DBMessaging.Protobuf.SignalDataRow - * @instance - */ - SignalDataRow.prototype.minValues = $util.emptyArray; - - /** - * SignalDataRow maxValues. - * @member {Array.} maxValues - * @memberof DBMessaging.Protobuf.SignalDataRow - * @instance - */ - SignalDataRow.prototype.maxValues = $util.emptyArray; - - /** - * SignalDataRow lastValues. - * @member {Array.} lastValues - * @memberof DBMessaging.Protobuf.SignalDataRow - * @instance - */ - SignalDataRow.prototype.lastValues = $util.emptyArray; - - /** - * Creates a new SignalDataRow instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {DBMessaging.Protobuf.ISignalDataRow=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow instance - */ - SignalDataRow.create = function create(properties) { - return new SignalDataRow(properties); - }; - - /** - * Encodes the specified SignalDataRow message. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRow.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {DBMessaging.Protobuf.ISignalDataRow} message SignalDataRow message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataRow.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.signalId != null && message.signalId.length) - for (var i = 0; i < message.signalId.length; ++i) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.signalId[i]); - if (message.minValues != null && message.minValues.length) - for (var i = 0; i < message.minValues.length; ++i) - $root.ICD.Protobuf.VariantValue.encode(message.minValues[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.maxValues != null && message.maxValues.length) - for (var i = 0; i < message.maxValues.length; ++i) - $root.ICD.Protobuf.VariantValue.encode(message.maxValues[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.lastValues != null && message.lastValues.length) - for (var i = 0; i < message.lastValues.length; ++i) - $root.ICD.Protobuf.VariantValue.encode(message.lastValues[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified SignalDataRow message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.SignalDataRow.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {DBMessaging.Protobuf.ISignalDataRow} message SignalDataRow message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SignalDataRow.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SignalDataRow message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataRow.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.SignalDataRow(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.signalId && message.signalId.length)) - message.signalId = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.signalId.push(reader.uint32()); - } else - message.signalId.push(reader.uint32()); - break; - } - case 2: { - if (!(message.minValues && message.minValues.length)) - message.minValues = []; - message.minValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); - break; - } - case 3: { - if (!(message.maxValues && message.maxValues.length)) - message.maxValues = []; - message.maxValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); - break; - } - case 4: { - if (!(message.lastValues && message.lastValues.length)) - message.lastValues = []; - message.lastValues.push($root.ICD.Protobuf.VariantValue.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SignalDataRow message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SignalDataRow.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SignalDataRow message. - * @function verify - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SignalDataRow.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.signalId != null && message.hasOwnProperty("signalId")) { - if (!Array.isArray(message.signalId)) - return "signalId: array expected"; - for (var i = 0; i < message.signalId.length; ++i) - if (!$util.isInteger(message.signalId[i])) - return "signalId: integer[] expected"; - } - if (message.minValues != null && message.hasOwnProperty("minValues")) { - if (!Array.isArray(message.minValues)) - return "minValues: array expected"; - for (var i = 0; i < message.minValues.length; ++i) { - var error = $root.ICD.Protobuf.VariantValue.verify(message.minValues[i]); - if (error) - return "minValues." + error; - } - } - if (message.maxValues != null && message.hasOwnProperty("maxValues")) { - if (!Array.isArray(message.maxValues)) - return "maxValues: array expected"; - for (var i = 0; i < message.maxValues.length; ++i) { - var error = $root.ICD.Protobuf.VariantValue.verify(message.maxValues[i]); - if (error) - return "maxValues." + error; - } - } - if (message.lastValues != null && message.hasOwnProperty("lastValues")) { - if (!Array.isArray(message.lastValues)) - return "lastValues: array expected"; - for (var i = 0; i < message.lastValues.length; ++i) { - var error = $root.ICD.Protobuf.VariantValue.verify(message.lastValues[i]); - if (error) - return "lastValues." + error; - } - } - return null; - }; - - /** - * Creates a SignalDataRow message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.SignalDataRow} SignalDataRow - */ - SignalDataRow.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.SignalDataRow) - return object; - var message = new $root.DBMessaging.Protobuf.SignalDataRow(); - if (object.signalId) { - if (!Array.isArray(object.signalId)) - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.signalId: array expected"); - message.signalId = []; - for (var i = 0; i < object.signalId.length; ++i) - message.signalId[i] = object.signalId[i] >>> 0; - } - if (object.minValues) { - if (!Array.isArray(object.minValues)) - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.minValues: array expected"); - message.minValues = []; - for (var i = 0; i < object.minValues.length; ++i) { - if (typeof object.minValues[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.minValues: object expected"); - message.minValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.minValues[i]); - } - } - if (object.maxValues) { - if (!Array.isArray(object.maxValues)) - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.maxValues: array expected"); - message.maxValues = []; - for (var i = 0; i < object.maxValues.length; ++i) { - if (typeof object.maxValues[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.maxValues: object expected"); - message.maxValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.maxValues[i]); - } - } - if (object.lastValues) { - if (!Array.isArray(object.lastValues)) - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.lastValues: array expected"); - message.lastValues = []; - for (var i = 0; i < object.lastValues.length; ++i) { - if (typeof object.lastValues[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.SignalDataRow.lastValues: object expected"); - message.lastValues[i] = $root.ICD.Protobuf.VariantValue.fromObject(object.lastValues[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a SignalDataRow message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {DBMessaging.Protobuf.SignalDataRow} message SignalDataRow - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SignalDataRow.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.signalId = []; - object.minValues = []; - object.maxValues = []; - object.lastValues = []; - } - if (message.signalId && message.signalId.length) { - object.signalId = []; - for (var j = 0; j < message.signalId.length; ++j) - object.signalId[j] = message.signalId[j]; - } - if (message.minValues && message.minValues.length) { - object.minValues = []; - for (var j = 0; j < message.minValues.length; ++j) - object.minValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.minValues[j], options); - } - if (message.maxValues && message.maxValues.length) { - object.maxValues = []; - for (var j = 0; j < message.maxValues.length; ++j) - object.maxValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.maxValues[j], options); - } - if (message.lastValues && message.lastValues.length) { - object.lastValues = []; - for (var j = 0; j < message.lastValues.length; ++j) - object.lastValues[j] = $root.ICD.Protobuf.VariantValue.toObject(message.lastValues[j], options); - } - return object; - }; - - /** - * Converts this SignalDataRow to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.SignalDataRow - * @instance - * @returns {Object.} JSON object - */ - SignalDataRow.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SignalDataRow - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.SignalDataRow - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SignalDataRow.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.SignalDataRow"; - }; - - return SignalDataRow; - })(); - - Protobuf.CriterionLimitsRequest = (function() { - - /** - * Properties of a CriterionLimitsRequest. - * @memberof DBMessaging.Protobuf - * @interface ICriterionLimitsRequest - * @property {number|null} [requestId] CriterionLimitsRequest requestId - */ - - /** - * Constructs a new CriterionLimitsRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a CriterionLimitsRequest. - * @implements ICriterionLimitsRequest - * @constructor - * @param {DBMessaging.Protobuf.ICriterionLimitsRequest=} [properties] Properties to set - */ - function CriterionLimitsRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * CriterionLimitsRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @instance - */ - CriterionLimitsRequest.prototype.requestId = 0; - - /** - * Creates a new CriterionLimitsRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest instance - */ - CriterionLimitsRequest.create = function create(properties) { - return new CriterionLimitsRequest(properties); - }; - - /** - * Encodes the specified CriterionLimitsRequest message. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsRequest} message CriterionLimitsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CriterionLimitsRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - return writer; - }; - - /** - * Encodes the specified CriterionLimitsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsRequest} message CriterionLimitsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CriterionLimitsRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a CriterionLimitsRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CriterionLimitsRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CriterionLimitsRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a CriterionLimitsRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CriterionLimitsRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a CriterionLimitsRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - CriterionLimitsRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - return null; - }; - - /** - * Creates a CriterionLimitsRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.CriterionLimitsRequest} CriterionLimitsRequest - */ - CriterionLimitsRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.CriterionLimitsRequest) - return object; - var message = new $root.DBMessaging.Protobuf.CriterionLimitsRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - return message; - }; - - /** - * Creates a plain object from a CriterionLimitsRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {DBMessaging.Protobuf.CriterionLimitsRequest} message CriterionLimitsRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - CriterionLimitsRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - return object; - }; - - /** - * Converts this CriterionLimitsRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @instance - * @returns {Object.} JSON object - */ - CriterionLimitsRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for CriterionLimitsRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.CriterionLimitsRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - CriterionLimitsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.CriterionLimitsRequest"; - }; - - return CriterionLimitsRequest; - })(); - - Protobuf.CriterionLimitsResponse = (function() { - - /** - * Properties of a CriterionLimitsResponse. - * @memberof DBMessaging.Protobuf - * @interface ICriterionLimitsResponse - * @property {number|null} [requestId] CriterionLimitsResponse requestId - * @property {number|null} [criterionMin] CriterionLimitsResponse criterionMin - * @property {number|null} [criterionMax] CriterionLimitsResponse criterionMax - */ - - /** - * Constructs a new CriterionLimitsResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a CriterionLimitsResponse. - * @implements ICriterionLimitsResponse - * @constructor - * @param {DBMessaging.Protobuf.ICriterionLimitsResponse=} [properties] Properties to set - */ - function CriterionLimitsResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * CriterionLimitsResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @instance - */ - CriterionLimitsResponse.prototype.requestId = 0; - - /** - * CriterionLimitsResponse criterionMin. - * @member {number} criterionMin - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @instance - */ - CriterionLimitsResponse.prototype.criterionMin = 0; - - /** - * CriterionLimitsResponse criterionMax. - * @member {number} criterionMax - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @instance - */ - CriterionLimitsResponse.prototype.criterionMax = 0; - - /** - * Creates a new CriterionLimitsResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse instance - */ - CriterionLimitsResponse.create = function create(properties) { - return new CriterionLimitsResponse(properties); - }; - - /** - * Encodes the specified CriterionLimitsResponse message. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsResponse} message CriterionLimitsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CriterionLimitsResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.criterionMin != null && Object.hasOwnProperty.call(message, "criterionMin")) - writer.uint32(/* id 2, wireType 1 =*/17).double(message.criterionMin); - if (message.criterionMax != null && Object.hasOwnProperty.call(message, "criterionMax")) - writer.uint32(/* id 3, wireType 1 =*/25).double(message.criterionMax); - return writer; - }; - - /** - * Encodes the specified CriterionLimitsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CriterionLimitsResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {DBMessaging.Protobuf.ICriterionLimitsResponse} message CriterionLimitsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CriterionLimitsResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a CriterionLimitsResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CriterionLimitsResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CriterionLimitsResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.criterionMin = reader.double(); - break; - } - case 3: { - message.criterionMax = reader.double(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a CriterionLimitsResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CriterionLimitsResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a CriterionLimitsResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - CriterionLimitsResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) - if (typeof message.criterionMin !== "number") - return "criterionMin: number expected"; - if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) - if (typeof message.criterionMax !== "number") - return "criterionMax: number expected"; - return null; - }; - - /** - * Creates a CriterionLimitsResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.CriterionLimitsResponse} CriterionLimitsResponse - */ - CriterionLimitsResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.CriterionLimitsResponse) - return object; - var message = new $root.DBMessaging.Protobuf.CriterionLimitsResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.criterionMin != null) - message.criterionMin = Number(object.criterionMin); - if (object.criterionMax != null) - message.criterionMax = Number(object.criterionMax); - return message; - }; - - /** - * Creates a plain object from a CriterionLimitsResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {DBMessaging.Protobuf.CriterionLimitsResponse} message CriterionLimitsResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - CriterionLimitsResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - object.criterionMin = 0; - object.criterionMax = 0; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.criterionMin != null && message.hasOwnProperty("criterionMin")) - object.criterionMin = options.json && !isFinite(message.criterionMin) ? String(message.criterionMin) : message.criterionMin; - if (message.criterionMax != null && message.hasOwnProperty("criterionMax")) - object.criterionMax = options.json && !isFinite(message.criterionMax) ? String(message.criterionMax) : message.criterionMax; - return object; - }; - - /** - * Converts this CriterionLimitsResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @instance - * @returns {Object.} JSON object - */ - CriterionLimitsResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for CriterionLimitsResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.CriterionLimitsResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - CriterionLimitsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.CriterionLimitsResponse"; - }; - - return CriterionLimitsResponse; - })(); - - Protobuf.Event = (function() { - - /** - * Properties of an Event. - * @memberof DBMessaging.Protobuf - * @interface IEvent - * @property {string|null} [sender] Event sender - * @property {Object.|null} [data] Event data - * @property {number|null} [timestampSec] Event timestampSec - * @property {number|Long|null} [id] Event id - * @property {number|null} [code] Event code - * @property {number|null} [status] Event status - * @property {number|null} [logstampSec] Event logstampSec - */ - - /** - * Constructs a new Event. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an Event. - * @implements IEvent - * @constructor - * @param {DBMessaging.Protobuf.IEvent=} [properties] Properties to set - */ - function Event(properties) { - this.data = {}; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Event sender. - * @member {string} sender - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.sender = ""; - - /** - * Event data. - * @member {Object.} data - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.data = $util.emptyObject; - - /** - * Event timestampSec. - * @member {number} timestampSec - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.timestampSec = 0; - - /** - * Event id. - * @member {number|Long} id - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.id = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - - /** - * Event code. - * @member {number} code - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.code = 0; - - /** - * Event status. - * @member {number} status - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.status = 0; - - /** - * Event logstampSec. - * @member {number} logstampSec - * @memberof DBMessaging.Protobuf.Event - * @instance - */ - Event.prototype.logstampSec = 0; - - /** - * Creates a new Event instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {DBMessaging.Protobuf.IEvent=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.Event} Event instance - */ - Event.create = function create(properties) { - return new Event(properties); - }; - - /** - * Encodes the specified Event message. Does not implicitly {@link DBMessaging.Protobuf.Event.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {DBMessaging.Protobuf.IEvent} message Event message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Event.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.sender != null && Object.hasOwnProperty.call(message, "sender")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.sender); - if (message.data != null && Object.hasOwnProperty.call(message, "data")) - for (var keys = Object.keys(message.data), i = 0; i < keys.length; ++i) - writer.uint32(/* id 2, wireType 2 =*/18).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.data[keys[i]]).ldelim(); - if (message.timestampSec != null && Object.hasOwnProperty.call(message, "timestampSec")) - writer.uint32(/* id 3, wireType 1 =*/25).double(message.timestampSec); - if (message.id != null && Object.hasOwnProperty.call(message, "id")) - writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.id); - if (message.code != null && Object.hasOwnProperty.call(message, "code")) - writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.code); - if (message.status != null && Object.hasOwnProperty.call(message, "status")) - writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.status); - if (message.logstampSec != null && Object.hasOwnProperty.call(message, "logstampSec")) - writer.uint32(/* id 7, wireType 1 =*/57).double(message.logstampSec); - return writer; - }; - - /** - * Encodes the specified Event message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Event.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {DBMessaging.Protobuf.IEvent} message Event message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Event.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an Event message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.Event} Event - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Event.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Event(), key, value; - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.sender = reader.string(); - break; - } - case 2: { - if (message.data === $util.emptyObject) - message.data = {}; - var end2 = reader.uint32() + reader.pos; - key = ""; - value = ""; - while (reader.pos < end2) { - var tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = reader.string(); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.data[key] = value; - break; - } - case 3: { - message.timestampSec = reader.double(); - break; - } - case 4: { - message.id = reader.uint64(); - break; - } - case 5: { - message.code = reader.uint32(); - break; - } - case 6: { - message.status = reader.uint32(); - break; - } - case 7: { - message.logstampSec = reader.double(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an Event message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.Event} Event - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Event.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an Event message. - * @function verify - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Event.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.sender != null && message.hasOwnProperty("sender")) - if (!$util.isString(message.sender)) - return "sender: string expected"; - if (message.data != null && message.hasOwnProperty("data")) { - if (!$util.isObject(message.data)) - return "data: object expected"; - var key = Object.keys(message.data); - for (var i = 0; i < key.length; ++i) - if (!$util.isString(message.data[key[i]])) - return "data: string{k:string} expected"; - } - if (message.timestampSec != null && message.hasOwnProperty("timestampSec")) - if (typeof message.timestampSec !== "number") - return "timestampSec: number expected"; - if (message.id != null && message.hasOwnProperty("id")) - if (!$util.isInteger(message.id) && !(message.id && $util.isInteger(message.id.low) && $util.isInteger(message.id.high))) - return "id: integer|Long expected"; - if (message.code != null && message.hasOwnProperty("code")) - if (!$util.isInteger(message.code)) - return "code: integer expected"; - if (message.status != null && message.hasOwnProperty("status")) - if (!$util.isInteger(message.status)) - return "status: integer expected"; - if (message.logstampSec != null && message.hasOwnProperty("logstampSec")) - if (typeof message.logstampSec !== "number") - return "logstampSec: number expected"; - return null; - }; - - /** - * Creates an Event message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.Event} Event - */ - Event.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.Event) - return object; - var message = new $root.DBMessaging.Protobuf.Event(); - if (object.sender != null) - message.sender = String(object.sender); - if (object.data) { - if (typeof object.data !== "object") - throw TypeError(".DBMessaging.Protobuf.Event.data: object expected"); - message.data = {}; - for (var keys = Object.keys(object.data), i = 0; i < keys.length; ++i) - message.data[keys[i]] = String(object.data[keys[i]]); - } - if (object.timestampSec != null) - message.timestampSec = Number(object.timestampSec); - if (object.id != null) - if ($util.Long) - (message.id = $util.Long.fromValue(object.id)).unsigned = true; - else if (typeof object.id === "string") - message.id = parseInt(object.id, 10); - else if (typeof object.id === "number") - message.id = object.id; - else if (typeof object.id === "object") - message.id = new $util.LongBits(object.id.low >>> 0, object.id.high >>> 0).toNumber(true); - if (object.code != null) - message.code = object.code >>> 0; - if (object.status != null) - message.status = object.status >>> 0; - if (object.logstampSec != null) - message.logstampSec = Number(object.logstampSec); - return message; - }; - - /** - * Creates a plain object from an Event message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {DBMessaging.Protobuf.Event} message Event - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Event.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.objects || options.defaults) - object.data = {}; - if (options.defaults) { - object.sender = ""; - object.timestampSec = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.id = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.id = options.longs === String ? "0" : 0; - object.code = 0; - object.status = 0; - object.logstampSec = 0; - } - if (message.sender != null && message.hasOwnProperty("sender")) - object.sender = message.sender; - var keys2; - if (message.data && (keys2 = Object.keys(message.data)).length) { - object.data = {}; - for (var j = 0; j < keys2.length; ++j) - object.data[keys2[j]] = message.data[keys2[j]]; - } - if (message.timestampSec != null && message.hasOwnProperty("timestampSec")) - object.timestampSec = options.json && !isFinite(message.timestampSec) ? String(message.timestampSec) : message.timestampSec; - if (message.id != null && message.hasOwnProperty("id")) - if (typeof message.id === "number") - object.id = options.longs === String ? String(message.id) : message.id; - else - object.id = options.longs === String ? $util.Long.prototype.toString.call(message.id) : options.longs === Number ? new $util.LongBits(message.id.low >>> 0, message.id.high >>> 0).toNumber(true) : message.id; - if (message.code != null && message.hasOwnProperty("code")) - object.code = message.code; - if (message.status != null && message.hasOwnProperty("status")) - object.status = message.status; - if (message.logstampSec != null && message.hasOwnProperty("logstampSec")) - object.logstampSec = options.json && !isFinite(message.logstampSec) ? String(message.logstampSec) : message.logstampSec; - return object; - }; - - /** - * Converts this Event to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.Event - * @instance - * @returns {Object.} JSON object - */ - Event.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Event - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.Event - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Event.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.Event"; - }; - - return Event; - })(); - - Protobuf.EventQuery = (function() { - - /** - * Properties of an EventQuery. - * @memberof DBMessaging.Protobuf - * @interface IEventQuery - * @property {number|null} [timeRangeBegin] EventQuery timeRangeBegin - * @property {number|null} [timeRangeEnd] EventQuery timeRangeEnd - * @property {number|null} [codeMask] EventQuery codeMask - * @property {number|null} [limit] EventQuery limit - * @property {number|null} [offset] EventQuery offset - * @property {number|null} [flags] EventQuery flags - * @property {DBMessaging.Protobuf.EventQuery.IConditionList|null} [senderConditions] EventQuery senderConditions - * @property {Object.|null} [dataConditions] EventQuery dataConditions - */ - - /** - * Constructs a new EventQuery. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an EventQuery. - * @implements IEventQuery - * @constructor - * @param {DBMessaging.Protobuf.IEventQuery=} [properties] Properties to set - */ - function EventQuery(properties) { - this.dataConditions = {}; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * EventQuery timeRangeBegin. - * @member {number} timeRangeBegin - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.timeRangeBegin = 0; - - /** - * EventQuery timeRangeEnd. - * @member {number} timeRangeEnd - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.timeRangeEnd = 0; - - /** - * EventQuery codeMask. - * @member {number} codeMask - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.codeMask = 0; - - /** - * EventQuery limit. - * @member {number} limit - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.limit = 0; - - /** - * EventQuery offset. - * @member {number} offset - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.offset = 0; - - /** - * EventQuery flags. - * @member {number} flags - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.flags = 0; - - /** - * EventQuery senderConditions. - * @member {DBMessaging.Protobuf.EventQuery.IConditionList|null|undefined} senderConditions - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.senderConditions = null; - - /** - * EventQuery dataConditions. - * @member {Object.} dataConditions - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - */ - EventQuery.prototype.dataConditions = $util.emptyObject; - - /** - * Creates a new EventQuery instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {DBMessaging.Protobuf.IEventQuery=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventQuery} EventQuery instance - */ - EventQuery.create = function create(properties) { - return new EventQuery(properties); - }; - - /** - * Encodes the specified EventQuery message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {DBMessaging.Protobuf.IEventQuery} message EventQuery message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventQuery.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.timeRangeBegin != null && Object.hasOwnProperty.call(message, "timeRangeBegin")) - writer.uint32(/* id 1, wireType 1 =*/9).double(message.timeRangeBegin); - if (message.timeRangeEnd != null && Object.hasOwnProperty.call(message, "timeRangeEnd")) - writer.uint32(/* id 2, wireType 1 =*/17).double(message.timeRangeEnd); - if (message.codeMask != null && Object.hasOwnProperty.call(message, "codeMask")) - writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.codeMask); - if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) - writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.limit); - if (message.offset != null && Object.hasOwnProperty.call(message, "offset")) - writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.offset); - if (message.flags != null && Object.hasOwnProperty.call(message, "flags")) - writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.flags); - if (message.senderConditions != null && Object.hasOwnProperty.call(message, "senderConditions")) - $root.DBMessaging.Protobuf.EventQuery.ConditionList.encode(message.senderConditions, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.dataConditions != null && Object.hasOwnProperty.call(message, "dataConditions")) - for (var keys = Object.keys(message.dataConditions), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 8, wireType 2 =*/66).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.DBMessaging.Protobuf.EventQuery.ConditionList.encode(message.dataConditions[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - return writer; - }; - - /** - * Encodes the specified EventQuery message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {DBMessaging.Protobuf.IEventQuery} message EventQuery message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventQuery.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an EventQuery message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventQuery} EventQuery - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventQuery.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery(), key, value; - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.timeRangeBegin = reader.double(); - break; - } - case 2: { - message.timeRangeEnd = reader.double(); - break; - } - case 3: { - message.codeMask = reader.uint32(); - break; - } - case 4: { - message.limit = reader.uint32(); - break; - } - case 5: { - message.offset = reader.uint32(); - break; - } - case 6: { - message.flags = reader.uint32(); - break; - } - case 7: { - message.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.decode(reader, reader.uint32()); - break; - } - case 8: { - if (message.dataConditions === $util.emptyObject) - message.dataConditions = {}; - var end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - var tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.DBMessaging.Protobuf.EventQuery.ConditionList.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.dataConditions[key] = value; - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an EventQuery message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventQuery} EventQuery - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventQuery.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an EventQuery message. - * @function verify - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - EventQuery.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.timeRangeBegin != null && message.hasOwnProperty("timeRangeBegin")) - if (typeof message.timeRangeBegin !== "number") - return "timeRangeBegin: number expected"; - if (message.timeRangeEnd != null && message.hasOwnProperty("timeRangeEnd")) - if (typeof message.timeRangeEnd !== "number") - return "timeRangeEnd: number expected"; - if (message.codeMask != null && message.hasOwnProperty("codeMask")) - if (!$util.isInteger(message.codeMask)) - return "codeMask: integer expected"; - if (message.limit != null && message.hasOwnProperty("limit")) - if (!$util.isInteger(message.limit)) - return "limit: integer expected"; - if (message.offset != null && message.hasOwnProperty("offset")) - if (!$util.isInteger(message.offset)) - return "offset: integer expected"; - if (message.flags != null && message.hasOwnProperty("flags")) - if (!$util.isInteger(message.flags)) - return "flags: integer expected"; - if (message.senderConditions != null && message.hasOwnProperty("senderConditions")) { - var error = $root.DBMessaging.Protobuf.EventQuery.ConditionList.verify(message.senderConditions); - if (error) - return "senderConditions." + error; - } - if (message.dataConditions != null && message.hasOwnProperty("dataConditions")) { - if (!$util.isObject(message.dataConditions)) - return "dataConditions: object expected"; - var key = Object.keys(message.dataConditions); - for (var i = 0; i < key.length; ++i) { - var error = $root.DBMessaging.Protobuf.EventQuery.ConditionList.verify(message.dataConditions[key[i]]); - if (error) - return "dataConditions." + error; - } - } - return null; - }; - - /** - * Creates an EventQuery message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventQuery} EventQuery - */ - EventQuery.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventQuery) - return object; - var message = new $root.DBMessaging.Protobuf.EventQuery(); - if (object.timeRangeBegin != null) - message.timeRangeBegin = Number(object.timeRangeBegin); - if (object.timeRangeEnd != null) - message.timeRangeEnd = Number(object.timeRangeEnd); - if (object.codeMask != null) - message.codeMask = object.codeMask >>> 0; - if (object.limit != null) - message.limit = object.limit >>> 0; - if (object.offset != null) - message.offset = object.offset >>> 0; - if (object.flags != null) - message.flags = object.flags >>> 0; - if (object.senderConditions != null) { - if (typeof object.senderConditions !== "object") - throw TypeError(".DBMessaging.Protobuf.EventQuery.senderConditions: object expected"); - message.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.fromObject(object.senderConditions); - } - if (object.dataConditions) { - if (typeof object.dataConditions !== "object") - throw TypeError(".DBMessaging.Protobuf.EventQuery.dataConditions: object expected"); - message.dataConditions = {}; - for (var keys = Object.keys(object.dataConditions), i = 0; i < keys.length; ++i) { - if (typeof object.dataConditions[keys[i]] !== "object") - throw TypeError(".DBMessaging.Protobuf.EventQuery.dataConditions: object expected"); - message.dataConditions[keys[i]] = $root.DBMessaging.Protobuf.EventQuery.ConditionList.fromObject(object.dataConditions[keys[i]]); - } - } - return message; - }; - - /** - * Creates a plain object from an EventQuery message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {DBMessaging.Protobuf.EventQuery} message EventQuery - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - EventQuery.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.objects || options.defaults) - object.dataConditions = {}; - if (options.defaults) { - object.timeRangeBegin = 0; - object.timeRangeEnd = 0; - object.codeMask = 0; - object.limit = 0; - object.offset = 0; - object.flags = 0; - object.senderConditions = null; - } - if (message.timeRangeBegin != null && message.hasOwnProperty("timeRangeBegin")) - object.timeRangeBegin = options.json && !isFinite(message.timeRangeBegin) ? String(message.timeRangeBegin) : message.timeRangeBegin; - if (message.timeRangeEnd != null && message.hasOwnProperty("timeRangeEnd")) - object.timeRangeEnd = options.json && !isFinite(message.timeRangeEnd) ? String(message.timeRangeEnd) : message.timeRangeEnd; - if (message.codeMask != null && message.hasOwnProperty("codeMask")) - object.codeMask = message.codeMask; - if (message.limit != null && message.hasOwnProperty("limit")) - object.limit = message.limit; - if (message.offset != null && message.hasOwnProperty("offset")) - object.offset = message.offset; - if (message.flags != null && message.hasOwnProperty("flags")) - object.flags = message.flags; - if (message.senderConditions != null && message.hasOwnProperty("senderConditions")) - object.senderConditions = $root.DBMessaging.Protobuf.EventQuery.ConditionList.toObject(message.senderConditions, options); - var keys2; - if (message.dataConditions && (keys2 = Object.keys(message.dataConditions)).length) { - object.dataConditions = {}; - for (var j = 0; j < keys2.length; ++j) - object.dataConditions[keys2[j]] = $root.DBMessaging.Protobuf.EventQuery.ConditionList.toObject(message.dataConditions[keys2[j]], options); - } - return object; - }; - - /** - * Converts this EventQuery to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventQuery - * @instance - * @returns {Object.} JSON object - */ - EventQuery.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for EventQuery - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventQuery - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - EventQuery.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery"; - }; - - /** - * MatchType enum. - * @name DBMessaging.Protobuf.EventQuery.MatchType - * @enum {number} - * @property {number} Exact=0 Exact value - * @property {number} Wildcard=1 Wildcard value - */ - EventQuery.MatchType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "Exact"] = 0; - values[valuesById[1] = "Wildcard"] = 1; - return values; - })(); - - EventQuery.Condition = (function() { - - /** - * Properties of a Condition. - * @memberof DBMessaging.Protobuf.EventQuery - * @interface ICondition - * @property {string|null} [value] Condition value - * @property {DBMessaging.Protobuf.EventQuery.MatchType|null} [type] Condition type - */ - - /** - * Constructs a new Condition. - * @memberof DBMessaging.Protobuf.EventQuery - * @classdesc Represents a Condition. - * @implements ICondition - * @constructor - * @param {DBMessaging.Protobuf.EventQuery.ICondition=} [properties] Properties to set - */ - function Condition(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Condition value. - * @member {string} value - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @instance - */ - Condition.prototype.value = ""; - - /** - * Condition type. - * @member {DBMessaging.Protobuf.EventQuery.MatchType} type - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @instance - */ - Condition.prototype.type = 0; - - /** - * Creates a new Condition instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {DBMessaging.Protobuf.EventQuery.ICondition=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition instance - */ - Condition.create = function create(properties) { - return new Condition(properties); - }; - - /** - * Encodes the specified Condition message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.Condition.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {DBMessaging.Protobuf.EventQuery.ICondition} message Condition message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Condition.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.value); - if (message.type != null && Object.hasOwnProperty.call(message, "type")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.type); - return writer; - }; - - /** - * Encodes the specified Condition message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.Condition.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {DBMessaging.Protobuf.EventQuery.ICondition} message Condition message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Condition.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Condition message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Condition.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery.Condition(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.value = reader.string(); - break; - } - case 2: { - message.type = reader.int32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Condition message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Condition.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Condition message. - * @function verify - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Condition.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!$util.isString(message.value)) - return "value: string expected"; - if (message.type != null && message.hasOwnProperty("type")) - switch (message.type) { - default: - return "type: enum value expected"; - case 0: - case 1: - break; - } - return null; - }; - - /** - * Creates a Condition message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventQuery.Condition} Condition - */ - Condition.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventQuery.Condition) - return object; - var message = new $root.DBMessaging.Protobuf.EventQuery.Condition(); - if (object.value != null) - message.value = String(object.value); - switch (object.type) { - default: - if (typeof object.type === "number") { - message.type = object.type; - break; - } - break; - case "Exact": - case 0: - message.type = 0; - break; - case "Wildcard": - case 1: - message.type = 1; - break; - } - return message; - }; - - /** - * Creates a plain object from a Condition message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {DBMessaging.Protobuf.EventQuery.Condition} message Condition - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Condition.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.value = ""; - object.type = options.enums === String ? "Exact" : 0; - } - if (message.value != null && message.hasOwnProperty("value")) - object.value = message.value; - if (message.type != null && message.hasOwnProperty("type")) - object.type = options.enums === String ? $root.DBMessaging.Protobuf.EventQuery.MatchType[message.type] === undefined ? message.type : $root.DBMessaging.Protobuf.EventQuery.MatchType[message.type] : message.type; - return object; - }; - - /** - * Converts this Condition to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @instance - * @returns {Object.} JSON object - */ - Condition.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Condition - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventQuery.Condition - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Condition.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery.Condition"; - }; - - return Condition; - })(); - - EventQuery.ConditionList = (function() { - - /** - * Properties of a ConditionList. - * @memberof DBMessaging.Protobuf.EventQuery - * @interface IConditionList - * @property {Array.|null} [conditions] ConditionList conditions - */ - - /** - * Constructs a new ConditionList. - * @memberof DBMessaging.Protobuf.EventQuery - * @classdesc Represents a ConditionList. - * @implements IConditionList - * @constructor - * @param {DBMessaging.Protobuf.EventQuery.IConditionList=} [properties] Properties to set - */ - function ConditionList(properties) { - this.conditions = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ConditionList conditions. - * @member {Array.} conditions - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @instance - */ - ConditionList.prototype.conditions = $util.emptyArray; - - /** - * Creates a new ConditionList instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {DBMessaging.Protobuf.EventQuery.IConditionList=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList instance - */ - ConditionList.create = function create(properties) { - return new ConditionList(properties); - }; - - /** - * Encodes the specified ConditionList message. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.ConditionList.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {DBMessaging.Protobuf.EventQuery.IConditionList} message ConditionList message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ConditionList.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.conditions != null && message.conditions.length) - for (var i = 0; i < message.conditions.length; ++i) - $root.DBMessaging.Protobuf.EventQuery.Condition.encode(message.conditions[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified ConditionList message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventQuery.ConditionList.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {DBMessaging.Protobuf.EventQuery.IConditionList} message ConditionList message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ConditionList.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ConditionList message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ConditionList.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventQuery.ConditionList(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.conditions && message.conditions.length)) - message.conditions = []; - message.conditions.push($root.DBMessaging.Protobuf.EventQuery.Condition.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ConditionList message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ConditionList.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ConditionList message. - * @function verify - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ConditionList.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.conditions != null && message.hasOwnProperty("conditions")) { - if (!Array.isArray(message.conditions)) - return "conditions: array expected"; - for (var i = 0; i < message.conditions.length; ++i) { - var error = $root.DBMessaging.Protobuf.EventQuery.Condition.verify(message.conditions[i]); - if (error) - return "conditions." + error; - } - } - return null; - }; - - /** - * Creates a ConditionList message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventQuery.ConditionList} ConditionList - */ - ConditionList.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventQuery.ConditionList) - return object; - var message = new $root.DBMessaging.Protobuf.EventQuery.ConditionList(); - if (object.conditions) { - if (!Array.isArray(object.conditions)) - throw TypeError(".DBMessaging.Protobuf.EventQuery.ConditionList.conditions: array expected"); - message.conditions = []; - for (var i = 0; i < object.conditions.length; ++i) { - if (typeof object.conditions[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.EventQuery.ConditionList.conditions: object expected"); - message.conditions[i] = $root.DBMessaging.Protobuf.EventQuery.Condition.fromObject(object.conditions[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a ConditionList message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {DBMessaging.Protobuf.EventQuery.ConditionList} message ConditionList - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ConditionList.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.conditions = []; - if (message.conditions && message.conditions.length) { - object.conditions = []; - for (var j = 0; j < message.conditions.length; ++j) - object.conditions[j] = $root.DBMessaging.Protobuf.EventQuery.Condition.toObject(message.conditions[j], options); - } - return object; - }; - - /** - * Converts this ConditionList to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @instance - * @returns {Object.} JSON object - */ - ConditionList.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ConditionList - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventQuery.ConditionList - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ConditionList.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventQuery.ConditionList"; - }; - - return ConditionList; - })(); - - return EventQuery; - })(); - - Protobuf.EventSenderTagsRequest = (function() { - - /** - * Properties of an EventSenderTagsRequest. - * @memberof DBMessaging.Protobuf - * @interface IEventSenderTagsRequest - * @property {number|null} [requestId] EventSenderTagsRequest requestId - */ - - /** - * Constructs a new EventSenderTagsRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an EventSenderTagsRequest. - * @implements IEventSenderTagsRequest - * @constructor - * @param {DBMessaging.Protobuf.IEventSenderTagsRequest=} [properties] Properties to set - */ - function EventSenderTagsRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * EventSenderTagsRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @instance - */ - EventSenderTagsRequest.prototype.requestId = 0; - - /** - * Creates a new EventSenderTagsRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest instance - */ - EventSenderTagsRequest.create = function create(properties) { - return new EventSenderTagsRequest(properties); - }; - - /** - * Encodes the specified EventSenderTagsRequest message. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsRequest} message EventSenderTagsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventSenderTagsRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - return writer; - }; - - /** - * Encodes the specified EventSenderTagsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsRequest} message EventSenderTagsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventSenderTagsRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an EventSenderTagsRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventSenderTagsRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventSenderTagsRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an EventSenderTagsRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventSenderTagsRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an EventSenderTagsRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - EventSenderTagsRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - return null; - }; - - /** - * Creates an EventSenderTagsRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventSenderTagsRequest} EventSenderTagsRequest - */ - EventSenderTagsRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventSenderTagsRequest) - return object; - var message = new $root.DBMessaging.Protobuf.EventSenderTagsRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - return message; - }; - - /** - * Creates a plain object from an EventSenderTagsRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {DBMessaging.Protobuf.EventSenderTagsRequest} message EventSenderTagsRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - EventSenderTagsRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - return object; - }; - - /** - * Converts this EventSenderTagsRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @instance - * @returns {Object.} JSON object - */ - EventSenderTagsRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for EventSenderTagsRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventSenderTagsRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - EventSenderTagsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventSenderTagsRequest"; - }; - - return EventSenderTagsRequest; - })(); - - Protobuf.EventSenderTagsResponse = (function() { - - /** - * Properties of an EventSenderTagsResponse. - * @memberof DBMessaging.Protobuf - * @interface IEventSenderTagsResponse - * @property {number|null} [requestId] EventSenderTagsResponse requestId - * @property {Object.|null} [senderTags] EventSenderTagsResponse senderTags - */ - - /** - * Constructs a new EventSenderTagsResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an EventSenderTagsResponse. - * @implements IEventSenderTagsResponse - * @constructor - * @param {DBMessaging.Protobuf.IEventSenderTagsResponse=} [properties] Properties to set - */ - function EventSenderTagsResponse(properties) { - this.senderTags = {}; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * EventSenderTagsResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @instance - */ - EventSenderTagsResponse.prototype.requestId = 0; - - /** - * EventSenderTagsResponse senderTags. - * @member {Object.} senderTags - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @instance - */ - EventSenderTagsResponse.prototype.senderTags = $util.emptyObject; - - /** - * Creates a new EventSenderTagsResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse instance - */ - EventSenderTagsResponse.create = function create(properties) { - return new EventSenderTagsResponse(properties); - }; - - /** - * Encodes the specified EventSenderTagsResponse message. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsResponse} message EventSenderTagsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventSenderTagsResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.senderTags != null && Object.hasOwnProperty.call(message, "senderTags")) - for (var keys = Object.keys(message.senderTags), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 2, wireType 2 =*/18).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.DBMessaging.Protobuf.TagMap.encode(message.senderTags[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - return writer; - }; - - /** - * Encodes the specified EventSenderTagsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventSenderTagsResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {DBMessaging.Protobuf.IEventSenderTagsResponse} message EventSenderTagsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventSenderTagsResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an EventSenderTagsResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventSenderTagsResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventSenderTagsResponse(), key, value; - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - if (message.senderTags === $util.emptyObject) - message.senderTags = {}; - var end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - var tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.DBMessaging.Protobuf.TagMap.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.senderTags[key] = value; - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an EventSenderTagsResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventSenderTagsResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an EventSenderTagsResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - EventSenderTagsResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.senderTags != null && message.hasOwnProperty("senderTags")) { - if (!$util.isObject(message.senderTags)) - return "senderTags: object expected"; - var key = Object.keys(message.senderTags); - for (var i = 0; i < key.length; ++i) { - var error = $root.DBMessaging.Protobuf.TagMap.verify(message.senderTags[key[i]]); - if (error) - return "senderTags." + error; - } - } - return null; - }; - - /** - * Creates an EventSenderTagsResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventSenderTagsResponse} EventSenderTagsResponse - */ - EventSenderTagsResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventSenderTagsResponse) - return object; - var message = new $root.DBMessaging.Protobuf.EventSenderTagsResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.senderTags) { - if (typeof object.senderTags !== "object") - throw TypeError(".DBMessaging.Protobuf.EventSenderTagsResponse.senderTags: object expected"); - message.senderTags = {}; - for (var keys = Object.keys(object.senderTags), i = 0; i < keys.length; ++i) { - if (typeof object.senderTags[keys[i]] !== "object") - throw TypeError(".DBMessaging.Protobuf.EventSenderTagsResponse.senderTags: object expected"); - message.senderTags[keys[i]] = $root.DBMessaging.Protobuf.TagMap.fromObject(object.senderTags[keys[i]]); - } - } - return message; - }; - - /** - * Creates a plain object from an EventSenderTagsResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {DBMessaging.Protobuf.EventSenderTagsResponse} message EventSenderTagsResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - EventSenderTagsResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.objects || options.defaults) - object.senderTags = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - var keys2; - if (message.senderTags && (keys2 = Object.keys(message.senderTags)).length) { - object.senderTags = {}; - for (var j = 0; j < keys2.length; ++j) - object.senderTags[keys2[j]] = $root.DBMessaging.Protobuf.TagMap.toObject(message.senderTags[keys2[j]], options); - } - return object; - }; - - /** - * Converts this EventSenderTagsResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @instance - * @returns {Object.} JSON object - */ - EventSenderTagsResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for EventSenderTagsResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventSenderTagsResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - EventSenderTagsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventSenderTagsResponse"; - }; - - return EventSenderTagsResponse; - })(); - - Protobuf.CountEventsRequest = (function() { - - /** - * Properties of a CountEventsRequest. - * @memberof DBMessaging.Protobuf - * @interface ICountEventsRequest - * @property {number|null} [requestId] CountEventsRequest requestId - * @property {DBMessaging.Protobuf.IEventQuery|null} [query] CountEventsRequest query - */ - - /** - * Constructs a new CountEventsRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a CountEventsRequest. - * @implements ICountEventsRequest - * @constructor - * @param {DBMessaging.Protobuf.ICountEventsRequest=} [properties] Properties to set - */ - function CountEventsRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * CountEventsRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @instance - */ - CountEventsRequest.prototype.requestId = 0; - - /** - * CountEventsRequest query. - * @member {DBMessaging.Protobuf.IEventQuery|null|undefined} query - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @instance - */ - CountEventsRequest.prototype.query = null; - - /** - * Creates a new CountEventsRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {DBMessaging.Protobuf.ICountEventsRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest instance - */ - CountEventsRequest.create = function create(properties) { - return new CountEventsRequest(properties); - }; - - /** - * Encodes the specified CountEventsRequest message. Does not implicitly {@link DBMessaging.Protobuf.CountEventsRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {DBMessaging.Protobuf.ICountEventsRequest} message CountEventsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CountEventsRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.query != null && Object.hasOwnProperty.call(message, "query")) - $root.DBMessaging.Protobuf.EventQuery.encode(message.query, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified CountEventsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CountEventsRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {DBMessaging.Protobuf.ICountEventsRequest} message CountEventsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CountEventsRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a CountEventsRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CountEventsRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CountEventsRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.query = $root.DBMessaging.Protobuf.EventQuery.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a CountEventsRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CountEventsRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a CountEventsRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - CountEventsRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.query != null && message.hasOwnProperty("query")) { - var error = $root.DBMessaging.Protobuf.EventQuery.verify(message.query); - if (error) - return "query." + error; - } - return null; - }; - - /** - * Creates a CountEventsRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.CountEventsRequest} CountEventsRequest - */ - CountEventsRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.CountEventsRequest) - return object; - var message = new $root.DBMessaging.Protobuf.CountEventsRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.query != null) { - if (typeof object.query !== "object") - throw TypeError(".DBMessaging.Protobuf.CountEventsRequest.query: object expected"); - message.query = $root.DBMessaging.Protobuf.EventQuery.fromObject(object.query); - } - return message; - }; - - /** - * Creates a plain object from a CountEventsRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {DBMessaging.Protobuf.CountEventsRequest} message CountEventsRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - CountEventsRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - object.query = null; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.query != null && message.hasOwnProperty("query")) - object.query = $root.DBMessaging.Protobuf.EventQuery.toObject(message.query, options); - return object; - }; - - /** - * Converts this CountEventsRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @instance - * @returns {Object.} JSON object - */ - CountEventsRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for CountEventsRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.CountEventsRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - CountEventsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.CountEventsRequest"; - }; - - return CountEventsRequest; - })(); - - Protobuf.CountEventsResponse = (function() { - - /** - * Properties of a CountEventsResponse. - * @memberof DBMessaging.Protobuf - * @interface ICountEventsResponse - * @property {number|null} [requestId] CountEventsResponse requestId - * @property {number|Long|null} [count] CountEventsResponse count - */ - - /** - * Constructs a new CountEventsResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a CountEventsResponse. - * @implements ICountEventsResponse - * @constructor - * @param {DBMessaging.Protobuf.ICountEventsResponse=} [properties] Properties to set - */ - function CountEventsResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * CountEventsResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @instance - */ - CountEventsResponse.prototype.requestId = 0; - - /** - * CountEventsResponse count. - * @member {number|Long} count - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @instance - */ - CountEventsResponse.prototype.count = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new CountEventsResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {DBMessaging.Protobuf.ICountEventsResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse instance - */ - CountEventsResponse.create = function create(properties) { - return new CountEventsResponse(properties); - }; - - /** - * Encodes the specified CountEventsResponse message. Does not implicitly {@link DBMessaging.Protobuf.CountEventsResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {DBMessaging.Protobuf.ICountEventsResponse} message CountEventsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CountEventsResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.count != null && Object.hasOwnProperty.call(message, "count")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.count); - return writer; - }; - - /** - * Encodes the specified CountEventsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.CountEventsResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {DBMessaging.Protobuf.ICountEventsResponse} message CountEventsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - CountEventsResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a CountEventsResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CountEventsResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.CountEventsResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.count = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a CountEventsResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - CountEventsResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a CountEventsResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - CountEventsResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.count != null && message.hasOwnProperty("count")) - if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) - return "count: integer|Long expected"; - return null; - }; - - /** - * Creates a CountEventsResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.CountEventsResponse} CountEventsResponse - */ - CountEventsResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.CountEventsResponse) - return object; - var message = new $root.DBMessaging.Protobuf.CountEventsResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.count != null) - if ($util.Long) - (message.count = $util.Long.fromValue(object.count)).unsigned = false; - else if (typeof object.count === "string") - message.count = parseInt(object.count, 10); - else if (typeof object.count === "number") - message.count = object.count; - else if (typeof object.count === "object") - message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from a CountEventsResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {DBMessaging.Protobuf.CountEventsResponse} message CountEventsResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - CountEventsResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.count = options.longs === String ? "0" : 0; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.count != null && message.hasOwnProperty("count")) - if (typeof message.count === "number") - object.count = options.longs === String ? String(message.count) : message.count; - else - object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber() : message.count; - return object; - }; - - /** - * Converts this CountEventsResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @instance - * @returns {Object.} JSON object - */ - CountEventsResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for CountEventsResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.CountEventsResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - CountEventsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.CountEventsResponse"; - }; - - return CountEventsResponse; - })(); - - Protobuf.EventsRequest = (function() { - - /** - * Properties of an EventsRequest. - * @memberof DBMessaging.Protobuf - * @interface IEventsRequest - * @property {number|null} [requestId] EventsRequest requestId - * @property {DBMessaging.Protobuf.IEventQuery|null} [query] EventsRequest query - */ - - /** - * Constructs a new EventsRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an EventsRequest. - * @implements IEventsRequest - * @constructor - * @param {DBMessaging.Protobuf.IEventsRequest=} [properties] Properties to set - */ - function EventsRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * EventsRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.EventsRequest - * @instance - */ - EventsRequest.prototype.requestId = 0; - - /** - * EventsRequest query. - * @member {DBMessaging.Protobuf.IEventQuery|null|undefined} query - * @memberof DBMessaging.Protobuf.EventsRequest - * @instance - */ - EventsRequest.prototype.query = null; - - /** - * Creates a new EventsRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {DBMessaging.Protobuf.IEventsRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest instance - */ - EventsRequest.create = function create(properties) { - return new EventsRequest(properties); - }; - - /** - * Encodes the specified EventsRequest message. Does not implicitly {@link DBMessaging.Protobuf.EventsRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {DBMessaging.Protobuf.IEventsRequest} message EventsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventsRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.query != null && Object.hasOwnProperty.call(message, "query")) - $root.DBMessaging.Protobuf.EventQuery.encode(message.query, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified EventsRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventsRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {DBMessaging.Protobuf.IEventsRequest} message EventsRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventsRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an EventsRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventsRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventsRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.query = $root.DBMessaging.Protobuf.EventQuery.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an EventsRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventsRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an EventsRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - EventsRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.query != null && message.hasOwnProperty("query")) { - var error = $root.DBMessaging.Protobuf.EventQuery.verify(message.query); - if (error) - return "query." + error; - } - return null; - }; - - /** - * Creates an EventsRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventsRequest} EventsRequest - */ - EventsRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventsRequest) - return object; - var message = new $root.DBMessaging.Protobuf.EventsRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.query != null) { - if (typeof object.query !== "object") - throw TypeError(".DBMessaging.Protobuf.EventsRequest.query: object expected"); - message.query = $root.DBMessaging.Protobuf.EventQuery.fromObject(object.query); - } - return message; - }; - - /** - * Creates a plain object from an EventsRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {DBMessaging.Protobuf.EventsRequest} message EventsRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - EventsRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - object.query = null; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.query != null && message.hasOwnProperty("query")) - object.query = $root.DBMessaging.Protobuf.EventQuery.toObject(message.query, options); - return object; - }; - - /** - * Converts this EventsRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventsRequest - * @instance - * @returns {Object.} JSON object - */ - EventsRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for EventsRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventsRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - EventsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventsRequest"; - }; - - return EventsRequest; - })(); - - Protobuf.EventsResponse = (function() { - - /** - * Properties of an EventsResponse. - * @memberof DBMessaging.Protobuf - * @interface IEventsResponse - * @property {number|null} [requestId] EventsResponse requestId - * @property {Array.|null} [events] EventsResponse events - */ - - /** - * Constructs a new EventsResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an EventsResponse. - * @implements IEventsResponse - * @constructor - * @param {DBMessaging.Protobuf.IEventsResponse=} [properties] Properties to set - */ - function EventsResponse(properties) { - this.events = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * EventsResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.EventsResponse - * @instance - */ - EventsResponse.prototype.requestId = 0; - - /** - * EventsResponse events. - * @member {Array.} events - * @memberof DBMessaging.Protobuf.EventsResponse - * @instance - */ - EventsResponse.prototype.events = $util.emptyArray; - - /** - * Creates a new EventsResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {DBMessaging.Protobuf.IEventsResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse instance - */ - EventsResponse.create = function create(properties) { - return new EventsResponse(properties); - }; - - /** - * Encodes the specified EventsResponse message. Does not implicitly {@link DBMessaging.Protobuf.EventsResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {DBMessaging.Protobuf.IEventsResponse} message EventsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventsResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.events != null && message.events.length) - for (var i = 0; i < message.events.length; ++i) - $root.DBMessaging.Protobuf.Event.encode(message.events[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified EventsResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.EventsResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {DBMessaging.Protobuf.IEventsResponse} message EventsResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - EventsResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an EventsResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventsResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.EventsResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - if (!(message.events && message.events.length)) - message.events = []; - message.events.push($root.DBMessaging.Protobuf.Event.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an EventsResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - EventsResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an EventsResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - EventsResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.events != null && message.hasOwnProperty("events")) { - if (!Array.isArray(message.events)) - return "events: array expected"; - for (var i = 0; i < message.events.length; ++i) { - var error = $root.DBMessaging.Protobuf.Event.verify(message.events[i]); - if (error) - return "events." + error; - } - } - return null; - }; - - /** - * Creates an EventsResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.EventsResponse} EventsResponse - */ - EventsResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.EventsResponse) - return object; - var message = new $root.DBMessaging.Protobuf.EventsResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.events) { - if (!Array.isArray(object.events)) - throw TypeError(".DBMessaging.Protobuf.EventsResponse.events: array expected"); - message.events = []; - for (var i = 0; i < object.events.length; ++i) { - if (typeof object.events[i] !== "object") - throw TypeError(".DBMessaging.Protobuf.EventsResponse.events: object expected"); - message.events[i] = $root.DBMessaging.Protobuf.Event.fromObject(object.events[i]); - } - } - return message; - }; - - /** - * Creates a plain object from an EventsResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {DBMessaging.Protobuf.EventsResponse} message EventsResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - EventsResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.events = []; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.events && message.events.length) { - object.events = []; - for (var j = 0; j < message.events.length; ++j) - object.events[j] = $root.DBMessaging.Protobuf.Event.toObject(message.events[j], options); - } - return object; - }; - - /** - * Converts this EventsResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.EventsResponse - * @instance - * @returns {Object.} JSON object - */ - EventsResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for EventsResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.EventsResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - EventsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.EventsResponse"; - }; - - return EventsResponse; - })(); - - Protobuf.VersionRequest = (function() { - - /** - * Properties of a VersionRequest. - * @memberof DBMessaging.Protobuf - * @interface IVersionRequest - * @property {number|null} [requestId] VersionRequest requestId - */ - - /** - * Constructs a new VersionRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a VersionRequest. - * @implements IVersionRequest - * @constructor - * @param {DBMessaging.Protobuf.IVersionRequest=} [properties] Properties to set - */ - function VersionRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * VersionRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.VersionRequest - * @instance - */ - VersionRequest.prototype.requestId = 0; - - /** - * Creates a new VersionRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {DBMessaging.Protobuf.IVersionRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest instance - */ - VersionRequest.create = function create(properties) { - return new VersionRequest(properties); - }; - - /** - * Encodes the specified VersionRequest message. Does not implicitly {@link DBMessaging.Protobuf.VersionRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {DBMessaging.Protobuf.IVersionRequest} message VersionRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VersionRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - return writer; - }; - - /** - * Encodes the specified VersionRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.VersionRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {DBMessaging.Protobuf.IVersionRequest} message VersionRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VersionRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a VersionRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VersionRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.VersionRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a VersionRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VersionRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a VersionRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - VersionRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - return null; - }; - - /** - * Creates a VersionRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.VersionRequest} VersionRequest - */ - VersionRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.VersionRequest) - return object; - var message = new $root.DBMessaging.Protobuf.VersionRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - return message; - }; - - /** - * Creates a plain object from a VersionRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {DBMessaging.Protobuf.VersionRequest} message VersionRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - VersionRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - return object; - }; - - /** - * Converts this VersionRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.VersionRequest - * @instance - * @returns {Object.} JSON object - */ - VersionRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for VersionRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.VersionRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - VersionRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.VersionRequest"; - }; - - return VersionRequest; - })(); - - Protobuf.VersionResponse = (function() { - - /** - * Properties of a VersionResponse. - * @memberof DBMessaging.Protobuf - * @interface IVersionResponse - * @property {number|null} [requestId] VersionResponse requestId - * @property {string|null} [version] VersionResponse version - */ - - /** - * Constructs a new VersionResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a VersionResponse. - * @implements IVersionResponse - * @constructor - * @param {DBMessaging.Protobuf.IVersionResponse=} [properties] Properties to set - */ - function VersionResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * VersionResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.VersionResponse - * @instance - */ - VersionResponse.prototype.requestId = 0; - - /** - * VersionResponse version. - * @member {string} version - * @memberof DBMessaging.Protobuf.VersionResponse - * @instance - */ - VersionResponse.prototype.version = ""; - - /** - * Creates a new VersionResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {DBMessaging.Protobuf.IVersionResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse instance - */ - VersionResponse.create = function create(properties) { - return new VersionResponse(properties); - }; - - /** - * Encodes the specified VersionResponse message. Does not implicitly {@link DBMessaging.Protobuf.VersionResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {DBMessaging.Protobuf.IVersionResponse} message VersionResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VersionResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.version != null && Object.hasOwnProperty.call(message, "version")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.version); - return writer; - }; - - /** - * Encodes the specified VersionResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.VersionResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {DBMessaging.Protobuf.IVersionResponse} message VersionResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VersionResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a VersionResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VersionResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.VersionResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.version = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a VersionResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VersionResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a VersionResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - VersionResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.version != null && message.hasOwnProperty("version")) - if (!$util.isString(message.version)) - return "version: string expected"; - return null; - }; - - /** - * Creates a VersionResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.VersionResponse} VersionResponse - */ - VersionResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.VersionResponse) - return object; - var message = new $root.DBMessaging.Protobuf.VersionResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.version != null) - message.version = String(object.version); - return message; - }; - - /** - * Creates a plain object from a VersionResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {DBMessaging.Protobuf.VersionResponse} message VersionResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - VersionResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - object.version = ""; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.version != null && message.hasOwnProperty("version")) - object.version = message.version; - return object; - }; - - /** - * Converts this VersionResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.VersionResponse - * @instance - * @returns {Object.} JSON object - */ - VersionResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for VersionResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.VersionResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - VersionResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.VersionResponse"; - }; - - return VersionResponse; - })(); - - Protobuf.Error = (function() { - - /** - * Properties of an Error. - * @memberof DBMessaging.Protobuf - * @interface IError - * @property {number|null} [requestId] Error requestId - * @property {string|null} [errorMessage] Error errorMessage - * @property {number|null} [errorCode] Error errorCode - */ - - /** - * Constructs a new Error. - * @memberof DBMessaging.Protobuf - * @classdesc Represents an Error. - * @implements IError - * @constructor - * @param {DBMessaging.Protobuf.IError=} [properties] Properties to set - */ - function Error(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Error requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.Error - * @instance - */ - Error.prototype.requestId = 0; - - /** - * Error errorMessage. - * @member {string} errorMessage - * @memberof DBMessaging.Protobuf.Error - * @instance - */ - Error.prototype.errorMessage = ""; - - /** - * Error errorCode. - * @member {number} errorCode - * @memberof DBMessaging.Protobuf.Error - * @instance - */ - Error.prototype.errorCode = 0; - - /** - * Creates a new Error instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {DBMessaging.Protobuf.IError=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.Error} Error instance - */ - Error.create = function create(properties) { - return new Error(properties); - }; - - /** - * Encodes the specified Error message. Does not implicitly {@link DBMessaging.Protobuf.Error.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {DBMessaging.Protobuf.IError} message Error message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Error.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.errorMessage != null && Object.hasOwnProperty.call(message, "errorMessage")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.errorMessage); - if (message.errorCode != null && Object.hasOwnProperty.call(message, "errorCode")) - writer.uint32(/* id 3, wireType 0 =*/24).int32(message.errorCode); - return writer; - }; - - /** - * Encodes the specified Error message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.Error.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {DBMessaging.Protobuf.IError} message Error message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Error.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an Error message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.Error} Error - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Error.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.Error(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.errorMessage = reader.string(); - break; - } - case 3: { - message.errorCode = reader.int32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an Error message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.Error} Error - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Error.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an Error message. - * @function verify - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Error.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.errorMessage != null && message.hasOwnProperty("errorMessage")) - if (!$util.isString(message.errorMessage)) - return "errorMessage: string expected"; - if (message.errorCode != null && message.hasOwnProperty("errorCode")) - if (!$util.isInteger(message.errorCode)) - return "errorCode: integer expected"; - return null; - }; - - /** - * Creates an Error message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.Error} Error - */ - Error.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.Error) - return object; - var message = new $root.DBMessaging.Protobuf.Error(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.errorMessage != null) - message.errorMessage = String(object.errorMessage); - if (object.errorCode != null) - message.errorCode = object.errorCode | 0; - return message; - }; - - /** - * Creates a plain object from an Error message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {DBMessaging.Protobuf.Error} message Error - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Error.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - object.errorMessage = ""; - object.errorCode = 0; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.errorMessage != null && message.hasOwnProperty("errorMessage")) - object.errorMessage = message.errorMessage; - if (message.errorCode != null && message.hasOwnProperty("errorCode")) - object.errorCode = message.errorCode; - return object; - }; - - /** - * Converts this Error to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.Error - * @instance - * @returns {Object.} JSON object - */ - Error.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Error - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.Error - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Error.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.Error"; - }; - - return Error; - })(); - - Protobuf.TimeRequest = (function() { - - /** - * Properties of a TimeRequest. - * @memberof DBMessaging.Protobuf - * @interface ITimeRequest - * @property {number|null} [requestId] TimeRequest requestId - */ - - /** - * Constructs a new TimeRequest. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a TimeRequest. - * @implements ITimeRequest - * @constructor - * @param {DBMessaging.Protobuf.ITimeRequest=} [properties] Properties to set - */ - function TimeRequest(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * TimeRequest requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.TimeRequest - * @instance - */ - TimeRequest.prototype.requestId = 0; - - /** - * Creates a new TimeRequest instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {DBMessaging.Protobuf.ITimeRequest=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest instance - */ - TimeRequest.create = function create(properties) { - return new TimeRequest(properties); - }; - - /** - * Encodes the specified TimeRequest message. Does not implicitly {@link DBMessaging.Protobuf.TimeRequest.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {DBMessaging.Protobuf.ITimeRequest} message TimeRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TimeRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - return writer; - }; - - /** - * Encodes the specified TimeRequest message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TimeRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {DBMessaging.Protobuf.ITimeRequest} message TimeRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TimeRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TimeRequest message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TimeRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TimeRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TimeRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TimeRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TimeRequest message. - * @function verify - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TimeRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - return null; - }; - - /** - * Creates a TimeRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.TimeRequest} TimeRequest - */ - TimeRequest.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.TimeRequest) - return object; - var message = new $root.DBMessaging.Protobuf.TimeRequest(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - return message; - }; - - /** - * Creates a plain object from a TimeRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {DBMessaging.Protobuf.TimeRequest} message TimeRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TimeRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.requestId = 0; - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - return object; - }; - - /** - * Converts this TimeRequest to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.TimeRequest - * @instance - * @returns {Object.} JSON object - */ - TimeRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TimeRequest - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.TimeRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TimeRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.TimeRequest"; - }; - - return TimeRequest; - })(); - - Protobuf.TimeResponse = (function() { - - /** - * Properties of a TimeResponse. - * @memberof DBMessaging.Protobuf - * @interface ITimeResponse - * @property {number|null} [requestId] TimeResponse requestId - * @property {number|Long|null} [timestamp] TimeResponse timestamp - */ - - /** - * Constructs a new TimeResponse. - * @memberof DBMessaging.Protobuf - * @classdesc Represents a TimeResponse. - * @implements ITimeResponse - * @constructor - * @param {DBMessaging.Protobuf.ITimeResponse=} [properties] Properties to set - */ - function TimeResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * TimeResponse requestId. - * @member {number} requestId - * @memberof DBMessaging.Protobuf.TimeResponse - * @instance - */ - TimeResponse.prototype.requestId = 0; - - /** - * TimeResponse timestamp. - * @member {number|Long} timestamp - * @memberof DBMessaging.Protobuf.TimeResponse - * @instance - */ - TimeResponse.prototype.timestamp = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new TimeResponse instance using the specified properties. - * @function create - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {DBMessaging.Protobuf.ITimeResponse=} [properties] Properties to set - * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse instance - */ - TimeResponse.create = function create(properties) { - return new TimeResponse(properties); - }; - - /** - * Encodes the specified TimeResponse message. Does not implicitly {@link DBMessaging.Protobuf.TimeResponse.verify|verify} messages. - * @function encode - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {DBMessaging.Protobuf.ITimeResponse} message TimeResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TimeResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.requestId); - if (message.timestamp != null && Object.hasOwnProperty.call(message, "timestamp")) - writer.uint32(/* id 2, wireType 1 =*/17).fixed64(message.timestamp); - return writer; - }; - - /** - * Encodes the specified TimeResponse message, length delimited. Does not implicitly {@link DBMessaging.Protobuf.TimeResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {DBMessaging.Protobuf.ITimeResponse} message TimeResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TimeResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TimeResponse message from the specified reader or buffer. - * @function decode - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TimeResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.DBMessaging.Protobuf.TimeResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.requestId = reader.uint32(); - break; - } - case 2: { - message.timestamp = reader.fixed64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TimeResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TimeResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TimeResponse message. - * @function verify - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TimeResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.requestId != null && message.hasOwnProperty("requestId")) - if (!$util.isInteger(message.requestId)) - return "requestId: integer expected"; - if (message.timestamp != null && message.hasOwnProperty("timestamp")) - if (!$util.isInteger(message.timestamp) && !(message.timestamp && $util.isInteger(message.timestamp.low) && $util.isInteger(message.timestamp.high))) - return "timestamp: integer|Long expected"; - return null; - }; - - /** - * Creates a TimeResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {Object.} object Plain object - * @returns {DBMessaging.Protobuf.TimeResponse} TimeResponse - */ - TimeResponse.fromObject = function fromObject(object) { - if (object instanceof $root.DBMessaging.Protobuf.TimeResponse) - return object; - var message = new $root.DBMessaging.Protobuf.TimeResponse(); - if (object.requestId != null) - message.requestId = object.requestId >>> 0; - if (object.timestamp != null) - if ($util.Long) - (message.timestamp = $util.Long.fromValue(object.timestamp)).unsigned = false; - else if (typeof object.timestamp === "string") - message.timestamp = parseInt(object.timestamp, 10); - else if (typeof object.timestamp === "number") - message.timestamp = object.timestamp; - else if (typeof object.timestamp === "object") - message.timestamp = new $util.LongBits(object.timestamp.low >>> 0, object.timestamp.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from a TimeResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {DBMessaging.Protobuf.TimeResponse} message TimeResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TimeResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.requestId = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.timestamp = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.timestamp = options.longs === String ? "0" : 0; - } - if (message.requestId != null && message.hasOwnProperty("requestId")) - object.requestId = message.requestId; - if (message.timestamp != null && message.hasOwnProperty("timestamp")) - if (typeof message.timestamp === "number") - object.timestamp = options.longs === String ? String(message.timestamp) : message.timestamp; - else - object.timestamp = options.longs === String ? $util.Long.prototype.toString.call(message.timestamp) : options.longs === Number ? new $util.LongBits(message.timestamp.low >>> 0, message.timestamp.high >>> 0).toNumber() : message.timestamp; - return object; - }; - - /** - * Converts this TimeResponse to JSON. - * @function toJSON - * @memberof DBMessaging.Protobuf.TimeResponse - * @instance - * @returns {Object.} JSON object - */ - TimeResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TimeResponse - * @function getTypeUrl - * @memberof DBMessaging.Protobuf.TimeResponse - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TimeResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/DBMessaging.Protobuf.TimeResponse"; - }; - - return TimeResponse; - })(); - - return Protobuf; - })(); - - return DBMessaging; -})(); - -$root.ICD = (function() { - - /** - * Namespace ICD. - * @exports ICD - * @namespace - */ - var ICD = {}; - - ICD.Protobuf = (function() { - - /** - * Namespace Protobuf. - * @memberof ICD - * @namespace - */ - var Protobuf = {}; - - /** - * CDP value type identifier. - * @name ICD.Protobuf.CDPValueType - * @enum {number} - * @property {number} eUNDEFINED=0 eUNDEFINED value - * @property {number} eDOUBLE=1 eDOUBLE value - * @property {number} eUINT64=2 eUINT64 value - * @property {number} eINT64=3 eINT64 value - * @property {number} eFLOAT=4 eFLOAT value - * @property {number} eUINT=5 eUINT value - * @property {number} eINT=6 eINT value - * @property {number} eUSHORT=7 eUSHORT value - * @property {number} eSHORT=8 eSHORT value - * @property {number} eUCHAR=9 eUCHAR value - * @property {number} eCHAR=10 eCHAR value - * @property {number} eBOOL=11 eBOOL value - * @property {number} eSTRING=12 eSTRING value - * @property {number} eUSERTYPE=100 eUSERTYPE value - */ - Protobuf.CDPValueType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "eUNDEFINED"] = 0; - values[valuesById[1] = "eDOUBLE"] = 1; - values[valuesById[2] = "eUINT64"] = 2; - values[valuesById[3] = "eINT64"] = 3; - values[valuesById[4] = "eFLOAT"] = 4; - values[valuesById[5] = "eUINT"] = 5; - values[valuesById[6] = "eINT"] = 6; - values[valuesById[7] = "eUSHORT"] = 7; - values[valuesById[8] = "eSHORT"] = 8; - values[valuesById[9] = "eUCHAR"] = 9; - values[valuesById[10] = "eCHAR"] = 10; - values[valuesById[11] = "eBOOL"] = 11; - values[valuesById[12] = "eSTRING"] = 12; - values[valuesById[100] = "eUSERTYPE"] = 100; - return values; - })(); - - Protobuf.VariantValue = (function() { - - /** - * Properties of a VariantValue. - * @memberof ICD.Protobuf - * @interface IVariantValue - * @property {number|null} [nodeId] VariantValue nodeId - * @property {number|null} [dValue] VariantValue dValue - * @property {number|null} [fValue] VariantValue fValue - * @property {number|Long|null} [ui64Value] VariantValue ui64Value - * @property {number|Long|null} [i64Value] VariantValue i64Value - * @property {number|null} [uiValue] VariantValue uiValue - * @property {number|null} [iValue] VariantValue iValue - * @property {number|null} [usValue] VariantValue usValue - * @property {number|null} [sValue] VariantValue sValue - * @property {number|null} [ucValue] VariantValue ucValue - * @property {number|null} [cValue] VariantValue cValue - * @property {boolean|null} [bValue] VariantValue bValue - * @property {string|null} [strValue] VariantValue strValue - * @property {number|null} [timestamp] VariantValue timestamp - */ - - /** - * Constructs a new VariantValue. - * @memberof ICD.Protobuf - * @classdesc Common Variant value type for a remote node. - * @implements IVariantValue - * @constructor - * @param {ICD.Protobuf.IVariantValue=} [properties] Properties to set - */ - function VariantValue(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * VariantValue nodeId. - * @member {number} nodeId - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.nodeId = 0; - - /** - * VariantValue dValue. - * @member {number} dValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.dValue = 0; - - /** - * VariantValue fValue. - * @member {number} fValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.fValue = 0; - - /** - * VariantValue ui64Value. - * @member {number|Long} ui64Value - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.ui64Value = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - - /** - * VariantValue i64Value. - * @member {number|Long} i64Value - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.i64Value = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * VariantValue uiValue. - * @member {number} uiValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.uiValue = 0; - - /** - * VariantValue iValue. - * @member {number} iValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.iValue = 0; - - /** - * VariantValue usValue. - * @member {number} usValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.usValue = 0; - - /** - * VariantValue sValue. - * @member {number} sValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.sValue = 0; - - /** - * VariantValue ucValue. - * @member {number} ucValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.ucValue = 0; - - /** - * VariantValue cValue. - * @member {number} cValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.cValue = 0; - - /** - * VariantValue bValue. - * @member {boolean} bValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.bValue = false; - - /** - * VariantValue strValue. - * @member {string} strValue - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.strValue = ""; - - /** - * VariantValue timestamp. - * @member {number} timestamp - * @memberof ICD.Protobuf.VariantValue - * @instance - */ - VariantValue.prototype.timestamp = 0; - - /** - * Creates a new VariantValue instance using the specified properties. - * @function create - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {ICD.Protobuf.IVariantValue=} [properties] Properties to set - * @returns {ICD.Protobuf.VariantValue} VariantValue instance - */ - VariantValue.create = function create(properties) { - return new VariantValue(properties); - }; - - /** - * Encodes the specified VariantValue message. Does not implicitly {@link ICD.Protobuf.VariantValue.verify|verify} messages. - * @function encode - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {ICD.Protobuf.IVariantValue} message VariantValue message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VariantValue.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.nodeId != null && Object.hasOwnProperty.call(message, "nodeId")) - writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.nodeId); - if (message.dValue != null && Object.hasOwnProperty.call(message, "dValue")) - writer.uint32(/* id 2, wireType 1 =*/17).double(message.dValue); - if (message.fValue != null && Object.hasOwnProperty.call(message, "fValue")) - writer.uint32(/* id 3, wireType 5 =*/29).float(message.fValue); - if (message.ui64Value != null && Object.hasOwnProperty.call(message, "ui64Value")) - writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.ui64Value); - if (message.i64Value != null && Object.hasOwnProperty.call(message, "i64Value")) - writer.uint32(/* id 5, wireType 0 =*/40).sint64(message.i64Value); - if (message.uiValue != null && Object.hasOwnProperty.call(message, "uiValue")) - writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.uiValue); - if (message.iValue != null && Object.hasOwnProperty.call(message, "iValue")) - writer.uint32(/* id 7, wireType 0 =*/56).sint32(message.iValue); - if (message.usValue != null && Object.hasOwnProperty.call(message, "usValue")) - writer.uint32(/* id 8, wireType 0 =*/64).uint32(message.usValue); - if (message.sValue != null && Object.hasOwnProperty.call(message, "sValue")) - writer.uint32(/* id 9, wireType 0 =*/72).sint32(message.sValue); - if (message.ucValue != null && Object.hasOwnProperty.call(message, "ucValue")) - writer.uint32(/* id 10, wireType 0 =*/80).uint32(message.ucValue); - if (message.cValue != null && Object.hasOwnProperty.call(message, "cValue")) - writer.uint32(/* id 11, wireType 0 =*/88).sint32(message.cValue); - if (message.bValue != null && Object.hasOwnProperty.call(message, "bValue")) - writer.uint32(/* id 12, wireType 0 =*/96).bool(message.bValue); - if (message.strValue != null && Object.hasOwnProperty.call(message, "strValue")) - writer.uint32(/* id 13, wireType 2 =*/106).string(message.strValue); - if (message.timestamp != null && Object.hasOwnProperty.call(message, "timestamp")) - writer.uint32(/* id 14, wireType 1 =*/113).double(message.timestamp); - return writer; - }; - - /** - * Encodes the specified VariantValue message, length delimited. Does not implicitly {@link ICD.Protobuf.VariantValue.verify|verify} messages. - * @function encodeDelimited - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {ICD.Protobuf.IVariantValue} message VariantValue message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - VariantValue.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a VariantValue message from the specified reader or buffer. - * @function decode - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {ICD.Protobuf.VariantValue} VariantValue - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VariantValue.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.ICD.Protobuf.VariantValue(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.nodeId = reader.uint32(); - break; - } - case 2: { - message.dValue = reader.double(); - break; - } - case 3: { - message.fValue = reader.float(); - break; - } - case 4: { - message.ui64Value = reader.uint64(); - break; - } - case 5: { - message.i64Value = reader.sint64(); - break; - } - case 6: { - message.uiValue = reader.uint32(); - break; - } - case 7: { - message.iValue = reader.sint32(); - break; - } - case 8: { - message.usValue = reader.uint32(); - break; - } - case 9: { - message.sValue = reader.sint32(); - break; - } - case 10: { - message.ucValue = reader.uint32(); - break; - } - case 11: { - message.cValue = reader.sint32(); - break; - } - case 12: { - message.bValue = reader.bool(); - break; - } - case 13: { - message.strValue = reader.string(); - break; - } - case 14: { - message.timestamp = reader.double(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a VariantValue message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {ICD.Protobuf.VariantValue} VariantValue - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - VariantValue.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a VariantValue message. - * @function verify - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - VariantValue.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.nodeId != null && message.hasOwnProperty("nodeId")) - if (!$util.isInteger(message.nodeId)) - return "nodeId: integer expected"; - if (message.dValue != null && message.hasOwnProperty("dValue")) - if (typeof message.dValue !== "number") - return "dValue: number expected"; - if (message.fValue != null && message.hasOwnProperty("fValue")) - if (typeof message.fValue !== "number") - return "fValue: number expected"; - if (message.ui64Value != null && message.hasOwnProperty("ui64Value")) - if (!$util.isInteger(message.ui64Value) && !(message.ui64Value && $util.isInteger(message.ui64Value.low) && $util.isInteger(message.ui64Value.high))) - return "ui64Value: integer|Long expected"; - if (message.i64Value != null && message.hasOwnProperty("i64Value")) - if (!$util.isInteger(message.i64Value) && !(message.i64Value && $util.isInteger(message.i64Value.low) && $util.isInteger(message.i64Value.high))) - return "i64Value: integer|Long expected"; - if (message.uiValue != null && message.hasOwnProperty("uiValue")) - if (!$util.isInteger(message.uiValue)) - return "uiValue: integer expected"; - if (message.iValue != null && message.hasOwnProperty("iValue")) - if (!$util.isInteger(message.iValue)) - return "iValue: integer expected"; - if (message.usValue != null && message.hasOwnProperty("usValue")) - if (!$util.isInteger(message.usValue)) - return "usValue: integer expected"; - if (message.sValue != null && message.hasOwnProperty("sValue")) - if (!$util.isInteger(message.sValue)) - return "sValue: integer expected"; - if (message.ucValue != null && message.hasOwnProperty("ucValue")) - if (!$util.isInteger(message.ucValue)) - return "ucValue: integer expected"; - if (message.cValue != null && message.hasOwnProperty("cValue")) - if (!$util.isInteger(message.cValue)) - return "cValue: integer expected"; - if (message.bValue != null && message.hasOwnProperty("bValue")) - if (typeof message.bValue !== "boolean") - return "bValue: boolean expected"; - if (message.strValue != null && message.hasOwnProperty("strValue")) - if (!$util.isString(message.strValue)) - return "strValue: string expected"; - if (message.timestamp != null && message.hasOwnProperty("timestamp")) - if (typeof message.timestamp !== "number") - return "timestamp: number expected"; - return null; - }; - - /** - * Creates a VariantValue message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {Object.} object Plain object - * @returns {ICD.Protobuf.VariantValue} VariantValue - */ - VariantValue.fromObject = function fromObject(object) { - if (object instanceof $root.ICD.Protobuf.VariantValue) - return object; - var message = new $root.ICD.Protobuf.VariantValue(); - if (object.nodeId != null) - message.nodeId = object.nodeId >>> 0; - if (object.dValue != null) - message.dValue = Number(object.dValue); - if (object.fValue != null) - message.fValue = Number(object.fValue); - if (object.ui64Value != null) - if ($util.Long) - (message.ui64Value = $util.Long.fromValue(object.ui64Value)).unsigned = true; - else if (typeof object.ui64Value === "string") - message.ui64Value = parseInt(object.ui64Value, 10); - else if (typeof object.ui64Value === "number") - message.ui64Value = object.ui64Value; - else if (typeof object.ui64Value === "object") - message.ui64Value = new $util.LongBits(object.ui64Value.low >>> 0, object.ui64Value.high >>> 0).toNumber(true); - if (object.i64Value != null) - if ($util.Long) - (message.i64Value = $util.Long.fromValue(object.i64Value)).unsigned = false; - else if (typeof object.i64Value === "string") - message.i64Value = parseInt(object.i64Value, 10); - else if (typeof object.i64Value === "number") - message.i64Value = object.i64Value; - else if (typeof object.i64Value === "object") - message.i64Value = new $util.LongBits(object.i64Value.low >>> 0, object.i64Value.high >>> 0).toNumber(); - if (object.uiValue != null) - message.uiValue = object.uiValue >>> 0; - if (object.iValue != null) - message.iValue = object.iValue | 0; - if (object.usValue != null) - message.usValue = object.usValue >>> 0; - if (object.sValue != null) - message.sValue = object.sValue | 0; - if (object.ucValue != null) - message.ucValue = object.ucValue >>> 0; - if (object.cValue != null) - message.cValue = object.cValue | 0; - if (object.bValue != null) - message.bValue = Boolean(object.bValue); - if (object.strValue != null) - message.strValue = String(object.strValue); - if (object.timestamp != null) - message.timestamp = Number(object.timestamp); - return message; - }; - - /** - * Creates a plain object from a VariantValue message. Also converts values to other types if specified. - * @function toObject - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {ICD.Protobuf.VariantValue} message VariantValue - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - VariantValue.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.nodeId = 0; - object.dValue = 0; - object.fValue = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.ui64Value = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.ui64Value = options.longs === String ? "0" : 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.i64Value = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.i64Value = options.longs === String ? "0" : 0; - object.uiValue = 0; - object.iValue = 0; - object.usValue = 0; - object.sValue = 0; - object.ucValue = 0; - object.cValue = 0; - object.bValue = false; - object.strValue = ""; - object.timestamp = 0; - } - if (message.nodeId != null && message.hasOwnProperty("nodeId")) - object.nodeId = message.nodeId; - if (message.dValue != null && message.hasOwnProperty("dValue")) - object.dValue = options.json && !isFinite(message.dValue) ? String(message.dValue) : message.dValue; - if (message.fValue != null && message.hasOwnProperty("fValue")) - object.fValue = options.json && !isFinite(message.fValue) ? String(message.fValue) : message.fValue; - if (message.ui64Value != null && message.hasOwnProperty("ui64Value")) - if (typeof message.ui64Value === "number") - object.ui64Value = options.longs === String ? String(message.ui64Value) : message.ui64Value; - else - object.ui64Value = options.longs === String ? $util.Long.prototype.toString.call(message.ui64Value) : options.longs === Number ? new $util.LongBits(message.ui64Value.low >>> 0, message.ui64Value.high >>> 0).toNumber(true) : message.ui64Value; - if (message.i64Value != null && message.hasOwnProperty("i64Value")) - if (typeof message.i64Value === "number") - object.i64Value = options.longs === String ? String(message.i64Value) : message.i64Value; - else - object.i64Value = options.longs === String ? $util.Long.prototype.toString.call(message.i64Value) : options.longs === Number ? new $util.LongBits(message.i64Value.low >>> 0, message.i64Value.high >>> 0).toNumber() : message.i64Value; - if (message.uiValue != null && message.hasOwnProperty("uiValue")) - object.uiValue = message.uiValue; - if (message.iValue != null && message.hasOwnProperty("iValue")) - object.iValue = message.iValue; - if (message.usValue != null && message.hasOwnProperty("usValue")) - object.usValue = message.usValue; - if (message.sValue != null && message.hasOwnProperty("sValue")) - object.sValue = message.sValue; - if (message.ucValue != null && message.hasOwnProperty("ucValue")) - object.ucValue = message.ucValue; - if (message.cValue != null && message.hasOwnProperty("cValue")) - object.cValue = message.cValue; - if (message.bValue != null && message.hasOwnProperty("bValue")) - object.bValue = message.bValue; - if (message.strValue != null && message.hasOwnProperty("strValue")) - object.strValue = message.strValue; - if (message.timestamp != null && message.hasOwnProperty("timestamp")) - object.timestamp = options.json && !isFinite(message.timestamp) ? String(message.timestamp) : message.timestamp; - return object; - }; - - /** - * Converts this VariantValue to JSON. - * @function toJSON - * @memberof ICD.Protobuf.VariantValue - * @instance - * @returns {Object.} JSON object - */ - VariantValue.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for VariantValue - * @function getTypeUrl - * @memberof ICD.Protobuf.VariantValue - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - VariantValue.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/ICD.Protobuf.VariantValue"; - }; - - return VariantValue; - })(); - - return Protobuf; - })(); - - return ICD; -})(); - -module.exports = $root; diff --git a/logger/client.js b/logger/logger-client.js similarity index 93% rename from logger/client.js rename to logger/logger-client.js index a12e4c4..3f6c6b4 100644 --- a/logger/client.js +++ b/logger/logger-client.js @@ -1,16 +1,22 @@ // Environment detection and dependency loading -let root; // protobuf definitions let WS; // WebSocket constructor +let root; // protobuf root namespace if (typeof window === 'undefined') { // ---- Node / CommonJS ---- - root = require('./generated/containerPb.js'); - WS = global.WebSocket || require('ws'); + WS = global.WebSocket || require('ws'); global.WebSocket = WS; // make sure anything else sees it + var protobuf = require('protobufjs'); + root = protobuf.parse(require('./variant.proto.js')).root; + protobuf.parse(require('./database.proto.js'), root); + protobuf.parse(require('./container.proto.js'), root); } else { // ---- Browser ---- - root = window.root; // injected by